diff -u --recursive --new-file v2.1.94/linux/Makefile linux/Makefile --- v2.1.94/linux/Makefile Wed Apr 8 19:36:24 1998 +++ linux/Makefile Wed Apr 8 19:36:06 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 94 +SUBLEVEL = 95 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.94/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c --- v2.1.94/linux/arch/alpha/kernel/apecs.c Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/apecs.c Thu Apr 9 13:16:18 1998 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.94/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.94/linux/arch/alpha/kernel/bios32.c Wed Apr 8 19:36:24 1998 +++ linux/arch/alpha/kernel/bios32.c Thu Apr 9 13:16:18 1998 @@ -250,7 +250,7 @@ { 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; @@ -278,7 +278,8 @@ 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. @@ -288,7 +289,7 @@ 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; } @@ -324,7 +325,7 @@ 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)); @@ -348,7 +349,7 @@ "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: diff -u --recursive --new-file v2.1.94/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.1.94/linux/arch/i386/kernel/bios32.c Wed Apr 8 19:36:24 1998 +++ linux/arch/i386/kernel/bios32.c Thu Apr 9 13:16:18 1998 @@ -834,44 +834,52 @@ __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 \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 \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); @@ -884,10 +892,13 @@ } #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 \n", + dev->bus->number, dev->devfn, pin); } } @@ -919,25 +930,25 @@ { 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; diff -u --recursive --new-file v2.1.94/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.94/linux/arch/i386/kernel/irq.c Wed Apr 8 19:36:25 1998 +++ linux/arch/i386/kernel/irq.c Thu Apr 9 22:10:59 1998 @@ -537,20 +537,31 @@ 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) @@ -562,33 +573,53 @@ __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 @@ -1073,7 +1104,6 @@ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ - printk("INIT IRQ\n"); for (i=0; imult_count; - spin_lock_irqsave(&io_request_lock,flags); read_next: rq = HWGROUP(drive)->rq; if (msect) { @@ -152,7 +151,6 @@ goto read_next; ide_set_handler (drive, &read_intr, WAIT_CMD); } - spin_unlock_irqrestore(&io_request_lock,flags); } /* @@ -167,7 +165,6 @@ 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", @@ -192,7 +189,6 @@ error = 1; out: - spin_unlock_irqrestore(&io_request_lock,flags); if (error) ide_error(drive, "write_intr", stat); @@ -246,7 +242,6 @@ 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) { @@ -268,7 +263,6 @@ error = 1; out: - spin_unlock_irqrestore(&io_request_lock,flags); if (error) ide_error(drive, "multwrite_intr", stat); diff -u --recursive --new-file v2.1.94/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.94/linux/drivers/block/ide.c Mon Apr 6 17:40:59 1998 +++ linux/drivers/block/ide.c Thu Apr 9 15:42:07 1998 @@ -1265,10 +1265,7 @@ #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; @@ -1303,13 +1300,11 @@ 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); } @@ -1319,6 +1314,18 @@ if (!IDE_IRQ_EQUAL(hwif->irq, irq)) enable_irq(hwif->irq); } 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); } /* diff -u --recursive --new-file v2.1.94/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.1.94/linux/drivers/block/ll_rw_blk.c Mon Apr 6 17:40:59 1998 +++ linux/drivers/block/ll_rw_blk.c Thu Apr 9 13:44:53 1998 @@ -148,8 +148,6 @@ queue_new_request = 1; } } - spin_unlock_irqrestore(&io_request_lock,flags); - if (queue_new_request) /* * request functions are smart enough to notice a change @@ -157,6 +155,8 @@ * is OK, i think. <-- FIXME: [is this true? --mingo] */ (dev->request_fn)(); + + spin_unlock_irqrestore(&io_request_lock,flags); } /* @@ -348,14 +348,13 @@ 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); } /* diff -u --recursive --new-file v2.1.94/linux/drivers/char/tga.c linux/drivers/char/tga.c --- v2.1.94/linux/drivers/char/tga.c Mon Apr 6 17:40:59 1998 +++ linux/drivers/char/tga.c Thu Apr 9 13:10:15 1998 @@ -472,12 +472,11 @@ 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; diff -u --recursive --new-file v2.1.94/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.1.94/linux/drivers/misc/parport_pc.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/misc/parport_pc.c Fri Apr 10 10:10:31 1998 @@ -641,58 +641,6 @@ /* --- IRQ detection -------------------------------------- */ -/* This code is for detecting ECP interrupts (due to problems with the - * monolithic interrupt probing routines). - * - * In short this is a voting system where the interrupt with the most - * "votes" is the elected interrupt (it SHOULD work...) - * - * This is horribly x86-specific at the moment. I'm not convinced it - * belongs at all. - */ - -static int intr_vote[16]; - -static void parport_vote_intr_func(int irq, void *dev_id, struct pt_regs *regs) -{ - intr_vote[irq]++; - return; -} - -static long open_intr_election(void) -{ - long tmp = 0; - int i; - - /* We ignore the timer - irq 0 */ - for (i = 1; i < 16; i++) { - intr_vote[i] = 0; - if (request_irq(i, parport_vote_intr_func, - SA_INTERRUPT, "probe", intr_vote) == 0) - tmp |= 1 << i; - } - return tmp; -} - -static int close_intr_election(long tmp) -{ - int irq = PARPORT_IRQ_NONE; - int i; - - /* We ignore the timer - irq 0 */ - for (i = 1; i < 16; i++) - if (tmp & (1 << i)) { - if (intr_vote[i]) { - if (irq != PARPORT_IRQ_NONE) - /* More than one interrupt */ - return PARPORT_IRQ_NONE; - irq = i; - } - free_irq(i, intr_vote); - } - return irq; -} - /* Only if supports ECP mode */ static int programmable_irq_support(struct parport *pb) { @@ -714,20 +662,23 @@ static int irq_probe_ECP(struct parport *pb) { int irqs, i; - unsigned char oecr = parport_pc_read_econtrol(pb); - probe_irq_off(probe_irq_on()); /* Clear any interrupts */ - irqs = open_intr_election(); + sti(); + irqs = probe_irq_on(); - parport_pc_write_econtrol(pb, 0x00); /* Reset FIFO */ - parport_pc_write_econtrol(pb, 0xd0); /* TEST FIFO + nErrIntrEn */ + parport_pc_write_econtrol(pb, 0x00); /* Reset FIFO */ + parport_pc_write_econtrol(pb, 0xd0); /* TEST FIFO + nErrIntrEn */ /* If Full FIFO sure that WriteIntrThresold is generated */ for (i=0; i < 1024 && !(parport_pc_read_econtrol(pb) & 0x02) ; i++) parport_pc_write_fifo(pb, 0xaa); - pb->irq = close_intr_election(irqs); - parport_pc_write_econtrol(pb, oecr); + pb->irq = probe_irq_off(irqs); + parport_pc_write_econtrol(pb, 0x00); + + if (pb->irq <= 0) + pb->irq = PARPORT_IRQ_NONE; + return pb->irq; } @@ -745,26 +696,30 @@ return PARPORT_IRQ_NONE; #endif - probe_irq_off(probe_irq_on()); /* Clear any interrupts */ - irqs = open_intr_election(); + sti(); + irqs = probe_irq_on(); if (pb->modes & PARPORT_MODE_PCECR) - parport_pc_write_econtrol(pb, parport_pc_read_econtrol(pb) | 0x10); + parport_pc_frob_econtrol (pb, 0x10, 0x10); epp_clear_timeout(pb); - parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20); - parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10); + parport_pc_frob_control (pb, 0x20, 0x20); + parport_pc_frob_control (pb, 0x10, 0x10); epp_clear_timeout(pb); - /* Device isn't expecting an EPP read + /* Device isn't expecting an EPP read * and generates an IRQ. */ parport_pc_read_epp(pb); udelay(20); - pb->irq = close_intr_election(irqs); + pb->irq = probe_irq_off (irqs); parport_pc_write_econtrol(pb, oecr); parport_pc_write_control(pb, octr); + + if (pb->irq <= 0) + pb->irq = PARPORT_IRQ_NONE; + return pb->irq; } @@ -815,16 +770,19 @@ */ static int parport_irq_probe(struct parport *pb) { - if (pb->modes & PARPORT_MODE_PCECR) + unsigned char oecr = parport_pc_read_econtrol (pb); + + if (pb->modes & PARPORT_MODE_PCECR) { pb->irq = programmable_irq_support(pb); + if (pb->irq != PARPORT_IRQ_NONE) + goto out; + } if (pb->modes & PARPORT_MODE_PCECP) pb->irq = irq_probe_ECP(pb); - + if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_PCECPEPP)) { - unsigned char oecr = parport_pc_read_econtrol(pb); - parport_pc_write_econtrol(pb, 0x80); pb->irq = irq_probe_EPP(pb); parport_pc_write_econtrol(pb, oecr); } @@ -839,6 +797,8 @@ if (pb->irq == PARPORT_IRQ_NONE) pb->irq = irq_probe_SPP(pb); +out: + parport_pc_write_econtrol (pb, oecr); return pb->irq; } diff -u --recursive --new-file v2.1.94/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.1.94/linux/drivers/net/ne.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/net/ne.c Thu Apr 9 16:20:29 1998 @@ -215,7 +215,7 @@ 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; diff -u --recursive --new-file v2.1.94/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c --- v2.1.94/linux/drivers/pci/oldproc.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/pci/oldproc.c Thu Apr 9 13:16:18 1998 @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #ifdef CONFIG_PROC_FS @@ -910,6 +912,17 @@ len += nprinted; } 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 */ diff -u --recursive --new-file v2.1.94/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.94/linux/drivers/pci/pci.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/pci/pci.c Thu Apr 9 13:16:18 1998 @@ -20,6 +20,7 @@ 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 @@ -193,8 +194,13 @@ * 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 @@ -204,6 +210,17 @@ 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 (class >> 8 == PCI_CLASS_BRIDGE_PCI) { @@ -299,6 +316,7 @@ if (!pci_present()) { printk("PCI: No PCI bus detected\n"); + return; } printk("PCI: Probing PCI hardware.\n"); @@ -312,12 +330,30 @@ #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; + } } diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.1.94/linux/drivers/scsi/BusLogic.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/scsi/BusLogic.c Thu Apr 9 13:53:13 1998 @@ -42,6 +42,9 @@ #include #include #include + +#include + #include #include #include @@ -3267,8 +3270,7 @@ 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) { @@ -3375,6 +3377,22 @@ } } +/* + * 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 diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v2.1.94/linux/drivers/scsi/aha1740.c Thu Mar 27 14:40:05 1997 +++ linux/drivers/scsi/aha1740.c Thu Apr 9 13:47:16 1998 @@ -228,6 +228,9 @@ 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"); @@ -304,6 +307,8 @@ } number_serviced++; } + + spin_unlock_irqrestore(&io_request_lock, flags); } int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.1.94/linux/drivers/scsi/eata.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/eata.c Fri Apr 10 10:13:58 1998 @@ -1,6 +1,14 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 + * Improved SMP support (if linux version >= 2.1.95). + * + * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94 + * Added support for new PCI code and IO-APIC remapping of irqs. + * Performance improvement: when sequential i/o is detected, + * always use direct sort instead of reverse sort. + * * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 * io_port is now unsigned long. * @@ -280,11 +288,14 @@ * the driver sets host->wish_block = TRUE for all ISA boards. */ +#include + #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) #define MAX_INT_PARAM 10 + #if defined(MODULE) #include -#include + #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26) MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i"); MODULE_PARM(linked_comm, "i"); @@ -294,6 +305,7 @@ MODULE_PARM(tag_mode, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif + #endif #include @@ -314,9 +326,12 @@ #include "eata.h" #include #include -#include #include +#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93) +#include +#endif + #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36) #include #else @@ -338,6 +353,7 @@ #undef DEBUG_LINKED_COMMANDS #undef DEBUG_DETECT +#undef DEBUG_PCI_DETECT #undef DEBUG_INTERRUPT #undef DEBUG_RESET @@ -583,7 +599,7 @@ #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0) -static void eata2x_interrupt_handler(int, void *, struct pt_regs *); +static void interrupt_handler(int, void *, struct pt_regs *); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; static int setup_done = FALSE; @@ -715,10 +731,48 @@ return FALSE; } +__initfunc (static inline int + get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) { + +#if defined(CONFIG_PCI) + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) + + unsigned int addr; + struct pci_dev *dev = NULL; + + if (!pci_present()) return FALSE; + + while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { + + if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue; + +#if defined(DEBUG_PCI_DETECT) + printk("%s: get_pci_irq, bus %d, devfn 0x%x, addr 0x%x, apic_irq %u.\n", + driver_name, dev->bus->number, dev->devfn, addr, dev->irq); +#endif + + if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + continue; + + if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) { + *apic_irq = dev->irq; + return TRUE; + } + + } + +#endif /* end new style PCI code */ + +#endif /* end CONFIG_PCI */ + + return FALSE; +} + __initfunc (static inline int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { unsigned char irq, dma_channel, subversion, i; - unsigned char protocol_rev; + unsigned char protocol_rev, apic_irq; struct eata_info info; char *bus_type, dma_name[16], tag_type; @@ -812,8 +866,13 @@ printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", name, irq); + if (get_pci_irq(port_base, &apic_irq) && (irq != apic_irq)) { + printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, apic_irq); + irq = apic_irq; + } + /* Board detected, allocate its IRQ */ - if (request_irq(irq, eata2x_interrupt_handler, + if (request_irq(irq, interrupt_handler, SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); @@ -1016,21 +1075,49 @@ #if defined(CONFIG_PCI) - unsigned short i = 0; - unsigned char bus, devfn; unsigned int addr, k; +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) + + struct pci_dev *dev = NULL; + if (!pci_present()) return; for (k = 0; k < MAX_PCI; k++) { + if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; + + if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue; + +#if defined(DEBUG_PCI_DETECT) + printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", + driver_name, k, dev->bus->number, dev->devfn, addr); +#endif + + if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) + continue; + + /* Reverse the returned address order */ + io_port[MAX_INT_PARAM + MAX_PCI - k] = + (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; + } + +#else /* else old style PCI code */ + + unsigned short i = 0; + unsigned char bus, devfn; + + if (!pcibios_present()) return; + + for (k = 0; k < MAX_PCI; k++) { + if (pcibios_find_class(PCI_CLASS_STORAGE_SCSI << 8, i++, &bus, &devfn) != PCIBIOS_SUCCESSFUL) break; if (pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &addr) != PCIBIOS_SUCCESSFUL) continue; -#if defined(DEBUG_DETECT) +#if defined(DEBUG_PCI_DETECT) printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", driver_name, k, bus, devfn, addr); #endif @@ -1042,7 +1129,10 @@ io_port[MAX_INT_PARAM + MAX_PCI - k] = (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; } -#endif + +#endif /* end old style PCI code */ + +#endif /* end CONFIG_PCI */ return; } @@ -1523,6 +1613,7 @@ unsigned int input_only = TRUE, overlap = FALSE; unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; + unsigned long ioseek = 0; static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; @@ -1547,6 +1638,7 @@ if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector; sl[n] = SCpnt->request.sector; + ioseek += SCpnt->request.nr_sectors; if (!n) continue; @@ -1568,6 +1660,8 @@ if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; + if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE; + if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); if (!input_only) for (n = 0; n < n_ready; n++) { @@ -1644,8 +1738,7 @@ } -static void eata2x_interrupt_handler(int irq, void *shap, - struct pt_regs *regs) { +static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { Scsi_Cmnd *SCpnt; unsigned int i, j, k, c, status, tstatus, reg; unsigned int n, n_ready, il[MAX_MAILBOXES]; @@ -1703,7 +1796,8 @@ else if (HD(j)->cp_stat[i] == IN_RESET) printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); else if (HD(j)->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i); + panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", + BN(j), i, HD(j)->cp_stat[i]); HD(j)->cp_stat[i] = FREE; cpp = &HD(j)->cp[i]; @@ -1839,6 +1933,22 @@ HD(j)->iocount); return; +} + +static void interrupt_handler(int irq, void *shap, struct pt_regs *regs) { + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) + + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + ihdlr(irq, shap, regs); + spin_unlock_irqrestore(&io_request_lock, flags); + +#else + + ihdlr(irq, shap, regs); + +#endif } int eata2x_release(struct Scsi_Host *shpnt) { diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- v2.1.94/linux/drivers/scsi/eata.h Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/eata.h Fri Apr 10 10:47:30 1998 @@ -5,6 +5,7 @@ #define _EATA_H #include +#include int eata2x_detect(Scsi_Host_Template *); int eata2x_release(struct Scsi_Host *); @@ -12,7 +13,7 @@ int eata2x_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *, unsigned int); -#define EATA_VERSION "4.02.00" +#define EATA_VERSION "4.04.00" #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.1.94/linux/drivers/scsi/ncr53c8xx.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/ncr53c8xx.c Thu Apr 9 22:11:00 1998 @@ -9787,12 +9787,16 @@ #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"); } diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.1.94/linux/drivers/scsi/scsi.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/scsi.c Thu Apr 9 22:11:00 1998 @@ -354,7 +354,6 @@ */ - spin_lock_irqsave(&io_request_lock, flags); host_active = NULL; for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next) { @@ -386,7 +385,6 @@ sh[index]->host_no); } - spin_unlock_irqrestore(&io_request_lock, flags); } static void scan_scsis_done (Scsi_Cmnd * SCpnt) @@ -653,9 +651,11 @@ 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; } @@ -694,9 +694,11 @@ 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; } @@ -836,9 +838,11 @@ 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; } @@ -1133,21 +1137,18 @@ 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," @@ -1197,7 +1198,6 @@ * 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))); @@ -1294,7 +1294,6 @@ 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; @@ -1304,7 +1303,6 @@ * 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; @@ -1317,11 +1315,11 @@ * 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 ) { @@ -1348,18 +1346,6 @@ { 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 @@ -1377,9 +1363,6 @@ { host->hostt->queuecommand (SCpnt, scsi_old_done); } - - if(!in_interrupt() && SCpnt->host->irq) - enable_irq(SCpnt->host->irq); } else { @@ -1452,20 +1435,18 @@ * 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 @@ -1819,7 +1800,6 @@ if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE) return NULL; - spin_lock_irqsave(&io_request_lock, flags); nbits = len >> 9; mask = (1 << nbits) - 1; @@ -1827,7 +1807,6 @@ 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))); @@ -1836,7 +1815,6 @@ return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); } } - spin_unlock_irqrestore(&io_request_lock, flags); return NULL; /* Nope. No more */ } @@ -1870,20 +1848,16 @@ 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<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; @@ -2830,7 +2800,6 @@ */ SCpnt->state = SCSI_STATE_DISCONNECTING; SCpnt->request.rq_status = RQ_SCSI_DISCONNECTING; /* Mark as busy */ - spin_unlock_irqrestore(&io_request_lock, flags); } } } diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v2.1.94/linux/drivers/scsi/scsi.h Thu Mar 26 15:57:03 1998 +++ linux/drivers/scsi/scsi.h Fri Apr 10 10:47:30 1998 @@ -686,7 +686,6 @@ #define INIT_SCSI_REQUEST \ if (!CURRENT) { \ CLEAR_INTR; \ - spin_unlock_irqrestore(&io_request_lock,flags); \ return; \ } \ if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \ diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.1.94/linux/drivers/scsi/sd.c Tue Mar 17 22:18:14 1998 +++ linux/drivers/scsi/sd.c Thu Apr 9 22:19:46 1998 @@ -36,6 +36,9 @@ #include #include +#include +#include + #include #include @@ -513,14 +516,10 @@ 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; } @@ -535,7 +534,6 @@ */ if( SDev->host->in_recovery ) { - spin_unlock_irqrestore(&io_request_lock, flags); return; } @@ -555,10 +553,11 @@ */ 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; @@ -587,7 +586,6 @@ * 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, @@ -605,7 +603,6 @@ 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, @@ -620,7 +617,6 @@ else req1->next = req->next; } - spin_unlock_irqrestore(&io_request_lock, flags); } if (!SCpnt) return; /* Could not find anything to do */ @@ -1125,6 +1121,8 @@ 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. @@ -1157,7 +1155,9 @@ (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; } @@ -1193,7 +1193,9 @@ (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; } @@ -1201,8 +1203,10 @@ } 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) { @@ -1231,7 +1235,9 @@ (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; } @@ -1406,7 +1412,9 @@ (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; } @@ -1431,6 +1439,7 @@ rscsi_disks[i].ten = 1; rscsi_disks[i].remap = 1; scsi_free(buffer, 512); + spin_unlock_irq(&io_request_lock); return i; } @@ -1590,7 +1599,6 @@ int revalidate_scsidisk(kdev_t dev, int maxusage){ int target; struct gendisk * gdev; - unsigned long flags; int max_p; int start; int i; @@ -1598,14 +1606,11 @@ 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; diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.1.94/linux/drivers/scsi/sg.c Wed Apr 1 20:11:53 1998 +++ linux/drivers/scsi/sg.c Thu Apr 9 22:11:00 1998 @@ -250,23 +250,22 @@ /* * 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. diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.1.94/linux/drivers/scsi/sr.c Tue Mar 10 10:03:33 1998 +++ linux/drivers/scsi/sr.c Thu Apr 9 13:43:52 1998 @@ -431,10 +431,7 @@ 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; }; @@ -450,7 +447,6 @@ */ if( SDev->host->in_recovery ) { - spin_unlock_irqrestore(&io_request_lock, flags); return; } @@ -469,8 +465,9 @@ */ 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; @@ -493,7 +490,6 @@ 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 @@ -505,7 +501,6 @@ 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, @@ -520,7 +515,6 @@ else req1->next = req->next; } - spin_unlock_irqrestore(&io_request_lock, flags); } if (!SCpnt) diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.1.94/linux/drivers/scsi/u14-34f.c Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/u14-34f.c Fri Apr 10 10:13:58 1998 @@ -1,6 +1,13 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 + * Improved SMP support (if linux version >= 2.1.95). + * + * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94 + * Performance improvement: when sequential i/o is detected, + * always use direct sort instead of reverse sort. + * * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 * io_port is now unsigned long. * @@ -266,11 +273,14 @@ * the driver sets host->wish_block = TRUE for all ISA boards. */ +#include + #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) #define MAX_INT_PARAM 10 + #if defined(MODULE) #include -#include + #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26) MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i"); MODULE_PARM(linked_comm, "i"); @@ -279,6 +289,7 @@ MODULE_PARM(max_queue_depth, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif + #endif #include @@ -483,7 +494,7 @@ #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0) -static void u14_34f_interrupt_handler(int, void *, struct pt_regs *); +static void interrupt_handler(int, void *, struct pt_regs *); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; static int setup_done = FALSE; @@ -683,7 +694,7 @@ subversion = (in_byte & 0x0f); /* Board detected, allocate its IRQ */ - if (request_irq(irq, u14_34f_interrupt_handler, + if (request_irq(irq, interrupt_handler, SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); @@ -1309,6 +1320,7 @@ unsigned int input_only = TRUE, overlap = FALSE; unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; + unsigned long ioseek = 0; static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; @@ -1333,6 +1345,7 @@ if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector; sl[n] = SCpnt->request.sector; + ioseek += SCpnt->request.nr_sectors; if (!n) continue; @@ -1354,6 +1367,8 @@ if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; + if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE; + if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); if (!input_only) for (n = 0; n < n_ready; n++) { @@ -1431,8 +1446,7 @@ } } -static void u14_34f_interrupt_handler(int irq, void *shap, - struct pt_regs *regs) { +static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { Scsi_Cmnd *SCpnt; unsigned int i, j, k, c, status, tstatus, reg, ret; struct mscp *spp; @@ -1479,7 +1493,8 @@ else if (HD(j)->cp_stat[i] == IN_RESET) printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); else if (HD(j)->cp_stat[i] != IN_USE) - panic("%s: ihdlr, mbox %d, invalid cp_stat.\n", BN(j), i); + panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", + BN(j), i, HD(j)->cp_stat[i]); HD(j)->cp_stat[i] = FREE; SCpnt = spp->SCpnt; @@ -1608,6 +1623,22 @@ HD(j)->iocount); return; +} + +static void interrupt_handler(int irq, void *shap, struct pt_regs *regs) { + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) + + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); + ihdlr(irq, shap, regs); + spin_unlock_irqrestore(&io_request_lock, flags); + +#else + + ihdlr(irq, shap, regs); + +#endif } int u14_34f_release(struct Scsi_Host *shpnt) { diff -u --recursive --new-file v2.1.94/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- v2.1.94/linux/drivers/scsi/u14-34f.h Mon Apr 6 17:41:00 1998 +++ linux/drivers/scsi/u14-34f.h Fri Apr 10 10:47:30 1998 @@ -4,6 +4,8 @@ #ifndef _U14_34F_H #define _U14_34F_H +#include + int u14_34f_detect(Scsi_Host_Template *); int u14_34f_release(struct Scsi_Host *); int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); @@ -11,7 +13,7 @@ int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "4.02.00" +#define U14_34F_VERSION "4.04.00" #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) diff -u --recursive --new-file v2.1.94/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.94/linux/fs/dcache.c Mon Apr 6 17:41:00 1998 +++ linux/fs/dcache.c Thu Apr 9 13:15:40 1998 @@ -784,7 +784,7 @@ 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) { diff -u --recursive --new-file v2.1.94/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.94/linux/fs/proc/root.c Tue Mar 17 22:18:15 1998 +++ linux/fs/proc/root.c Thu Apr 9 13:16:18 1998 @@ -499,13 +499,6 @@ 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", @@ -640,9 +633,6 @@ 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 @@ -707,9 +697,6 @@ #endif proc_bus = create_proc_entry("bus", S_IFDIR, 0); -#ifdef CONFIG_PCI - proc_bus_pci_init(); -#endif } /* diff -u --recursive --new-file v2.1.94/linux/include/asm-i386/system.h linux/include/asm-i386/system.h --- v2.1.94/linux/include/asm-i386/system.h Thu Feb 12 20:56:12 1998 +++ linux/include/asm-i386/system.h Fri Apr 10 10:08:11 1998 @@ -215,7 +215,12 @@ return x; } -#define mb() __asm__ __volatile__ ("" : : :"memory") +/* + * Force strict CPU ordering. + * And yes, this is required on UP too when we're talking + * to devices. + */ +#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") /* interrupt control.. */ #define __sti() __asm__ __volatile__ ("sti": : :"memory") diff -u --recursive --new-file v2.1.94/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.94/linux/include/linux/pci.h Wed Apr 8 19:36:29 1998 +++ linux/include/linux/pci.h Thu Apr 9 13:16:18 1998 @@ -977,9 +977,6 @@ #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. @@ -1078,6 +1075,8 @@ 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); diff -u --recursive --new-file v2.1.94/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.94/linux/include/linux/proc_fs.h Mon Apr 6 17:41:01 1998 +++ linux/include/linux/proc_fs.h Fri Apr 10 10:46:47 1998 @@ -275,7 +275,6 @@ 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);