VERSION = 2
PATCHLEVEL = 1
-SUBLEVEL = 94
+SUBLEVEL = 95
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <asm/system.h>
{
struct pci_bus *bus;
unsigned short cmd;
- unsigned int base, mask, size, off;
+ unsigned int base, mask, size, off, idx;
unsigned int alignto;
unsigned long handle;
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
- for (off = PCI_BASE_ADDRESS_0; off <= PCI_BASE_ADDRESS_5; off += 4) {
+ for (idx = 0; idx <= 5; idx++) {
+ off = PCI_BASE_ADDRESS_0 + 4*idx;
/*
* Figure out how much space and of what type this
* device wants.
pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
if (!base) {
/* this base-address register is unused */
- dev->base_address[PCI_BASE_INDEX(off)] = 0;
+ dev->base_address[idx] = 0;
continue;
}
off, base | 0x1);
handle = HANDLE(bus->number) | base | 1;
- dev->base_address[PCI_BASE_INDEX(off)] = handle;
+ dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
dev->device, handle, size));
"slot %d, function %d: \n",
PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn));
- off += 4; /* skip extra 4 bytes */
+ idx++; /* skip extra 4 bytes */
continue;
case PCI_BASE_ADDRESS_MEM_TYPE_1M:
__initfunc(void pcibios_fixup(void))
{
struct pci_dev *dev;
- int i, has_io;
+ int i, has_io, has_mem;
+ unsigned short cmd;
+ unsigned char pin;
for(dev = pci_devices; dev; dev=dev->next) {
/*
- * There are probably some buggy BIOSes that forget to assign I/O port
- * addresses to several devices. We probably should assign new addresses
- * to such devices, but we need to gather some information first. [mj]
+ * There are buggy BIOSes that forget to enable I/O and memory
+ * access to PCI devices. We try to fix this, but we need to
+ * be sure that the BIOS didn't forget to assign an address
+ * to the device. [mj]
*/
- has_io = 0;
+ has_io = has_mem = 0;
for(i=0; i<6; i++) {
unsigned long a = dev->base_address[i];
if (a & PCI_BASE_ADDRESS_SPACE_IO) {
- has_io = 1;
+ has_io |= 1;
a &= PCI_BASE_ADDRESS_IO_MASK;
- if (!a || a == PCI_BASE_ADDRESS_IO_MASK)
+ if (!a || a == PCI_BASE_ADDRESS_IO_MASK) {
printk(KERN_WARNING "PCI: BIOS forgot to assign address #%d to device %02x:%02x,"
" please report to <mj@ucw.cz>\n", i, dev->bus->number, dev->devfn);
- }
+ has_io |= 2;
+ }
+ } else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+ has_mem = 1;
}
- /*
- * Check if the I/O space access is allowed. If not, moan loudly. [mj]
- */
- if (has_io) {
- unsigned short cmd;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (!(cmd & PCI_COMMAND_IO))
- printk(KERN_WARNING "PCI: BIOS forgot to enable I/O for device %02x:%02x,"
- " please report to <mj@ucw.cz>\n", dev->bus->number, dev->devfn);
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (has_io == 1 && !(cmd & PCI_COMMAND_IO)) {
+ printk("PCI: Enabling I/O for device %02x:%02x\n",
+ dev->bus->number, dev->devfn);
+ cmd |= PCI_COMMAND_IO;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
}
+ if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+ printk("PCI: Enabling memory for device %02x:%02x\n",
+ dev->bus->number, dev->devfn);
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
#ifdef __SMP__
/*
* Recalculate IRQ numbers if we use the I/O APIC
*/
{
- unsigned char pin;
int irq;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin) {
pin--; /* interrupt pins are numbered starting from 1 */
irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
}
#endif
/*
- * Fix out-of-range IRQ numbers.
+ * Fix out-of-range IRQ numbers and report bogus IRQ.
*/
if (dev->irq >= NR_IRQS)
dev->irq = 0;
+ if (pin && !dev->irq)
+ printk(KERN_WARNING "PCI: Bogus IRQ for device %02x:%02x [pin=%x], please report to <mj@ucw.cz>\n",
+ dev->bus->number, dev->devfn, pin);
}
}
{
if (!strncmp(str, "off", 3)) {
pci_probe = 0;
- return str+3;
+ return NULL;
}
#ifdef CONFIG_PCI_BIOS
else if (!strncmp(str, "bios", 4)) {
pci_probe = PCI_PROBE_BIOS;
- return str+4;
+ return NULL;
} else if (!strncmp(str, "nobios", 6)) {
pci_probe &= ~PCI_PROBE_BIOS;
- return str+6;
+ return NULL;
}
#endif
#ifdef CONFIG_PCI_DIRECT
else if (!strncmp(str, "conf1", 5)) {
pci_probe = PCI_PROBE_CONF1;
- return str+5;
+ return NULL;
}
else if (!strncmp(str, "conf2", 5)) {
pci_probe = PCI_PROBE_CONF2;
- return str+5;
+ return NULL;
}
#endif
return str;
global_irq_holder = cpu;
}
+#define EFLAGS_IF_SHIFT 9
+
/*
* A global "cli()" while in an interrupt context
* turns into just a local cli(). Interrupts
* should use spinlocks for the (very unlikely)
* case that they ever want to protect against
* each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
*/
void __global_cli(void)
{
- int cpu = smp_processor_id();
+ unsigned int flags;
- __cli();
- if (!local_irq_count[cpu])
- get_irqlock(cpu);
+ __save_flags(flags);
+ if (flags & (1 << EFLAGS_IF_SHIFT)) {
+ int cpu = smp_processor_id();
+ __cli();
+ if (!local_irq_count[cpu])
+ get_irqlock(cpu);
+ }
}
void __global_sti(void)
__sti();
}
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
unsigned long __global_save_flags(void)
{
- if (!local_irq_count[smp_processor_id()])
- return global_irq_holder == (unsigned char) smp_processor_id();
- else {
- unsigned long x;
- __save_flags(x);
- return x;
+ int retval;
+ int local_enabled;
+ unsigned long flags;
+
+ __save_flags(flags);
+ local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
+ /* default to local */
+ retval = 2 + local_enabled;
+
+ /* check for global flags if we're not in an interrupt */
+ if (!local_irq_count[smp_processor_id()]) {
+ if (local_enabled)
+ retval = 1;
+ if (global_irq_holder == (unsigned char) smp_processor_id())
+ retval = 0;
}
+ return retval;
}
void __global_restore_flags(unsigned long flags)
{
- if (!local_irq_count[smp_processor_id()]) {
- switch (flags) {
- case 0:
- __global_sti();
- break;
- case 1:
- __global_cli();
- break;
- default:
- printk("global_restore_flags: %08lx (%08lx)\n",
- flags, (&flags)[-1]);
- }
- } else
- __restore_flags(flags);
+ switch (flags) {
+ case 0:
+ __global_cli();
+ break;
+ case 1:
+ __global_sti();
+ break;
+ case 2:
+ __cli();
+ break;
+ case 3:
+ __sti();
+ break;
+ default:
+ printk("global_restore_flags: %08lx (%08lx)\n",
+ flags, (&flags)[-1]);
+ }
}
#endif
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- printk("INIT IRQ\n");
for (i=0; i<NR_IRQS; i++) {
irq_events[i] = 0;
disabled_irq[i] = 0;
}
msect = drive->mult_count;
- spin_lock_irqsave(&io_request_lock,flags);
read_next:
rq = HWGROUP(drive)->rq;
if (msect) {
goto read_next;
ide_set_handler (drive, &read_intr, WAIT_CMD);
}
- spin_unlock_irqrestore(&io_request_lock,flags);
}
/*
unsigned long flags;
int error = 0;
- spin_lock_irqsave(&io_request_lock,flags);
if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
#ifdef DEBUG
printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
error = 1;
out:
- spin_unlock_irqrestore(&io_request_lock,flags);
if (error)
ide_error(drive, "write_intr", stat);
unsigned long flags;
int error = 0;
- spin_lock_irqsave(&io_request_lock,flags);
if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
if (stat & DRQ_STAT) {
if (rq->nr_sectors) {
error = 1;
out:
- spin_unlock_irqrestore(&io_request_lock,flags);
if (error)
ide_error(drive, "multwrite_intr", stat);
#define IDE_IRQ_EQUAL(irq1, irq2) ((irq1) == (irq2))
#endif
-/*
- * entry point for all interrupts, caller does __cli() for us
- */
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = dev_id;
ide_sti(); HACK */
handler(drive);
/* this is necessary, as next rq may be different irq */
- spin_lock_irqsave(&io_request_lock,flags);
if (hwgroup->handler == NULL) {
set_recovery_timer(HWIF(drive));
drive->service_time = jiffies - drive->service_start;
ide_do_request(hwgroup);
}
- spin_unlock_irqrestore(&io_request_lock,flags);
} else {
unexpected_intr(irq, hwgroup);
}
} while ((hwif = hwif->next) != hwgroup->hwif);
}
+/*
+ * entry point for all interrupts, caller does __cli() for us
+ */
+void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ do_ide_intr(irq, dev_id, regs);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
/*
* get_info_ptr() returns the (ide_drive_t *) for a given device number.
* It returns NULL if the given device number does not match any present drives.
queue_new_request = 1;
}
}
- spin_unlock_irqrestore(&io_request_lock,flags);
-
if (queue_new_request)
/*
* request functions are smart enough to notice a change
* is OK, i think. <-- FIXME: [is this true? --mingo]
*/
(dev->request_fn)();
+
+ spin_unlock_irqrestore(&io_request_lock,flags);
}
/*
if (scsi_blk_major(MAJOR(req->rq_dev)))
queue_new_request = 1;
out:
- spin_unlock_irqrestore(&io_request_lock,flags);
-
/*
* request_fn() is usually a quite complex and slow function,
* we want to call it with no spinlocks held
*/
if (queue_new_request)
(dev->request_fn)();
+ spin_unlock_irqrestore(&io_request_lock,flags);
}
/*
tga_console_init(void))
{
struct pci_dev *dev;
- int status;
/*
* first, find the TGA among the PCI devices...
*/
- if (! (dev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL)))
+ if (! (dev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL))) {
/* PANIC!!! */
printk("tga_console_init: TGA not found!!! :-(\n");
return;
static int close_intr_election(long tmp)
{
int irq = PARPORT_IRQ_NONE;
- int i;
+ int i, valid = 1;
/* We ignore the timer - irq 0 */
for (i = 1; i < 16; i++)
if (intr_vote[i]) {
if (irq != PARPORT_IRQ_NONE)
/* More than one interrupt */
- return PARPORT_IRQ_NONE;
+ valid = 0;
irq = i;
}
free_irq(i, intr_vote);
}
- return irq;
+ if(valid)
+ return irq;
+ else
+ return PARPORT_IRQ_NONE;
}
/* Only if supports ECP mode */
if (check_region(pci_ioaddr, NE_IO_EXTENT))
continue;
pci_irq_line = pdev->irq;
- if (pci_irq_line == 0) continue; /* Try next PCI ID */
+ if (pci_irq_line) break; /* Found it */
}
if (!pdev)
continue;
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
#include <asm/page.h>
#ifdef CONFIG_PROC_FS
return len;
}
+static struct proc_dir_entry proc_old_pci = {
+ PROC_PCI, 3, "pci",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations
+};
+
+__initfunc(void proc_old_pci_init(void))
+{
+ proc_register(&proc_root, &proc_old_pci);
+}
+
#endif /* CONFIG_PROC_FS */
struct pci_bus pci_root;
struct pci_dev *pci_devices = NULL;
static struct pci_dev **pci_last_dev_p = &pci_devices;
+static int pci_reverse __initdata = 0;
#undef DEBUG
* Put it into the global PCI device chain. It's used to
* find devices once everything is set up.
*/
- *pci_last_dev_p = dev;
- pci_last_dev_p = &dev->next;
+ if (!pci_reverse) {
+ *pci_last_dev_p = dev;
+ pci_last_dev_p = &dev->next;
+ } else {
+ dev->next = pci_devices;
+ pci_devices = dev;
+ }
/*
* Now insert it into the list of devices held
dev->sibling = bus->devices;
bus->devices = dev;
+ /*
+ * In case the latency timer value is less than 32,
+ * which makes everything very sllooowww, set it to
+ * 32. Pciutils should be used to fine-tune it later.
+ * Note that we don't check if the device is a bus-master:
+ * if it isn't, write to the latency timer should be ignored.
+ */
+ pcibios_read_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, &tmp);
+ if (tmp < 32)
+ pcibios_write_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, 32);
+
/*
* If it's a bridge, scan the bus behind it.
*/
if (!pci_present()) {
printk("PCI: No PCI bus detected\n");
+ return;
}
printk("PCI: Probing PCI hardware.\n");
#ifdef CONFIG_PCI_OPTIMIZE
pci_quirks_init();
#endif
+
+#ifdef CONFIG_PROC_FS
+ proc_bus_pci_init();
+#ifdef CONFIG_PCI_OLD_PROC
+ proc_old_pci_init();
+#endif
+#endif
}
__initfunc(void pci_setup (char *str, int *ints))
{
str = pcibios_setup(str);
- if (*str)
- printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+ while (str) {
+ char *k = strchr(str, ',');
+ if (k)
+ *k++ = 0;
+ if (*str) {
+ if (!(str = pcibios_setup(str)) || !*str)
+ continue;
+ if (!strcmp(str, "reverse"))
+ pci_reverse = 1;
+ else printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+ }
+ str = k;
+ }
}
#include <linux/stat.h>
#include <linux/pci.h>
#include <linux/bios32.h>
+
+#include <linux/blk.h>
+
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
Adapters.
*/
-
-static void BusLogic_InterruptHandler(int IRQ_Channel,
+static void do_BusLogic_InterruptHandler(int IRQ_Channel,
void *DeviceIdentifier,
Registers_T *InterruptRegisters)
{
}
}
+/*
+ * This is the low-level interrupt handler:
+ * we get the io request lock here to guarantee
+ * that all of this is atomic wrt the setup
+ * functions.
+ */
+static void BusLogic_InterruptHandler(int IRQ_Channel,
+ void *DeviceIdentifier,
+ Registers_T *InterruptRegisters)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ do_BusLogic_InterruptHandler(IRQ_Channel, DeviceIdentifier, InterruptRegisters);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
/*
BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
struct ecb *ecbptr;
Scsi_Cmnd *SCtmp;
unsigned int base;
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
if (!aha_host[irq - 9])
panic("aha1740.c: Irq from unknown host!\n");
}
number_serviced++;
}
+
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
#if LINUX_VERSION_CODE >= LinuxVersionCode(1,3,70)
static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
{
+ unsigned long flags;
+
#ifdef DEBUG_NCR53C8XX
printk("ncr53c8xx : interrupt received\n");
#endif
if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
+ spin_lock_irqsave(&io_request_lock, flags);
ncr_exception((ncb_p) dev_id);
+ spin_unlock_irqrestore(&io_request_lock, flags);
if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
}
*/
- spin_lock_irqsave(&io_request_lock, flags);
host_active = NULL;
for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) {
sh[index]->host_no);
}
- spin_unlock_irqrestore(&io_request_lock, flags);
}
static void scan_scsis_done (Scsi_Cmnd * SCpnt)
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ spin_lock_irq(&io_request_lock);
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
(void *) scsi_result,
256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
+ spin_unlock_irq(&io_request_lock);
down (&sem);
SCpnt->request.sem = NULL;
}
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.sem = &sem;
SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ spin_lock_irq(&io_request_lock);
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
(void *) scsi_result,
256, scan_scsis_done, SCSI_TIMEOUT, 3);
+ spin_unlock_irq(&io_request_lock);
down (&sem);
SCpnt->request.sem = NULL;
}
struct semaphore sem = MUTEX_LOCKED;
SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->request.sem = &sem;
+ spin_lock_irq(&io_request_lock);
scsi_do_cmd (SCpnt, (void *) scsi_cmd,
(void *) scsi_result, 0x2a,
scan_scsis_done, SCSI_TIMEOUT, 3);
+ spin_unlock_irq(&io_request_lock);
down (&sem);
SCpnt->request.sem = NULL;
}
SCpnt = found;
}
- __save_flags(flags);
- __cli();
/* See if this request has already been queued by an interrupt routine
*/
if (req && (req->rq_status == RQ_INACTIVE || req->rq_dev != dev)) {
- __restore_flags(flags);
return NULL;
}
if (!SCpnt || SCpnt->request.rq_status != RQ_INACTIVE) /* Might have changed */
{
if (wait && SCwait && SCwait->request.rq_status != RQ_INACTIVE){
+ spin_unlock(&io_request_lock); /* FIXME!!!! */
sleep_on(&device->device_wait);
- __restore_flags(flags);
+ spin_lock_irq(&io_request_lock); /* FIXME!!!! */
} else {
- __restore_flags(flags);
if (!wait) return NULL;
if (!SCwait) {
printk("Attempt to allocate device channel %d,"
* to complete */
}
atomic_inc(&SCpnt->host->host_active);
- __restore_flags(flags);
SCSI_LOG_MLQUEUE(5, printk("Activating command for device %d (%d)\n",
SCpnt->target,
atomic_read(&SCpnt->host->host_active)));
host = SCpnt->host;
- spin_lock_irqsave(&io_request_lock, flags);
/* Assign a unique nonzero serial_number. */
if (++serial_number == 0) serial_number = 1;
SCpnt->serial_number = serial_number;
* we can avoid the drive not being ready.
*/
timeout = host->last_reset + MIN_RESET_DELAY;
- spin_unlock(&io_request_lock);
if (jiffies < timeout) {
int ticks_remaining = timeout - jiffies;
* interrupt handler (assuming there is one irq-level per
* host).
*/
- __sti();
+ spin_unlock_irq(&io_request_lock);
while (--ticks_remaining >= 0) udelay(1000000/HZ);
host->last_reset = jiffies - MIN_RESET_DELAY;
+ spin_lock_irq(&io_request_lock);
}
- __restore_flags(flags); /* this possibly puts us back into __cli() */
if( host->hostt->use_new_eh_code )
{
{
SCSI_LOG_MLQUEUE(3,printk("queuecommand : routine at %p\n",
host->hostt->queuecommand));
- /* This locking tries to prevent all sorts of races between
- * queuecommand and the interrupt code. In effect,
- * we are only allowed to be in queuecommand once at
- * any given time, and we can only be in the interrupt
- * handler and the queuecommand function at the same time
- * when queuecommand is called while servicing the
- * interrupt.
- */
-
- if(!in_interrupt() && SCpnt->host->irq)
- disable_irq(SCpnt->host->irq);
-
/*
* Use the old error handling code if we haven't converted the driver
* to use the new one yet. Note - only the new queuecommand variant
{
host->hostt->queuecommand (SCpnt, scsi_old_done);
}
-
- if(!in_interrupt() && SCpnt->host->irq)
- enable_irq(SCpnt->host->irq);
}
else
{
* ourselves.
*/
- spin_lock_irqsave(&io_request_lock, flags);
SCpnt->pid = scsi_pid++;
while (SCSI_BLOCK((Scsi_Device *) NULL, host)) {
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock(&io_request_lock); /* FIXME!!! */
SCSI_SLEEP(&host->host_wait, SCSI_BLOCK((Scsi_Device *) NULL, host));
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irq(&io_request_lock); /* FIXME!!! */
}
if (host->block) host_active = host;
host->host_busy++;
device->device_busy++;
- spin_unlock_irqrestore(&io_request_lock, flags);
/*
* Our own function scsi_done (which marks the host as not busy, disables
if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
return NULL;
- spin_lock_irqsave(&io_request_lock, flags);
nbits = len >> 9;
mask = (1 << nbits) - 1;
for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){
if ((dma_malloc_freelist[i] & (mask << j)) == 0){
dma_malloc_freelist[i] |= (mask << j);
- spin_unlock_irqrestore(&io_request_lock, flags);
scsi_dma_free_sectors -= nbits;
#ifdef DEBUG
SCSI_LOG_MLQUEUE(3,printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9)));
return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
}
}
- spin_unlock_irqrestore(&io_request_lock, flags);
return NULL; /* Nope. No more */
}
if ((mask << sector) >= (1 << SECTORS_PER_PAGE))
panic ("scsi_free:Bad memory alignment");
- spin_lock_irqsave(&io_request_lock, flags);
if((dma_malloc_freelist[page] &
(mask << sector)) != (mask<<sector)){
- spin_unlock_irqrestore(&io_request_lock, flags);
#ifdef DEBUG
printk("scsi_free(obj=%p, len=%d) called from %08lx\n",
obj, len, ret);
#endif
panic("scsi_free:Trying to free unused memory");
- spin_lock_irqsave(&io_request_lock, flags);
}
scsi_dma_free_sectors += nbits;
dma_malloc_freelist[page] &= ~(mask << sector);
- spin_unlock_irqrestore(&io_request_lock, flags);
return 0;
}
}
/* When we dick with the actual DMA list, we need to
* protect things
*/
- spin_lock_irqsave(&io_request_lock, flags);
if (dma_malloc_freelist)
{
size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
dma_malloc_pages = new_dma_malloc_pages;
dma_sectors = new_dma_sectors;
scsi_need_isa_buffer = new_need_isa_buffer;
- spin_unlock_irqrestore(&io_request_lock, flags);
#ifdef DEBUG_INIT
printk("resize_dma_pool: dma free sectors = %d\n", scsi_dma_free_sectors);
{
online_status = SDpnt->online;
SDpnt->online = FALSE;
- spin_lock_irqsave(&io_request_lock, flags);
if(SCpnt->request.rq_status != RQ_INACTIVE)
{
- spin_unlock_irqrestore(&io_request_lock, flags);
printk("SCSI device not inactive - state=%d, id=%d\n",
SCpnt->request.rq_status, SCpnt->target);
for(SDpnt1 = shpnt->host_queue; SDpnt1;
*/
SCpnt->state = SCSI_STATE_DISCONNECTING;
SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */
- spin_unlock_irqrestore(&io_request_lock, flags);
}
}
}
#define INIT_SCSI_REQUEST \
if (!CURRENT) { \
CLEAR_INTR; \
- spin_unlock_irqrestore(&io_request_lock,flags); \
return; \
} \
if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
#include <linux/errno.h>
#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <asm/smp_lock.h>
+
#include <asm/system.h>
#include <asm/io.h>
Scsi_Cmnd * SCpnt = NULL;
Scsi_Device * SDev;
struct request * req = NULL;
- unsigned long flags;
int flag = 0;
while (1==1){
- spin_lock_irqsave(&io_request_lock, flags);
-
if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) {
- spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
*/
if( SDev->host->in_recovery )
{
- spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
*/
if( SDev->removable && !in_interrupt() )
{
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irq(&io_request_lock); /* FIXME!!!! */
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
/* scsi_ioctl may allow CURRENT to change, so start over. */
SDev->was_reset = 0;
+ spin_lock_irq(&io_request_lock); /* FIXME!!!! */
continue;
}
SDev->was_reset = 0;
* Using a "sti()" gets rid of the latency problems but causes
* race conditions and crashes.
*/
- spin_unlock_irqrestore(&io_request_lock, flags);
/* This is a performance enhancement. We dig down into the request
* list and try to find a queueable request (i.e. device not busy,
if (!SCpnt && sd_template.nr_dev > 1){
struct request *req1;
req1 = NULL;
- spin_lock_irqsave(&io_request_lock, flags);
req = CURRENT;
while(req){
SCpnt = scsi_request_queueable(req,
else
req1->next = req->next;
}
- spin_unlock_irqrestore(&io_request_lock, flags);
}
if (!SCpnt) return; /* Could not find anything to do */
return i;
}
+ spin_lock_irq(&io_request_lock);
+
/* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is
* considered a fatal error, and many devices report such an error
* just after a scsi bus reset.
(void *) cmd, (void *) buffer,
512, sd_init_done, SD_TIMEOUT,
MAX_RETRIES);
+ spin_unlock_irq(&io_request_lock);
down(&sem);
+ spin_lock_irq(&io_request_lock);
SCpnt->request.sem = NULL;
}
(void *) cmd, (void *) buffer,
512, sd_init_done, SD_TIMEOUT,
MAX_RETRIES);
+ spin_unlock_irq(&io_request_lock);
down(&sem);
+ spin_lock_irq(&io_request_lock);
SCpnt->request.sem = NULL;
}
}
time1 = jiffies + HZ;
+ spin_unlock_irq(&io_request_lock);
while(jiffies < time1); /* Wait 1 second for next try */
printk( "." );
+ spin_lock_irq(&io_request_lock);
}
} while(the_result && spintime && spintime+100*HZ > jiffies);
if (spintime) {
(void *) cmd, (void *) buffer,
8, sd_init_done, SD_TIMEOUT,
MAX_RETRIES);
+ spin_unlock_irq(&io_request_lock);
down(&sem); /* sleep until it is ready */
+ spin_lock_irq(&io_request_lock);
SCpnt->request.sem = NULL;
}
(void *) cmd, (void *) buffer,
512, sd_init_done, SD_TIMEOUT,
MAX_RETRIES);
+ spin_unlock_irq(&io_request_lock);
down(&sem);
+ spin_lock_irq(&io_request_lock);
SCpnt->request.sem = NULL;
}
rscsi_disks[i].ten = 1;
rscsi_disks[i].remap = 1;
scsi_free(buffer, 512);
+ spin_unlock_irq(&io_request_lock);
return i;
}
int revalidate_scsidisk(kdev_t dev, int maxusage){
int target;
struct gendisk * gdev;
- unsigned long flags;
int max_p;
int start;
int i;
target = DEVICE_NR(dev);
gdev = &GENDISK_STRUCT;
- spin_lock_irqsave(&io_request_lock, flags);
if (DEVICE_BUSY || USAGE > maxusage) {
- spin_unlock_irqrestore(&io_request_lock, flags);
printk("Device busy for revalidation (usage=%d)\n", USAGE);
return -EBUSY;
}
DEVICE_BUSY = 1;
- spin_unlock_irqrestore(&io_request_lock, flags);
max_p = gdev->max_p;
start = target << gdev->minor_shift;
/*
* Wait until the command is actually done.
*/
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&io_request_lock, flags);
while(!device->pending || !device->complete)
{
if (filp->f_flags & O_NONBLOCK)
{
- restore_flags(flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return -EAGAIN;
}
interruptible_sleep_on(&device->read_wait);
if (signal_pending(current))
{
- restore_flags(flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
return -ERESTARTSYS;
}
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&io_request_lock, flags);
/*
* Now copy the result back to the user buffer.
int flag = 0;
while (1==1){
- spin_lock_irqsave(&io_request_lock, flags);
-
if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) {
- spin_unlock_irqrestore(&io_request_lock, flags);
return;
};
*/
if( SDev->host->in_recovery )
{
- spin_unlock_irqrestore(&io_request_lock, flags);
return;
}
*/
if( SDev->removable && !in_interrupt() )
{
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irq(&io_request_lock); /* FIXME!!!! */
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
+ spin_lock_irq(&io_request_lock); /* FIXME!!!! */
/* scsi_ioctl may allow CURRENT to change, so start over. */
SDev->was_reset = 0;
continue;
SCpnt = scsi_allocate_device(&CURRENT,
scsi_CDs[DEVICE_NR(CURRENT->rq_dev)].device, 0);
else SCpnt = NULL;
- spin_unlock_irqrestore(&io_request_lock, flags);
/* This is a performance enhancement. We dig down into the request list and
* try to find a queueable request (i.e. device not busy, and host able to
if (!SCpnt && sr_template.nr_dev > 1){
struct request *req1;
req1 = NULL;
- spin_lock_irqsave(&io_request_lock, flags);
req = CURRENT;
while(req){
SCpnt = scsi_request_queueable(req,
else
req1->next = req->next;
}
- spin_unlock_irqrestore(&io_request_lock, flags);
}
if (!SCpnt)
error = -ENOENT;
/* Has the current directory has been unlinked? */
- if (pwd->d_parent != pwd && list_empty(&pwd->d_hash)) {
+ if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash)) {
char *page = (char *) __get_free_page(GFP_USER);
error = -ENOMEM;
if (page) {
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
-#ifdef CONFIG_PCI_OLD_PROC
-static struct proc_dir_entry proc_root_pci = {
- PROC_PCI, 3, "pci",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, &proc_array_inode_operations
-};
-#endif
#ifdef CONFIG_ZORRO
static struct proc_dir_entry proc_root_zorro = {
PROC_ZORRO, 5, "zorro",
proc_register(&proc_root, &proc_root_meminfo);
proc_register(&proc_root, &proc_root_kmsg);
proc_register(&proc_root, &proc_root_version);
-#ifdef CONFIG_PCI_OLD_PROC
- proc_register(&proc_root, &proc_root_pci);
-#endif
#ifdef CONFIG_ZORRO
proc_register(&proc_root, &proc_root_zorro);
#endif
#endif
proc_bus = create_proc_entry("bus", S_IFDIR, 0);
-#ifdef CONFIG_PCI
- proc_bus_pci_init();
-#endif
}
/*
#ifdef __KERNEL__
-/* Create an index into the pci_dev base_address[] array from an offset. */
-#define PCI_BASE_INDEX(o) (((o)-PCI_BASE_ADDRESS_0)>>2)
-
/*
* Error values that may be returned by the PCI bios. Use
* pcibios_strerror() to convert to a printable string.
void pci_setup(char *str, int *ints);
void pci_quirks_init(void);
unsigned int pci_scan_bus(struct pci_bus *bus);
+void proc_bus_pci_init(void);
+void proc_old_pci_init(void);
struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
extern void proc_root_init(void);
extern void proc_base_init(void);
-extern void proc_bus_pci_init(void);
extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
extern int proc_unregister(struct proc_dir_entry *, int);