Commit 61cb5dec authored by Linus Torvalds's avatar Linus Torvalds

Linux 2.1.98

I just released a fairly small patch to 97 to bring it up to 98.

I've gotten a lot of patches in the mail for the last week, and I've been
ignoring most of them for obvious reasons. They aren't in any in-queue,
you can more-or-less consider them lost - but don't resend them all
immediately, because if I get another huge batch of patches then I'll just
have to ignore them again.

We're going slow and easy, and the plan is to not only keep me sane in the
midst of all the diapers, but I'll also at the same time take the
opportunity to actually enforce the feature-freeze. You've known about it
for a long time, _tough_.

Anyway, 2.1.98 _should_ fix:

 - the IDE/SCSI lockups. The irq enable/disable code was broken, and could
   do some really bad things. This tended to lock up the machine if you
   accessed your IDE disks heavily, or in particular if you had a mixture
   of IDE and SCSI and used them at the same time. Tell me if you still
   have problems - I'm sure there are still bugs left, and I want to hear
   about them.
 - memory management especially on small-memory machines. I think I made a
   good change to the allocation logic, and I'm hoping it will fix the bad
   bahevaiour on those wimpy machines that all you losers out there are
   using that have less than half a Gig of RAM. It certainly still works
   fine on my machine, and I'm certainly still too lazy to test it out on
   anything smaller.

There's a few other updates too: the asm constraints are fixed, so it
should compile again with other compiler versions than the particular one
I happen to be using. And some of the SCSI drivers have been updated a
bit.

There's been a lot of discussion and patches on capabilities, and I
haven't applied them yet, I'll let them simmer a bit. Similarly, I've seen
so many pathes to kmod that my head is spinning, and as I don't use
modules myself I'd really like to get feedback from users about the
different patches, so that maybe I'll get something that everybody can
agree on as acceptable. Right now I don't know which patch I should even
begin looking at.

                Linus
parent 5d2e518d
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 97 SUBLEVEL = 98
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
...@@ -37,11 +37,9 @@ OLD_GAS := $(shell if cat ./GAS_VER | grep 'version 2.7' > /dev/null; then echo ...@@ -37,11 +37,9 @@ OLD_GAS := $(shell if cat ./GAS_VER | grep 'version 2.7' > /dev/null; then echo
$(shell rm -f ./GAS_VER) $(shell rm -f ./GAS_VER)
ifneq ($(OLD_GAS),yes) ifneq ($(OLD_GAS),yes)
CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE
# if PYXIS, then enable use of BWIO space # if PYXIS, then enable use of BWIO space
ifeq ($(CONFIG_ALPHA_PYXIS),y) ifeq ($(CONFIG_ALPHA_PYXIS),y)
CFLAGS := $(CFLAGS) -DBWIO_ENABLED CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED
endif endif
endif endif
......
...@@ -337,7 +337,7 @@ int get_irq_list(char *buf) ...@@ -337,7 +337,7 @@ int get_irq_list(char *buf)
if (IO_APIC_IRQ(i)) if (IO_APIC_IRQ(i))
p += sprintf(p, " IO-APIC "); p += sprintf(p, " IO-APIC ");
else else
p += sprintf(p, " XT PIC "); p += sprintf(p, " XT-PIC ");
p += sprintf(p, " %s", action->name); p += sprintf(p, " %s", action->name);
for (action=action->next; action; action = action->next) { for (action=action->next; action; action = action->next) {
...@@ -669,7 +669,6 @@ void disable_irq(unsigned int irq) ...@@ -669,7 +669,6 @@ void disable_irq(unsigned int irq)
*/ */
static void disable_8259A_irq(unsigned int irq) static void disable_8259A_irq(unsigned int irq)
{ {
disabled_irq[irq]++;
cached_irq_mask |= 1 << irq; cached_irq_mask |= 1 << irq;
set_8259A_irq_mask(irq); set_8259A_irq_mask(irq);
} }
...@@ -677,7 +676,7 @@ static void disable_8259A_irq(unsigned int irq) ...@@ -677,7 +676,7 @@ static void disable_8259A_irq(unsigned int irq)
#ifdef __SMP__ #ifdef __SMP__
static void disable_ioapic_irq(unsigned int irq) static void disable_ioapic_irq(unsigned int irq)
{ {
disabled_irq[irq]++; disabled_irq[irq] = 1;
/* /*
* We do not disable IO-APIC irqs in hardware ... * We do not disable IO-APIC irqs in hardware ...
*/ */
...@@ -688,12 +687,6 @@ void enable_8259A_irq (unsigned int irq) ...@@ -688,12 +687,6 @@ void enable_8259A_irq (unsigned int irq)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&irq_controller_lock, flags); spin_lock_irqsave(&irq_controller_lock, flags);
if (disabled_irq[irq])
disabled_irq[irq]--;
else {
spin_unlock_irqrestore(&irq_controller_lock, flags);
return;
}
cached_irq_mask &= ~(1 << irq); cached_irq_mask &= ~(1 << irq);
set_8259A_irq_mask(irq); set_8259A_irq_mask(irq);
spin_unlock_irqrestore(&irq_controller_lock, flags); spin_unlock_irqrestore(&irq_controller_lock, flags);
...@@ -706,13 +699,8 @@ void enable_ioapic_irq (unsigned int irq) ...@@ -706,13 +699,8 @@ void enable_ioapic_irq (unsigned int irq)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
spin_lock_irqsave(&irq_controller_lock, flags); spin_lock_irqsave(&irq_controller_lock, flags);
if (disabled_irq[irq]) disabled_irq[irq] = 0;
disabled_irq[irq]--;
else {
spin_unlock_irqrestore(&irq_controller_lock, flags);
return;
}
#if 0
/* /*
* In the SMP+IOAPIC case it might happen that there are an unspecified * In the SMP+IOAPIC case it might happen that there are an unspecified
* number of pending IRQ events unhandled. These cases are very rare, * number of pending IRQ events unhandled. These cases are very rare,
...@@ -720,7 +708,7 @@ void enable_ioapic_irq (unsigned int irq) ...@@ -720,7 +708,7 @@ void enable_ioapic_irq (unsigned int irq)
* better to do it this way as thus we dont have to be aware of * better to do it this way as thus we dont have to be aware of
* 'pending' interrupts in the IRQ path, except at this point. * 'pending' interrupts in the IRQ path, except at this point.
*/ */
if (!disabled_irq[irq] && irq_events[irq]) { if (irq_events[irq]) {
if (!ipi_pending[irq]) { if (!ipi_pending[irq]) {
ipi_pending[irq] = 1; ipi_pending[irq] = 1;
--irq_events[irq]; --irq_events[irq];
...@@ -728,36 +716,6 @@ void enable_ioapic_irq (unsigned int irq) ...@@ -728,36 +716,6 @@ void enable_ioapic_irq (unsigned int irq)
} }
} }
spin_unlock_irqrestore(&irq_controller_lock, flags); spin_unlock_irqrestore(&irq_controller_lock, flags);
#else
if (!disabled_irq[irq] && irq_events[irq]) {
struct pt_regs regs; /* FIXME: these are fake currently */
disabled_irq[irq]++;
hardirq_enter(cpu);
spin_unlock(&irq_controller_lock);
release_irqlock(cpu);
while (test_bit(0,&global_irq_lock)) mb();
again:
handle_IRQ_event(irq, &regs);
spin_lock(&irq_controller_lock);
disabled_irq[irq]--;
should_handle_irq=0;
if (--irq_events[irq] && !disabled_irq[irq]) {
should_handle_irq=1;
disabled_irq[irq]++;
}
spin_unlock(&irq_controller_lock);
if (should_handle_irq)
goto again;
irq_exit(cpu, irq);
__restore_flags(flags);
} else
spin_unlock_irqrestore(&irq_controller_lock, flags);
#endif
} }
#endif #endif
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* applications that require more DP ram, we can expand the boundaries * applications that require more DP ram, we can expand the boundaries
* but then we have to be careful of any downloaded microcode. * but then we have to be careful of any downloaded microcode.
*/ */
#include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* small packets. * small packets.
* *
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
......
#include <linux/config.h>
#include "../kernel/ppc_defs.h" #include "../kernel/ppc_defs.h"
#include "../kernel/ppc_asm.tmpl" #include "../kernel/ppc_asm.tmpl"
#include <asm/processor.h> #include <asm/processor.h>
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* *
*/ */
#include <linux/config.h>
#include <linux/sys.h> #include <linux/sys.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/errno.h> #include <asm/errno.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/a.out.h> #include <linux/a.out.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/config.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* creating a software PLL, I have set HZ to 128. -- Dan * creating a software PLL, I have set HZ to 128. -- Dan
*/ */
#include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
* Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/ */
#include <linux/config.h> /* for CONFIG_PROFILE */
#include <asm/head.h> #include <asm/head.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
* Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
*/ */
#include <linux/config.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
......
...@@ -1118,10 +1118,9 @@ struct request **ide_get_queue (kdev_t dev) ...@@ -1118,10 +1118,9 @@ struct request **ide_get_queue (kdev_t dev)
* conditions in the event that an unexpected interrupt occurs while * conditions in the event that an unexpected interrupt occurs while
* we are in the driver. * we are in the driver.
* *
* Note that when an interrupt is used to reenter the driver, the first level * Note that the io-request lock will guarantee that the driver never gets
* handler will already have masked the irq that triggered, but any other ones * re-entered even on another interrupt level, so we no longer need to
* for the hwgroup will still be unmasked. The driver tries to be careful * mask the irq's.
* about such things.
*/ */
static void do_hwgroup_request (ide_hwgroup_t *hwgroup) static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
{ {
...@@ -1132,13 +1131,7 @@ static void do_hwgroup_request (ide_hwgroup_t *hwgroup) ...@@ -1132,13 +1131,7 @@ static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
del_timer(&hwgroup->timer); del_timer(&hwgroup->timer);
ide_get_lock(&ide_lock, ide_intr, hwgroup); ide_get_lock(&ide_lock, ide_intr, hwgroup);
hwgroup->active = 1; hwgroup->active = 1;
do {
disable_irq(hwif->irq);
} while ((hwif = hwif->next) != hgif);
ide_do_request (hwgroup); ide_do_request (hwgroup);
do {
enable_irq(hwif->irq);
} while ((hwif = hwif->next) != hgif);
} }
} }
...@@ -1274,10 +1267,6 @@ static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs) ...@@ -1274,10 +1267,6 @@ static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET])) if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
return; return;
do {
if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq))
disable_irq(hwif->irq);
} while ((hwif = hwif->next) != hwgroup->hwif);
if (IDE_IRQ_EQUAL(irq, hwif->irq) if (IDE_IRQ_EQUAL(irq, hwif->irq)
&& (handler = hwgroup->handler) != NULL) { && (handler = hwgroup->handler) != NULL) {
ide_drive_t *drive = hwgroup->drive; ide_drive_t *drive = hwgroup->drive;
...@@ -1309,10 +1298,6 @@ static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs) ...@@ -1309,10 +1298,6 @@ static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
} }
__cli(); __cli();
hwif = hwgroup->hwif; hwif = hwgroup->hwif;
do {
if (!IDE_IRQ_EQUAL(hwif->irq, irq))
enable_irq(hwif->irq);
} while ((hwif = hwif->next) != hwgroup->hwif);
} }
/* /*
......
...@@ -658,7 +658,7 @@ MODULE_PARM(reset, "i"); ...@@ -658,7 +658,7 @@ MODULE_PARM(reset, "i");
#else #else
static int parport[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; static int parport_nr[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
static int reset __initdata = 0; static int reset __initdata = 0;
static int parport_ptr = 0; static int parport_ptr = 0;
...@@ -668,21 +668,21 @@ __initfunc(void lp_setup(char *str, int *ints)) ...@@ -668,21 +668,21 @@ __initfunc(void lp_setup(char *str, int *ints))
if (!str) { if (!str) {
if (ints[0] == 0 || ints[1] == 0) { if (ints[0] == 0 || ints[1] == 0) {
/* disable driver on "lp=" or "lp=0" */ /* disable driver on "lp=" or "lp=0" */
parport[0] = LP_PARPORT_OFF; parport_nr[0] = LP_PARPORT_OFF;
} else { } else {
printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]); printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
} }
} else if (!strncmp(str, "parport", 7)) { } else if (!strncmp(str, "parport", 7)) {
int n = simple_strtoul(str+7, NULL, 10); int n = simple_strtoul(str+7, NULL, 10);
if (parport_ptr < LP_NO) if (parport_ptr < LP_NO)
parport[parport_ptr++] = n; parport_nr[parport_ptr++] = n;
else else
printk(KERN_INFO "lp: too many ports, %s ignored.\n", printk(KERN_INFO "lp: too many ports, %s ignored.\n",
str); str);
} else if (!strcmp(str, "auto")) { } else if (!strcmp(str, "auto")) {
parport[0] = LP_PARPORT_AUTO; parport_nr[0] = LP_PARPORT_AUTO;
} else if (!strcmp(str, "none")) { } else if (!strcmp(str, "none")) {
parport[parport_ptr++] = LP_PARPORT_NONE; parport_nr[parport_ptr++] = LP_PARPORT_NONE;
} else if (!strcmp(str, "reset")) { } else if (!strcmp(str, "reset")) {
reset = 1; reset = 1;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/ */
#include <linux/config.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
......
...@@ -100,10 +100,6 @@ static int irq_write_proc(struct file *file, const char *buffer, ...@@ -100,10 +100,6 @@ static int irq_write_proc(struct file *file, const char *buffer,
out_ok: out_ok:
pp->irq = newirq; pp->irq = newirq;
if (oldirq != PARPORT_IRQ_NONE && newirq == PARPORT_IRQ_NONE &&
cad && cad->irq_func)
cad->irq_func(pp->irq, cad->private, NULL);
out: out:
return retval; return retval;
} }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#undef PARPORT_PARANOID #undef PARPORT_PARANOID
#define PARPORT_DEFAULT_TIMESLICE (HZ/10) #define PARPORT_DEFAULT_TIMESLICE (HZ/5)
static struct parport *portlist = NULL, *portlist_tail = NULL; static struct parport *portlist = NULL, *portlist_tail = NULL;
static int portcount = 0; static int portcount = 0;
......
...@@ -66,6 +66,7 @@ static char *version = ...@@ -66,6 +66,7 @@ static char *version =
static char *lancestr = "LANCE"; static char *lancestr = "LANCE";
static char *lancedma = "LANCE DMA"; static char *lancedma = "LANCE DMA";
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -323,7 +323,7 @@ __initfunc(void pci_init(void)) ...@@ -323,7 +323,7 @@ __initfunc(void pci_init(void))
pci_quirks_init(); pci_quirks_init();
#endif #endif
#ifdef CONFIG_PROC #ifdef CONFIG_PROC_FS
pci_proc_init(); pci_proc_init();
#endif #endif
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz> * Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/ */
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h> #include <linux/pci.h>
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (C) 1998 Pavel Machek (pavel@ucw.cz) * Copyright (C) 1998 Pavel Machek (pavel@ucw.cz)
*/ */
#include <linux/config.h>
#include <linux/kd.h> #include <linux/kd.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/malloc.h> #include <linux/malloc.h>
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
* *
*/ */
#include <linux/config.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -1124,7 +1124,7 @@ static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T ...@@ -1124,7 +1124,7 @@ static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T
If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
Host Adapters; otherwise, default to the standard ISA MultiMaster probe. Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
*/ */
if (!BusLogic_ProbeOptions.NoProbePCI && pcibios_present()) if (!BusLogic_ProbeOptions.NoProbePCI && pci_present())
{ {
if (BusLogic_ProbeOptions.MultiMasterFirst) if (BusLogic_ProbeOptions.MultiMasterFirst)
{ {
......
/* /*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters. * eata.c - Low-level driver for EATA/DMA SCSI host adapters.
* *
* 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
* Reworked interrupt handler.
*
* 11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
* Major reliability improvement: when a batch with overlapping
* requests is detected, requests are queued one at a time
* eliminating any possible board or drive reordering.
*
* 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
* Improved SMP support (if linux version >= 2.1.95). * Improved SMP support (if linux version >= 2.1.95).
* *
...@@ -8,7 +16,7 @@ ...@@ -8,7 +16,7 @@
* Added support for new PCI code and IO-APIC remapping of irqs. * Added support for new PCI code and IO-APIC remapping of irqs.
* Performance improvement: when sequential i/o is detected, * Performance improvement: when sequential i/o is detected,
* always use direct sort instead of reverse sort. * always use direct sort instead of reverse sort.
* *
* 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
* io_port is now unsigned long. * io_port is now unsigned long.
* *
...@@ -16,7 +24,6 @@ ...@@ -16,7 +24,6 @@
* Use new scsi error handling code (if linux version >= 2.1.88). * Use new scsi error handling code (if linux version >= 2.1.88).
* Use new interrupt code. * Use new interrupt code.
* *
*
* 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
* Use of udelay inside the wait loops to avoid timeout * Use of udelay inside the wait loops to avoid timeout
* problems with fast cpus. * problems with fast cpus.
...@@ -30,7 +37,7 @@ ...@@ -30,7 +37,7 @@
* Use of serial_number_at_timeout in abort and reset processing. * Use of serial_number_at_timeout in abort and reset processing.
* Use of the __initfunc and __initdata macro in setup code. * Use of the __initfunc and __initdata macro in setup code.
* Minor cleanups in the list_statistics code. * Minor cleanups in the list_statistics code.
* Increased controller busy timeout in order to better support * Increased controller busy timeout in order to better support
* slow SCSI devices. * slow SCSI devices.
* *
* 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26 * 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26
...@@ -39,7 +46,7 @@ ...@@ -39,7 +46,7 @@
* Fixed data transfer direction for some SCSI opcodes. * Fixed data transfer direction for some SCSI opcodes.
* Immediate acknowledge to request sense commands. * Immediate acknowledge to request sense commands.
* Linked commands to each disk device are now reordered by elevator * Linked commands to each disk device are now reordered by elevator
* sorting. Rare cases in which reordering of write requests could * sorting. Rare cases in which reordering of write requests could
* cause wrong results are managed. * cause wrong results are managed.
* Fixed spurious timeouts caused by long simple queue tag sequences. * Fixed spurious timeouts caused by long simple queue tag sequences.
* New command line option (tm:[0-3]) to choose the type of tags: * New command line option (tm:[0-3]) to choose the type of tags:
...@@ -105,7 +112,7 @@ ...@@ -105,7 +112,7 @@
* *
* 28 Jan 1995 rev. 1.14 for linux 1.1.86 * 28 Jan 1995 rev. 1.14 for linux 1.1.86
* Added module support. * Added module support.
* Log and do a retry when a disk drive returns a target status * Log and do a retry when a disk drive returns a target status
* different from zero on a recovered error. * different from zero on a recovered error.
* *
* 24 Jan 1995 rev. 1.13 for linux 1.1.85 * 24 Jan 1995 rev. 1.13 for linux 1.1.85
...@@ -119,7 +126,7 @@ ...@@ -119,7 +126,7 @@
* *
* 17 Dec 1994 rev. 1.11 for linux 1.1.74 * 17 Dec 1994 rev. 1.11 for linux 1.1.74
* Use the scsicam_bios_param routine. This allows an easy * Use the scsicam_bios_param routine. This allows an easy
* migration path from disk partition tables created using * migration path from disk partition tables created using
* different SCSI drivers and non optimal disk geometry. * different SCSI drivers and non optimal disk geometry.
* *
* 15 Dec 1994 rev. 1.10 for linux 1.1.74 * 15 Dec 1994 rev. 1.10 for linux 1.1.74
...@@ -173,10 +180,10 @@ ...@@ -173,10 +180,10 @@
* The DPT PM2001 provides only the EATA/PIO interface and hence is not * The DPT PM2001 provides only the EATA/PIO interface and hence is not
* supported by this driver. * supported by this driver.
* *
* This code has been tested with up to 3 Distributed Processing Technology * This code has been tested with up to 3 Distributed Processing Technology
* PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers, * PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) EISA controllers,
* in any combination of private and shared IRQ. * in any combination of private and shared IRQ.
* PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS * PCI support has been tested using up to 2 DPT PM3224W (DPT SCSI BIOS
* v003.D0, firmware v07G.0). * v003.D0, firmware v07G.0).
* *
* DPT SmartRAID boards support "Hardware Array" - a group of disk drives * DPT SmartRAID boards support "Hardware Array" - a group of disk drives
...@@ -186,14 +193,14 @@ ...@@ -186,14 +193,14 @@
* *
* WARNING: to create a RAID-0 "Hardware Array" you must select "Other Unix" * WARNING: to create a RAID-0 "Hardware Array" you must select "Other Unix"
* as the current OS in the DPTMGR "Initial System Installation" menu. * as the current OS in the DPTMGR "Initial System Installation" menu.
* Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0), * Otherwise RAID-0 is generated as an "Array Group" (i.e. software RAID-0),
* which is not supported by the actual SCSI subsystem. * which is not supported by the actual SCSI subsystem.
* To get the "Array Group" functionality, the Linux MD driver must be used * To get the "Array Group" functionality, the Linux MD driver must be used
* instead of the DPT "Array Group" feature. * instead of the DPT "Array Group" feature.
* *
* Multiple ISA, EISA and PCI boards can be configured in the same system. * Multiple ISA, EISA and PCI boards can be configured in the same system.
* It is suggested to put all the EISA boards on the same IRQ level, all * It is suggested to put all the EISA boards on the same IRQ level, all
* the PCI boards on another IRQ level, while ISA boards cannot share * the PCI boards on another IRQ level, while ISA boards cannot share
* interrupts. * interrupts.
* *
* If you configure multiple boards on the same IRQ, the interrupt must * If you configure multiple boards on the same IRQ, the interrupt must
...@@ -206,7 +213,7 @@ ...@@ -206,7 +213,7 @@
* bus, or even if you system has no EISA bus at all. * bus, or even if you system has no EISA bus at all.
* Do not force any ISA address on EATA PCI boards. * Do not force any ISA address on EATA PCI boards.
* *
* If PCI bios support is configured into the kernel, BIOS32 is used to * If PCI bios support is configured into the kernel, BIOS32 is used to
* include in the list of i/o ports to be probed all the PCI SCSI controllers. * include in the list of i/o ports to be probed all the PCI SCSI controllers.
* *
* Due to a DPT BIOS "feature", it might not be possible to force an EISA * Due to a DPT BIOS "feature", it might not be possible to force an EISA
...@@ -215,11 +222,11 @@ ...@@ -215,11 +222,11 @@
* *
* The sequence of detection probes is: * The sequence of detection probes is:
* *
* - ISA 0x1F0; * - ISA 0x1F0;
* - PCI SCSI controllers (only if BIOS32 is available); * - PCI SCSI controllers (only if BIOS32 is available);
* - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15); * - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15);
* - ISA 0x170, 0x230, 0x330. * - ISA 0x170, 0x230, 0x330.
* *
* The above list of detection probes can be totally replaced by the * The above list of detection probes can be totally replaced by the
* boot command line option: "eata=port0,port1,port2,...", where the * boot command line option: "eata=port0,port1,port2,...", where the
* port0, port1... arguments are ISA/EISA/PCI addresses to be probed. * port0, port1... arguments are ISA/EISA/PCI addresses to be probed.
...@@ -261,15 +268,15 @@ ...@@ -261,15 +268,15 @@
* in the elevator sorting queue. When the active command completes, the * in the elevator sorting queue. When the active command completes, the
* commands in this queue are sorted by sector address. The sort is chosen * commands in this queue are sorted by sector address. The sort is chosen
* between increasing or decreasing by minimizing the seek distance between * between increasing or decreasing by minimizing the seek distance between
* the sector of the commands just completed and the sector of the first * the sector of the commands just completed and the sector of the first
* command in the list to be sorted. * command in the list to be sorted.
* Trivial math assures that the unsorted average seek distance when doing * Trivial math assures that the unsorted average seek distance when doing
* random seeks over S sectors is S/3. * random seeks over S sectors is S/3.
* When (Q-1) requests are uniformly distributed over S sectors, the average * When (Q-1) requests are uniformly distributed over S sectors, the average
* distance between two adjacent requests is S/((Q-1) + 1), so the sorted * distance between two adjacent requests is S/((Q-1) + 1), so the sorted
* average seek distance for (Q-1) random requests over S sectors is S/Q. * average seek distance for (Q-1) random requests over S sectors is S/Q.
* The elevator sorting hence divides the seek distance by a factor Q/3. * The elevator sorting hence divides the seek distance by a factor Q/3.
* The above pure geometric remarks are valid in all cases and the * The above pure geometric remarks are valid in all cases and the
* driver effectively reduces the seek distance by the predicted factor * driver effectively reduces the seek distance by the predicted factor
* when there are Q concurrent read i/o operations on the device, but this * when there are Q concurrent read i/o operations on the device, but this
* does not necessarily results in a noticeable performance improvement: * does not necessarily results in a noticeable performance improvement:
...@@ -277,7 +284,7 @@ ...@@ -277,7 +284,7 @@
* *
* Note: command reordering inside a batch of queued commands could cause * Note: command reordering inside a batch of queued commands could cause
* wrong results only if there is at least one write request and the * wrong results only if there is at least one write request and the
* intersection (sector-wise) of all requests is not empty. * intersection (sector-wise) of all requests is not empty.
* When the driver detects a batch including overlapping requests * When the driver detects a batch including overlapping requests
* (a really rare event) strict serial (pid) order is enforced. * (a really rare event) strict serial (pid) order is enforced.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
...@@ -316,7 +323,11 @@ MODULE_AUTHOR("Dario Ballabio"); ...@@ -316,7 +323,11 @@ MODULE_AUTHOR("Dario Ballabio");
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
#include <asm/spinlock.h> #include <asm/spinlock.h>
#endif
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/blk.h> #include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
...@@ -359,7 +370,7 @@ struct proc_dir_entry proc_scsi_eata2x = { ...@@ -359,7 +370,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
#undef DEBUG_RESET #undef DEBUG_RESET
#define MAX_ISA 4 #define MAX_ISA 4
#define MAX_VESA 0 #define MAX_VESA 0
#define MAX_EISA 15 #define MAX_EISA 15
#define MAX_PCI 16 #define MAX_PCI 16
#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
...@@ -499,7 +510,7 @@ struct mssp { ...@@ -499,7 +510,7 @@ struct mssp {
unchar target_status; /* SCSI status received after data transfer */ unchar target_status; /* SCSI status received after data transfer */
unchar unused[2]; unchar unused[2];
ulong inv_res_len; /* Number of bytes not transferred */ ulong inv_res_len; /* Number of bytes not transferred */
Scsi_Cmnd *SCpnt; /* Address set in cp */ struct mscp *cpp; /* Address set in cp */
char mess[12]; char mess[12];
}; };
...@@ -515,7 +526,7 @@ struct mscp { ...@@ -515,7 +526,7 @@ struct mscp {
reqsen:1, /* Transfer Request Sense Data to addr using DMA */ reqsen:1, /* Transfer Request Sense Data to addr using DMA */
sg:1, /* Use Scatter/Gather */ sg:1, /* Use Scatter/Gather */
:1, :1,
interp:1, /* The controller interprets cp, not the target */ interp:1, /* The controller interprets cp, not the target */
dout:1, /* Direction of Transfer is Out (Host to Target) */ dout:1, /* Direction of Transfer is Out (Host to Target) */
din:1; /* Direction of Transfer is In (Target to Host) */ din:1; /* Direction of Transfer is In (Target to Host) */
unchar sense_len; /* Request Sense Length */ unchar sense_len; /* Request Sense Length */
...@@ -535,10 +546,11 @@ struct mscp { ...@@ -535,10 +546,11 @@ struct mscp {
unchar mess[3]; /* Massage to/from Target */ unchar mess[3]; /* Massage to/from Target */
unchar cdb[12]; /* Command Descriptor Block */ unchar cdb[12]; /* Command Descriptor Block */
ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */
Scsi_Cmnd *SCpnt; /* Address to be returned in sp */ struct mscp *cpp; /* Address to be returned in sp */
ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */ ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */
ulong sp_addr; /* Address where sp is DMA'ed when cp completes */ ulong sp_addr; /* Address where sp is DMA'ed when cp completes */
ulong sense_addr; /* Address where Sense Data is DMA'ed on error */ ulong sense_addr; /* Address where Sense Data is DMA'ed on error */
Scsi_Cmnd *SCpnt;
unsigned int index; /* cp index */ unsigned int index; /* cp index */
struct sg_list *sglist; struct sg_list *sglist;
}; };
...@@ -558,7 +570,7 @@ struct hostdata { ...@@ -558,7 +570,7 @@ struct hostdata {
unsigned long last_retried_pid; /* Pid of last retried command */ unsigned long last_retried_pid; /* Pid of last retried command */
unsigned char subversion; /* Bus type, either ISA or EISA/PCI */ unsigned char subversion; /* Bus type, either ISA or EISA/PCI */
unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */ unsigned char protocol_rev; /* EATA 2.0 rev., 'A' or 'B' or 'C' */
struct mssp sp[MAX_MAILBOXES]; /* Returned status for this board */ struct mssp sp[2]; /* Returned status for this board */
}; };
static struct Scsi_Host *sh[MAX_BOARDS + 1]; static struct Scsi_Host *sh[MAX_BOARDS + 1];
...@@ -568,7 +580,7 @@ static char sha[MAX_BOARDS]; ...@@ -568,7 +580,7 @@ static char sha[MAX_BOARDS];
/* Initialize num_boards so that ihdlr can work while detect is in progress */ /* Initialize num_boards so that ihdlr can work while detect is in progress */
static unsigned int num_boards = MAX_BOARDS; static unsigned int num_boards = MAX_BOARDS;
static unsigned long io_port[] __initdata = { static unsigned long io_port[] __initdata = {
/* Space for MAX_INT_PARAM ports usable while loading as a module */ /* Space for MAX_INT_PARAM ports usable while loading as a module */
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
...@@ -583,11 +595,11 @@ static unsigned long io_port[] __initdata = { ...@@ -583,11 +595,11 @@ static unsigned long io_port[] __initdata = {
/* MAX_EISA ports */ /* MAX_EISA ports */
0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88,
0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88,
/* Other (MAX_ISA - 1) ports */ /* Other (MAX_ISA - 1) ports */
0x170, 0x230, 0x330, 0x170, 0x230, 0x330,
/* End of list */ /* End of list */
0x0 0x0
}; };
...@@ -627,7 +639,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN; ...@@ -627,7 +639,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN;
static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
Scsi_Device *dev; Scsi_Device *dev;
int j, ntag = 0, nuntag = 0, tqd, utqd; int j, ntag = 0, nuntag = 0, tqd, utqd;
unsigned long flags; unsigned long flags;
save_flags(flags); save_flags(flags);
...@@ -792,14 +804,14 @@ __initfunc (static inline int port_detect \ ...@@ -792,14 +804,14 @@ __initfunc (static inline int port_detect \
if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE; if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE;
/* Read the info structure */ /* Read the info structure */
if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0]))
return FALSE; return FALSE;
/* Check the controller "EATA" signature */ /* Check the controller "EATA" signature */
if (info.sign != EATA_SIGNATURE) return FALSE; if (info.sign != EATA_SIGNATURE) return FALSE;
if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
printk("%s: config structure size (%ld bytes) too short, detaching.\n", printk("%s: config structure size (%ld bytes) too short, detaching.\n",
name, DEV2H(info.data_len)); name, DEV2H(info.data_len));
return FALSE; return FALSE;
} }
...@@ -956,7 +968,7 @@ __initfunc (static inline int port_detect \ ...@@ -956,7 +968,7 @@ __initfunc (static inline int port_detect \
/* DPT PM2012 does not allow to detect can_queue correctly */ /* DPT PM2012 does not allow to detect can_queue correctly */
if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue < 2) { if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue < 2) {
printk("%s: detect, wrong n. of Mbox %d, fixed.\n", printk("%s: detect, wrong n. of mbox %d, fixed.\n",
BN(j), sh[j]->can_queue); BN(j), sh[j]->can_queue);
sh[j]->can_queue = MAX_MAILBOXES; sh[j]->can_queue = MAX_MAILBOXES;
} }
...@@ -984,14 +996,14 @@ __initfunc (static inline int port_detect \ ...@@ -984,14 +996,14 @@ __initfunc (static inline int port_detect \
for (i = 0; i < sh[j]->can_queue; i++) for (i = 0; i < sh[j]->can_queue; i++)
if (! ((&HD(j)->cp[i])->sglist = kmalloc( if (! ((&HD(j)->cp[i])->sglist = kmalloc(
sh[j]->sg_tablesize * sizeof(struct sg_list), sh[j]->sg_tablesize * sizeof(struct sg_list),
(sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
eata2x_release(sh[j]); eata2x_release(sh[j]);
return FALSE; return FALSE;
} }
if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
max_queue_depth = MAX_TAGGED_CMD_PER_LUN; max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
...@@ -1032,7 +1044,7 @@ __initfunc (static inline int port_detect \ ...@@ -1032,7 +1044,7 @@ __initfunc (static inline int port_detect \
if (protocol_rev == 'C') if (protocol_rev == 'C')
printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\ printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\
"raidnum %u.\n", name, info.max_lun, info.m1, info.idquest, "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest,
info.pci, info.eisa, info.raidnum); info.pci, info.eisa, info.raidnum);
#endif #endif
...@@ -1047,8 +1059,8 @@ __initfunc (void eata2x_setup(char *str, int *ints)) { ...@@ -1047,8 +1059,8 @@ __initfunc (void eata2x_setup(char *str, int *ints)) {
if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM; if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
io_port[i] = 0; io_port[i] = 0;
setup_done = TRUE; setup_done = TRUE;
} }
...@@ -1099,7 +1111,7 @@ __initfunc (static void add_pci_ports(void)) { ...@@ -1099,7 +1111,7 @@ __initfunc (static void add_pci_ports(void)) {
continue; continue;
/* Reverse the returned address order */ /* Reverse the returned address order */
io_port[MAX_INT_PARAM + MAX_PCI - k] = io_port[MAX_INT_PARAM + MAX_PCI - k] =
(addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
} }
...@@ -1127,7 +1139,7 @@ __initfunc (static void add_pci_ports(void)) { ...@@ -1127,7 +1139,7 @@ __initfunc (static void add_pci_ports(void)) {
continue; continue;
/* Reverse the returned address order */ /* Reverse the returned address order */
io_port[MAX_INT_PARAM + MAX_PCI - k] = io_port[MAX_INT_PARAM + MAX_PCI - k] =
(addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0;
} }
...@@ -1166,7 +1178,7 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { ...@@ -1166,7 +1178,7 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) {
if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
} }
if (j > 0) if (j > 0)
printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n"); printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n");
num_boards = j; num_boards = j;
...@@ -1197,7 +1209,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1197,7 +1209,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
static const unsigned char data_out_cmds[] = { static const unsigned char data_out_cmds[] = {
0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e, 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
}; };
...@@ -1215,16 +1227,16 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1215,16 +1227,16 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) { if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
SCpnt->result = DID_OK << 16; SCpnt->result = DID_OK << 16;
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n", printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
restore_flags(flags); restore_flags(flags);
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
/* i is the mailbox number, look for the first free mailbox /* i is the mailbox number, look for the first free mailbox
starting from last_cp_used */ starting from last_cp_used */
i = HD(j)->last_cp_used + 1; i = HD(j)->last_cp_used + 1;
...@@ -1241,17 +1253,17 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1241,17 +1253,17 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
if (k == sh[j]->can_queue) { if (k == sh[j]->can_queue) {
printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
if (HD(j)->in_reset) if (HD(j)->in_reset)
printk("%s: qcomm, already in reset.\n", BN(j)); printk("%s: qcomm, already in reset.\n", BN(j));
else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
== SCSI_RESET_SUCCESS) == SCSI_RESET_SUCCESS)
panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
SCpnt->result = DID_BUS_BUSY << 16; SCpnt->result = DID_BUS_BUSY << 16;
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
restore_flags(flags); restore_flags(flags);
done(SCpnt); done(SCpnt);
return 1; return 1;
} }
...@@ -1261,13 +1273,12 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1261,13 +1273,12 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *)); memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *));
/* Set pointer to status packet structure */ /* Set pointer to status packet structure */
spp = &HD(j)->sp[i]; spp = &HD(j)->sp[0];
memset(spp, 0, sizeof(struct mssp));
/* The EATA protocol uses Big Endian format */ /* The EATA protocol uses Big Endian format */
cpp->sp_addr = V2DEV(spp); cpp->sp_addr = V2DEV(spp);
cpp->cpp = cpp;
SCpnt->scsi_done = done; SCpnt->scsi_done = done;
cpp->index = i; cpp->index = i;
SCpnt->host_scribble = (unsigned char *) &cpp->index; SCpnt->host_scribble = (unsigned char *) &cpp->index;
...@@ -1297,11 +1308,11 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1297,11 +1308,11 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
cpp->one = TRUE; cpp->one = TRUE;
cpp->channel = SCpnt->channel; cpp->channel = SCpnt->channel;
cpp->target = SCpnt->target; cpp->target = SCpnt->target;
cpp->lun = SCpnt->lun; cpp->lun = SCpnt->lun;
cpp->SCpnt = SCpnt; cpp->SCpnt = SCpnt;
cpp->sense_addr = V2DEV(SCpnt->sense_buffer); cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
cpp->sense_len = sizeof SCpnt->sense_buffer; cpp->sense_len = sizeof SCpnt->sense_buffer;
if (SCpnt->device->tagged_queue) { if (SCpnt->device->tagged_queue) {
if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] || if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] ||
...@@ -1341,13 +1352,13 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -1341,13 +1352,13 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
/* Send control packet to the board */ /* Send control packet to the board */
if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
SCpnt->result = DID_ERROR << 16; SCpnt->result = DID_ERROR << 16;
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\ printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
" done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
SCpnt->pid); SCpnt->pid);
restore_flags(flags); restore_flags(flags);
done(SCpnt); done(SCpnt);
return 1; return 1;
} }
...@@ -1373,7 +1384,7 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { ...@@ -1373,7 +1384,7 @@ int eata2x_abort(Scsi_Cmnd *SCarg) {
} }
i = *(unsigned int *)SCarg->host_scribble; i = *(unsigned int *)SCarg->host_scribble;
printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
if (i >= sh[j]->can_queue) if (i >= sh[j]->can_queue)
...@@ -1441,7 +1452,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1441,7 +1452,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
save_flags(flags); save_flags(flags);
cli(); cli();
j = ((struct hostdata *) SCarg->host->hostdata)->board_number; j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
reset_flags); reset_flags);
...@@ -1502,10 +1513,10 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1502,10 +1513,10 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
if (SCpnt->host_scribble == NULL) if (SCpnt->host_scribble == NULL)
panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
if (*(unsigned int *)SCpnt->host_scribble != i) if (*(unsigned int *)SCpnt->host_scribble != i)
panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
if (SCpnt->scsi_done == NULL) if (SCpnt->scsi_done == NULL)
panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
if (SCpnt == SCarg) arg_done = TRUE; if (SCpnt == SCarg) arg_done = TRUE;
...@@ -1588,7 +1599,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, ...@@ -1588,7 +1599,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
for (i = 0; i < n - 1; i++) { for (i = 0; i < n - 1; i++) {
k = i; k = i;
for (j = k + 1; j < n; j++) for (j = k + 1; j < n; j++)
if (rev) { if (rev) {
if (sk[j] > sk[k]) k = j; if (sk[j] > sk[k]) k = j;
} }
...@@ -1605,7 +1616,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, ...@@ -1605,7 +1616,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
return; return;
} }
static inline void reorder(unsigned int j, unsigned long cursec, static inline int reorder(unsigned int j, unsigned long cursec,
unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
Scsi_Cmnd *SCpnt; Scsi_Cmnd *SCpnt;
struct mscp *cpp; struct mscp *cpp;
...@@ -1625,10 +1636,10 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1625,10 +1636,10 @@ static inline void reorder(unsigned int j, unsigned long cursec,
printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
" av %ldK as %ldK.\n", flushcount, batchcount, inputcount, " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
ovlcount, readycount, readysorted, sortcount, revcount, ovlcount, readycount, readysorted, sortcount, revcount,
seeknosort / (readycount + 1), seeknosort / (readycount + 1),
seeksorted / (readycount + 1)); seeksorted / (readycount + 1));
if (n_ready <= 1) return; if (n_ready <= 1) return FALSE;
for (n = 0; n < n_ready; n++) { for (n = 0; n < n_ready; n++) {
k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
...@@ -1645,7 +1656,7 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1645,7 +1656,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
if (sl[n] < sl[n - 1]) s = FALSE; if (sl[n] < sl[n - 1]) s = FALSE;
if (sl[n] > sl[n - 1]) r = FALSE; if (sl[n] > sl[n - 1]) r = FALSE;
if (link_statistics) { if (link_statistics) {
if (sl[n] > sl[n - 1]) if (sl[n] > sl[n - 1])
seek += sl[n] - sl[n - 1]; seek += sl[n] - sl[n - 1];
...@@ -1670,7 +1681,7 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1670,7 +1681,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid; ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
if (!n) continue; if (!n) continue;
if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
|| (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE; || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
} }
...@@ -1679,9 +1690,9 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1679,9 +1690,9 @@ static inline void reorder(unsigned int j, unsigned long cursec,
if (link_statistics) { if (link_statistics) {
if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
batchcount++; readycount += n_ready, seeknosort += seek / 1024; batchcount++; readycount += n_ready, seeknosort += seek / 1024;
if (input_only) inputcount++; if (input_only) inputcount++;
if (overlap) { ovlcount++; seeksorted += seek / 1024; } if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
else seeksorted += (iseek + maxsec - minsec) / 1024; else seeksorted += (iseek + maxsec - minsec) / 1024;
if (rev && !r) { revcount++; readysorted += n_ready; } if (rev && !r) { revcount++; readysorted += n_ready; }
if (!rev && !s) { sortcount++; readysorted += n_ready; } if (!rev && !s) { sortcount++; readysorted += n_ready; }
...@@ -1696,10 +1707,11 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1696,10 +1707,11 @@ static inline void reorder(unsigned int j, unsigned long cursec,
(ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
SCpnt->request.sector, SCpnt->request.nr_sectors, cursec, SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
YESNO(overlap), cpp->din); YESNO(overlap), cpp->din);
} }
#endif #endif
return overlap;
} }
static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
...@@ -1721,13 +1733,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, ...@@ -1721,13 +1733,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
il[n_ready++] = k; il[n_ready++] = k;
} }
reorder(j, cursec, ihdlr, il, n_ready); if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
for (n = 0; n < n_ready; n++) { for (n = 0; n < n_ready; n++) {
k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\ printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
" busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"), " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k); SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
HD(j)->cp_stat[k] = ABORTING; HD(j)->cp_stat[k] = ABORTING;
...@@ -1739,196 +1751,201 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, ...@@ -1739,196 +1751,201 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
} }
static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { static inline void ihdlr(int irq, unsigned int j) {
Scsi_Cmnd *SCpnt; Scsi_Cmnd *SCpnt;
unsigned int i, j, k, c, status, tstatus, reg; unsigned int i, k, c, status, tstatus, reg;
unsigned int n, n_ready, il[MAX_MAILBOXES]; struct mssp *dspp, *spp;
struct mssp *spp;
struct mscp *cpp; struct mscp *cpp;
/* Check if the interrupt must be processed by this handler */
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
if (sh[j]->irq != irq) if (sh[j]->irq != irq)
panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq); panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
HD(j)->iocount);
/* Check if this board need to be serviced */ /* Check if this board need to be serviced */
if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return; if (!(inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)) return;
n_ready = 0; HD(j)->iocount++;
/* Find the mailboxes to be serviced on this board */
for (i = 0; i < sh[j]->can_queue; i++) {
spp = &HD(j)->sp[i];
/* Check if this mailbox has completed the operation */ if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
if (spp->eoc == FALSE) continue; HD(j)->iocount);
spp->eoc = FALSE; /* Check if this board is still busy */
il[n_ready++] = i; if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
reg = inb(sh[j]->io_port + REG_STATUS);
printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n",
BN(j), irq, reg, HD(j)->iocount);
return;
} }
dspp = &HD(j)->sp[0];
spp = &HD(j)->sp[1];
/* Make a local copy just before clearing the interrupt indication */
memcpy(spp, dspp, sizeof(struct mssp));
/* Clear the completion flag and cp pointer on the dynamic copy of sp */
memset(dspp, 0, sizeof(struct mssp));
/* Read the status register to clear the interrupt indication */ /* Read the status register to clear the interrupt indication */
reg = inb(sh[j]->io_port + REG_STATUS); reg = inb(sh[j]->io_port + REG_STATUS);
/* Mailbox service loop */ /* Reject any sp with supspect data */
for (n = 0; n < n_ready; n++) { if (spp->eoc == FALSE)
i = il[n]; printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n",
spp = &HD(j)->sp[i]; BN(j), irq, reg, HD(j)->iocount);
if (spp->cpp == NULL)
printk("%s: ihdlr, spp->cpp == NULL, irq %d, reg 0x%x, count %d.\n",
BN(j), irq, reg, HD(j)->iocount);
if (spp->eoc == FALSE || spp->cpp == NULL) return;
if (HD(j)->cp_stat[i] == IGNORE) { cpp = spp->cpp;
HD(j)->cp_stat[i] = FREE;
return;
}
else if (HD(j)->cp_stat[i] == LOCKED) {
HD(j)->cp_stat[i] = FREE;
printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
HD(j)->iocount);
return;
}
else if (HD(j)->cp_stat[i] == FREE) {
printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
HD(j)->iocount);
return;
}
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: %d.\n",
BN(j), i, HD(j)->cp_stat[i]);
/* Find the mailbox to be serviced on this board */
i = cpp - HD(j)->cp;
if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
|| i >= sh[j]->can_queue)
panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
cpp, HD(j)->cp);
if (HD(j)->cp_stat[i] == IGNORE) {
HD(j)->cp_stat[i] = FREE; HD(j)->cp_stat[i] = FREE;
cpp = &HD(j)->cp[i]; return;
SCpnt = spp->SCpnt; }
else if (HD(j)->cp_stat[i] == LOCKED) {
HD(j)->cp_stat[i] = FREE;
printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i,
HD(j)->iocount);
return;
}
else if (HD(j)->cp_stat[i] == FREE) {
printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i,
HD(j)->iocount);
return;
}
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: %d.\n",
BN(j), i, HD(j)->cp_stat[i]);
if(SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); HD(j)->cp_stat[i] = FREE;
SCpnt = cpp->SCpnt;
if (SCpnt != cpp->SCpnt) if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
panic("%s: ihdlr, mbox %d, sp SCpnt %p, cp SCpnt %p.\n", BN(j), i,
SCpnt, cpp->SCpnt);
if (SCpnt->host_scribble == NULL) if (SCpnt->host_scribble == NULL)
panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
SCpnt->pid, SCpnt); SCpnt->pid, SCpnt);
if (*(unsigned int *)SCpnt->host_scribble != i) if (*(unsigned int *)SCpnt->host_scribble != i)
panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq); BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
if (linked_comm && SCpnt->device->queue_depth > 2 if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type)) && TLDEV(SCpnt->device->type))
flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE); flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE);
tstatus = status_byte(spp->target_status); tstatus = status_byte(spp->target_status);
switch (spp->adapter_status) { switch (spp->adapter_status) {
case ASOK: /* status OK */ case ASOK: /* status OK */
/* Forces a reset if a disk drive keeps returning BUSY */ /* Forces a reset if a disk drive keeps returning BUSY */
if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
status = DID_ERROR << 16;
/* If there was a bus reset, redo operation on each target */
else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
&& HD(j)->target_redo[SCpnt->target][SCpnt->channel])
status = DID_BUS_BUSY << 16;
/* Works around a flaw in scsi.c */
else if (tstatus == CHECK_CONDITION
&& SCpnt->device->type == TYPE_DISK
&& (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
status = DID_BUS_BUSY << 16;
else
status = DID_OK << 16;
if (tstatus == GOOD)
HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
if (spp->target_status && SCpnt->device->type == TYPE_DISK)
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
"target_status 0x%x, sense key 0x%x.\n", BN(j),
SCpnt->channel, SCpnt->target, SCpnt->lun,
SCpnt->pid, spp->target_status,
SCpnt->sense_buffer[2]);
HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
break;
case ASST: /* Selection Time Out */
case 0x02: /* Command Time Out */
if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
status = DID_ERROR << 16;
else {
status = DID_TIME_OUT << 16;
HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
}
break;
/* Perform a limited number of internal retries */
case 0x03: /* SCSI Bus Reset Received */
case 0x04: /* Initial Controller Power-up */
for (c = 0; c <= sh[j]->max_channel; c++)
for (k = 0; k < sh[j]->max_id; k++)
HD(j)->target_redo[k][c] = TRUE;
if (SCpnt->device->type != TYPE_TAPE
&& HD(j)->retries < MAX_INTERNAL_RETRIES) {
status = DID_BUS_BUSY << 16;
HD(j)->retries++;
HD(j)->last_retried_pid = SCpnt->pid;
}
else
status = DID_ERROR << 16;
break;
case 0x05: /* Unexpected Bus Phase */
case 0x06: /* Unexpected Bus Free */
case 0x07: /* Bus Parity Error */
case 0x08: /* SCSI Hung */
case 0x09: /* Unexpected Message Reject */
case 0x0a: /* SCSI Bus Reset Stuck */
case 0x0b: /* Auto Request-Sense Failed */
case 0x0c: /* Controller Ram Parity Error */
default:
status = DID_ERROR << 16; status = DID_ERROR << 16;
break;
}
SCpnt->result = status | spp->target_status; /* If there was a bus reset, redo operation on each target */
HD(j)->iocount++; else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
&& HD(j)->target_redo[SCpnt->target][SCpnt->channel])
status = DID_BUS_BUSY << 16;
/* Works around a flaw in scsi.c */
else if (tstatus == CHECK_CONDITION
&& SCpnt->device->type == TYPE_DISK
&& (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR)
status = DID_BUS_BUSY << 16;
else
status = DID_OK << 16;
if (tstatus == GOOD)
HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
if (spp->target_status && SCpnt->device->type == TYPE_DISK)
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
"target_status 0x%x, sense key 0x%x.\n", BN(j),
SCpnt->channel, SCpnt->target, SCpnt->lun,
SCpnt->pid, spp->target_status,
SCpnt->sense_buffer[2]);
HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
break;
case ASST: /* Selection Time Out */
case 0x02: /* Command Time Out */
if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
status = DID_ERROR << 16;
else {
status = DID_TIME_OUT << 16;
HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
}
break;
/* Perform a limited number of internal retries */
case 0x03: /* SCSI Bus Reset Received */
case 0x04: /* Initial Controller Power-up */
for (c = 0; c <= sh[j]->max_channel; c++)
for (k = 0; k < sh[j]->max_id; k++)
HD(j)->target_redo[k][c] = TRUE;
if (SCpnt->device->type != TYPE_TAPE
&& HD(j)->retries < MAX_INTERNAL_RETRIES) {
status = DID_BUS_BUSY << 16;
HD(j)->retries++;
HD(j)->last_retried_pid = SCpnt->pid;
}
else
status = DID_ERROR << 16;
break;
case 0x05: /* Unexpected Bus Phase */
case 0x06: /* Unexpected Bus Free */
case 0x07: /* Bus Parity Error */
case 0x08: /* SCSI Hung */
case 0x09: /* Unexpected Message Reject */
case 0x0a: /* SCSI Bus Reset Stuck */
case 0x0b: /* Auto Request-Sense Failed */
case 0x0c: /* Controller Ram Parity Error */
default:
status = DID_ERROR << 16;
break;
}
SCpnt->result = status | spp->target_status;
#if defined (DEBUG_INTERRUPT) #if defined (DEBUG_INTERRUPT)
if (SCpnt->result || do_trace) if (SCpnt->result || do_trace)
#else #else
if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) ||
(spp->adapter_status != ASOK && (spp->adapter_status != ASOK &&
spp->adapter_status != ASST && HD(j)->iocount <= 1000) || spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
do_trace || msg_byte(spp->target_status)) do_trace || msg_byte(spp->target_status))
#endif #endif
printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
" target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n",
BN(j), i, spp->adapter_status, spp->target_status, BN(j), i, spp->adapter_status, spp->target_status,
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
reg, HD(j)->iocount); reg, HD(j)->iocount);
/* Set the command state to inactive */ /* Set the command state to inactive */
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
SCpnt->scsi_done(SCpnt);
} /* Mailbox loop */ SCpnt->scsi_done(SCpnt);
if (n_ready > 1)
printk("%s: ihdlr, multiple commands (%d) completed.\n", BN(j), n_ready);
if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq,
HD(j)->iocount); HD(j)->iocount);
...@@ -1938,18 +1955,22 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1938,18 +1955,22 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) { static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) unsigned int j;
/* Check if the interrupt must be processed by this handler */
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
{
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags); spin_lock_irqsave(&io_request_lock, flags);
ihdlr(irq, shap, regs); ihdlr(irq, j);
spin_unlock_irqrestore(&io_request_lock, flags); spin_unlock_irqrestore(&io_request_lock, flags);
}
#else #else
ihdlr(irq, j);
ihdlr(irq, shap, regs);
#endif #endif
} }
int eata2x_release(struct Scsi_Host *shpnt) { int eata2x_release(struct Scsi_Host *shpnt) {
...@@ -1960,11 +1981,11 @@ int eata2x_release(struct Scsi_Host *shpnt) { ...@@ -1960,11 +1981,11 @@ int eata2x_release(struct Scsi_Host *shpnt) {
cli(); cli();
for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n", if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
driver_name); driver_name);
for (i = 0; i < sh[j]->can_queue; i++) for (i = 0; i < sh[j]->can_queue; i++)
if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
free_irq(sh[j]->irq, &sha[j]); free_irq(sh[j]->irq, &sha[j]);
......
...@@ -13,7 +13,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); ...@@ -13,7 +13,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int eata2x_abort(Scsi_Cmnd *); int eata2x_abort(Scsi_Cmnd *);
int eata2x_reset(Scsi_Cmnd *, unsigned int); int eata2x_reset(Scsi_Cmnd *, unsigned int);
#define EATA_VERSION "4.04.00" #define EATA_VERSION "4.20.00"
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $ $Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
*/ */
#include <linux/config.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
/* It is senseless to set SG_ALL any higher than this - the performance /* It is senseless to set SG_ALL any higher than this - the performance
......
/* /*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
* *
* 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97
* Reworked interrupt handler.
*
* 11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95
* Major reliability improvement: when a batch with overlapping
* requests is detected, requests are queued one at a time
* eliminating any possible board or drive reordering.
*
* 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95
* Improved SMP support (if linux version >= 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 * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94
* Performance improvement: when sequential i/o is detected, * Performance improvement: when sequential i/o is detected,
* always use direct sort instead of reverse sort. * always use direct sort instead of reverse sort.
* *
* 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92
* io_port is now unsigned long. * io_port is now unsigned long.
* *
...@@ -35,7 +43,7 @@ ...@@ -35,7 +43,7 @@
* Fixed data transfer direction for some SCSI opcodes. * Fixed data transfer direction for some SCSI opcodes.
* Immediate acknowledge to request sense commands. * Immediate acknowledge to request sense commands.
* Linked commands to each disk device are now reordered by elevator * Linked commands to each disk device are now reordered by elevator
* sorting. Rare cases in which reordering of write requests could * sorting. Rare cases in which reordering of write requests could
* cause wrong results are managed. * cause wrong results are managed.
* *
* 18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28 * 18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28
...@@ -119,12 +127,12 @@ ...@@ -119,12 +127,12 @@
* 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release. * 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release.
* 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release. * 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release.
* *
* This driver is a total replacement of the original UltraStor * This driver is a total replacement of the original UltraStor
* scsi driver, but it supports ONLY the 14F and 34F boards. * scsi driver, but it supports ONLY the 14F and 34F boards.
* It can be configured in the same kernel in which the original * It can be configured in the same kernel in which the original
* ultrastor driver is configured to allow the original U24F * ultrastor driver is configured to allow the original U24F
* support. * support.
* *
* Multiple U14F and/or U34F host adapters are supported. * Multiple U14F and/or U34F host adapters are supported.
* *
* Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com) * Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com)
...@@ -148,11 +156,11 @@ ...@@ -148,11 +156,11 @@
* 24F - EISA Bus Master HA with floppy support and WD1003 emulation. * 24F - EISA Bus Master HA with floppy support and WD1003 emulation.
* 34F - VESA Local-Bus Bus Master HA (no WD1003 emulation). * 34F - VESA Local-Bus Bus Master HA (no WD1003 emulation).
* *
* This code has been tested with up to two U14F boards, using both * This code has been tested with up to two U14F boards, using both
* firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware * firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware
* 28004-006/38004-005 (BIOS rev. 2.01). * 28004-006/38004-005 (BIOS rev. 2.01).
* *
* The latest firmware is required in order to get reliable operations when * The latest firmware is required in order to get reliable operations when
* clustering is enabled. ENABLE_CLUSTERING provides a performance increase * clustering is enabled. ENABLE_CLUSTERING provides a performance increase
* up to 50% on sequential access. * up to 50% on sequential access.
* *
...@@ -168,24 +176,24 @@ ...@@ -168,24 +176,24 @@
* have their BIOS disabled, or enabled to an higher address. * have their BIOS disabled, or enabled to an higher address.
* Boards are named Ux4F0, Ux4F1..., according to the port address order in * Boards are named Ux4F0, Ux4F1..., according to the port address order in
* the io_port[] array. * the io_port[] array.
* *
* The following facts are based on real testing results (not on * The following facts are based on real testing results (not on
* documentation) on the above U14F board. * documentation) on the above U14F board.
* *
* - The U14F board should be jumpered for bus on time less or equal to 7 * - The U14F board should be jumpered for bus on time less or equal to 7
* microseconds, while the default is 11 microseconds. This is order to * microseconds, while the default is 11 microseconds. This is order to
* get acceptable performance while using floppy drive and hard disk * get acceptable performance while using floppy drive and hard disk
* together. The jumpering for 7 microseconds is: JP13 pin 15-16, * together. The jumpering for 7 microseconds is: JP13 pin 15-16,
* JP14 pin 7-8 and pin 9-10. * JP14 pin 7-8 and pin 9-10.
* The reduction has a little impact on scsi performance. * The reduction has a little impact on scsi performance.
* *
* - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced * - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced
* from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8). * from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8).
* *
* - If U14F on board firmware is older than 28004-006/38004-005, * - If U14F on board firmware is older than 28004-006/38004-005,
* the U14F board is unable to provide reliable operations if the scsi * the U14F board is unable to provide reliable operations if the scsi
* request length exceeds 16Kbyte. When this length is exceeded the * request length exceeds 16Kbyte. When this length is exceeded the
* behavior is: * behavior is:
* - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94; * - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94;
* - adapter_status equal 0 and target_status equal 2 on for all targets * - adapter_status equal 0 and target_status equal 2 on for all targets
* in the next operation following the reset. * in the next operation following the reset.
...@@ -199,7 +207,7 @@ ...@@ -199,7 +207,7 @@
* Any reset of the scsi bus is going to kill tape operations, since * Any reset of the scsi bus is going to kill tape operations, since
* no retry is allowed for tapes. Bus resets are more likely when the * no retry is allowed for tapes. Bus resets are more likely when the
* scsi bus is under heavy load. * scsi bus is under heavy load.
* Requests using scatter/gather have a maximum length of 16 x 1024 bytes * Requests using scatter/gather have a maximum length of 16 x 1024 bytes
* when DISABLE_CLUSTERING is in effect, but unscattered requests could be * when DISABLE_CLUSTERING is in effect, but unscattered requests could be
* larger than 16Kbyte. * larger than 16Kbyte.
* *
...@@ -246,15 +254,15 @@ ...@@ -246,15 +254,15 @@
* in the elevator sorting queue. When the active command completes, the * in the elevator sorting queue. When the active command completes, the
* commands in this queue are sorted by sector address. The sort is chosen * commands in this queue are sorted by sector address. The sort is chosen
* between increasing or decreasing by minimizing the seek distance between * between increasing or decreasing by minimizing the seek distance between
* the sector of the commands just completed and the sector of the first * the sector of the commands just completed and the sector of the first
* command in the list to be sorted. * command in the list to be sorted.
* Trivial math assures that the unsorted average seek distance when doing * Trivial math assures that the unsorted average seek distance when doing
* random seeks over S sectors is S/3. * random seeks over S sectors is S/3.
* When (Q-1) requests are uniformly distributed over S sectors, the average * When (Q-1) requests are uniformly distributed over S sectors, the average
* distance between two adjacent requests is S/((Q-1) + 1), so the sorted * distance between two adjacent requests is S/((Q-1) + 1), so the sorted
* average seek distance for (Q-1) random requests over S sectors is S/Q. * average seek distance for (Q-1) random requests over S sectors is S/Q.
* The elevator sorting hence divides the seek distance by a factor Q/3. * The elevator sorting hence divides the seek distance by a factor Q/3.
* The above pure geometric remarks are valid in all cases and the * The above pure geometric remarks are valid in all cases and the
* driver effectively reduces the seek distance by the predicted factor * driver effectively reduces the seek distance by the predicted factor
* when there are Q concurrent read i/o operations on the device, but this * when there are Q concurrent read i/o operations on the device, but this
* does not necessarily results in a noticeable performance improvement: * does not necessarily results in a noticeable performance improvement:
...@@ -262,7 +270,7 @@ ...@@ -262,7 +270,7 @@
* *
* Note: command reordering inside a batch of queued commands could cause * Note: command reordering inside a batch of queued commands could cause
* wrong results only if there is at least one write request and the * wrong results only if there is at least one write request and the
* intersection (sector-wise) of all requests is not empty. * intersection (sector-wise) of all requests is not empty.
* When the driver detects a batch including overlapping requests * When the driver detects a batch including overlapping requests
* (a really rare event) strict serial (pid) order is enforced. * (a really rare event) strict serial (pid) order is enforced.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
...@@ -300,6 +308,11 @@ MODULE_AUTHOR("Dario Ballabio"); ...@@ -300,6 +308,11 @@ MODULE_AUTHOR("Dario Ballabio");
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
#include <asm/spinlock.h>
#endif
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/blk.h> #include <linux/blk.h>
#include "scsi.h" #include "scsi.h"
...@@ -350,7 +363,7 @@ struct proc_dir_entry proc_scsi_u14_34f = { ...@@ -350,7 +363,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
#undef DEBUG_RESET #undef DEBUG_RESET
#define MAX_ISA 3 #define MAX_ISA 3
#define MAX_VESA 1 #define MAX_VESA 1
#define MAX_EISA 0 #define MAX_EISA 0
#define MAX_PCI 0 #define MAX_PCI 0
#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI) #define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)
...@@ -462,7 +475,7 @@ static char sha[MAX_BOARDS]; ...@@ -462,7 +475,7 @@ static char sha[MAX_BOARDS];
/* Initialize num_boards so that ihdlr can work while detect is in progress */ /* Initialize num_boards so that ihdlr can work while detect is in progress */
static unsigned int num_boards = MAX_BOARDS; static unsigned int num_boards = MAX_BOARDS;
static unsigned long io_port[] __initdata = { static unsigned long io_port[] __initdata = {
/* Space for MAX_INT_PARAM ports usable while loading as a module */ /* Space for MAX_INT_PARAM ports usable while loading as a module */
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
...@@ -494,7 +507,7 @@ static unsigned long io_port[] __initdata = { ...@@ -494,7 +507,7 @@ static unsigned long io_port[] __initdata = {
#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0) #define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0) #define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
static void interrupt_handler(int, void *, struct pt_regs *); static void do_interrupt_handler(int, void *, struct pt_regs *);
static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);
static int do_trace = FALSE; static int do_trace = FALSE;
static int setup_done = FALSE; static int setup_done = FALSE;
...@@ -520,7 +533,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN; ...@@ -520,7 +533,7 @@ static int max_queue_depth = MAX_CMD_PER_LUN;
static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
Scsi_Device *dev; Scsi_Device *dev;
int j, ntag = 0, nuntag = 0, tqd, utqd; int j, ntag = 0, nuntag = 0, tqd, utqd;
unsigned long flags; unsigned long flags;
save_flags(flags); save_flags(flags);
...@@ -637,23 +650,23 @@ __initfunc (static inline int port_detect \ ...@@ -637,23 +650,23 @@ __initfunc (static inline int port_detect \
char *bus_type, dma_name[16]; char *bus_type, dma_name[16];
/* Allowed BIOS base addresses (NULL indicates reserved) */ /* Allowed BIOS base addresses (NULL indicates reserved) */
void *bios_segment_table[8] = { void *bios_segment_table[8] = {
NULL, NULL,
(void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000, (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000,
(void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000 (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000
}; };
/* Allowed IRQs */ /* Allowed IRQs */
unsigned char interrupt_table[4] = { 15, 14, 11, 10 }; unsigned char interrupt_table[4] = { 15, 14, 11, 10 };
/* Allowed DMA channels for ISA (0 indicates reserved) */ /* Allowed DMA channels for ISA (0 indicates reserved) */
unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
/* Head/sector mappings */ /* Head/sector mappings */
struct { struct {
unsigned char heads; unsigned char heads;
unsigned char sectors; unsigned char sectors;
} mapping_table[4] = { } mapping_table[4] = {
{ 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }
}; };
...@@ -694,7 +707,7 @@ __initfunc (static inline int port_detect \ ...@@ -694,7 +707,7 @@ __initfunc (static inline int port_detect \
subversion = (in_byte & 0x0f); subversion = (in_byte & 0x0f);
/* Board detected, allocate its IRQ */ /* Board detected, allocate its IRQ */
if (request_irq(irq, interrupt_handler, if (request_irq(irq, do_interrupt_handler,
SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
driver_name, (void *) &sha[j])) { driver_name, (void *) &sha[j])) {
printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
...@@ -797,14 +810,14 @@ __initfunc (static inline int port_detect \ ...@@ -797,14 +810,14 @@ __initfunc (static inline int port_detect \
for (i = 0; i < sh[j]->can_queue; i++) for (i = 0; i < sh[j]->can_queue; i++)
if (! ((&HD(j)->cp[i])->sglist = kmalloc( if (! ((&HD(j)->cp[i])->sglist = kmalloc(
sh[j]->sg_tablesize * sizeof(struct sg_list), sh[j]->sg_tablesize * sizeof(struct sg_list),
(sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {
printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);
u14_34f_release(sh[j]); u14_34f_release(sh[j]);
return FALSE; return FALSE;
} }
if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)
max_queue_depth = MAX_TAGGED_CMD_PER_LUN; max_queue_depth = MAX_TAGGED_CMD_PER_LUN;
if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
...@@ -834,8 +847,8 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) { ...@@ -834,8 +847,8 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) {
if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM; if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM;
for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; for (i = 0; i < argc; i++) io_port[i] = ints[i + 1];
io_port[i] = 0; io_port[i] = 0;
setup_done = TRUE; setup_done = TRUE;
} }
...@@ -884,7 +897,7 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) { ...@@ -884,7 +897,7 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) {
if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;
} }
if (j > 0) if (j > 0)
printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n"); printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n");
num_boards = j; num_boards = j;
...@@ -916,7 +929,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -916,7 +929,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
static const unsigned char data_out_cmds[] = { static const unsigned char data_out_cmds[] = {
0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e, 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,
0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,
0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b
}; };
...@@ -934,16 +947,16 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -934,16 +947,16 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid);
if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) { if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) {
SCpnt->result = DID_OK << 16; SCpnt->result = DID_OK << 16;
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n", printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n",
BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid);
restore_flags(flags); restore_flags(flags);
done(SCpnt); done(SCpnt);
return 0; return 0;
} }
/* i is the mailbox number, look for the first free mailbox /* i is the mailbox number, look for the first free mailbox
starting from last_cp_used */ starting from last_cp_used */
i = HD(j)->last_cp_used + 1; i = HD(j)->last_cp_used + 1;
...@@ -960,17 +973,17 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -960,17 +973,17 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
if (k == sh[j]->can_queue) { if (k == sh[j]->can_queue) {
printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); printk("%s: qcomm, no free mailbox, resetting.\n", BN(j));
if (HD(j)->in_reset) if (HD(j)->in_reset)
printk("%s: qcomm, already in reset.\n", BN(j)); printk("%s: qcomm, already in reset.\n", BN(j));
else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET)
== SCSI_RESET_SUCCESS) == SCSI_RESET_SUCCESS)
panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j));
SCpnt->result = DID_BUS_BUSY << 16; SCpnt->result = DID_BUS_BUSY << 16;
SCpnt->host_scribble = NULL; SCpnt->host_scribble = NULL;
printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid);
restore_flags(flags); restore_flags(flags);
done(SCpnt); done(SCpnt);
return 1; return 1;
} }
...@@ -983,7 +996,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { ...@@ -983,7 +996,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
SCpnt->host_scribble = (unsigned char *) &cpp->index; SCpnt->host_scribble = (unsigned char *) &cpp->index;
if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
BN(j), i, SCpnt->channel, SCpnt->target, BN(j), i, SCpnt->channel, SCpnt->target,
SCpnt->lun, SCpnt->pid); SCpnt->lun, SCpnt->pid);
cpp->xdir = DTD_IN; cpp->xdir = DTD_IN;
...@@ -1136,7 +1149,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1136,7 +1149,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
save_flags(flags); save_flags(flags);
cli(); cli();
j = ((struct hostdata *) SCarg->host->hostdata)->board_number; j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n",
BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
reset_flags); reset_flags);
...@@ -1197,10 +1210,10 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1197,10 +1210,10 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
if (SCpnt->host_scribble == NULL) if (SCpnt->host_scribble == NULL)
panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i);
if (*(unsigned int *)SCpnt->host_scribble != i) if (*(unsigned int *)SCpnt->host_scribble != i)
panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i);
if (SCpnt->scsi_done == NULL) if (SCpnt->scsi_done == NULL)
panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i);
if (SCpnt == SCarg) arg_done = TRUE; if (SCpnt == SCarg) arg_done = TRUE;
...@@ -1294,7 +1307,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, ...@@ -1294,7 +1307,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
for (i = 0; i < n - 1; i++) { for (i = 0; i < n - 1; i++) {
k = i; k = i;
for (j = k + 1; j < n; j++) for (j = k + 1; j < n; j++)
if (rev) { if (rev) {
if (sk[j] > sk[k]) k = j; if (sk[j] > sk[k]) k = j;
} }
...@@ -1311,7 +1324,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n, ...@@ -1311,7 +1324,7 @@ static void sort(unsigned long sk[], unsigned int da[], unsigned int n,
return; return;
} }
static inline void reorder(unsigned int j, unsigned long cursec, static inline int reorder(unsigned int j, unsigned long cursec,
unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { unsigned int ihdlr, unsigned int il[], unsigned int n_ready) {
Scsi_Cmnd *SCpnt; Scsi_Cmnd *SCpnt;
struct mscp *cpp; struct mscp *cpp;
...@@ -1331,10 +1344,10 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1331,10 +1344,10 @@ static inline void reorder(unsigned int j, unsigned long cursec,
printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\
" av %ldK as %ldK.\n", flushcount, batchcount, inputcount, " av %ldK as %ldK.\n", flushcount, batchcount, inputcount,
ovlcount, readycount, readysorted, sortcount, revcount, ovlcount, readycount, readysorted, sortcount, revcount,
seeknosort / (readycount + 1), seeknosort / (readycount + 1),
seeksorted / (readycount + 1)); seeksorted / (readycount + 1));
if (n_ready <= 1) return; if (n_ready <= 1) return FALSE;
for (n = 0; n < n_ready; n++) { for (n = 0; n < n_ready; n++) {
k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
...@@ -1351,7 +1364,7 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1351,7 +1364,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
if (sl[n] < sl[n - 1]) s = FALSE; if (sl[n] < sl[n - 1]) s = FALSE;
if (sl[n] > sl[n - 1]) r = FALSE; if (sl[n] > sl[n - 1]) r = FALSE;
if (link_statistics) { if (link_statistics) {
if (sl[n] > sl[n - 1]) if (sl[n] > sl[n - 1])
seek += sl[n] - sl[n - 1]; seek += sl[n] - sl[n - 1];
...@@ -1376,7 +1389,7 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1376,7 +1389,7 @@ static inline void reorder(unsigned int j, unsigned long cursec,
ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid; ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid;
if (!n) continue; if (!n) continue;
if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n]))
|| (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE; || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE;
} }
...@@ -1385,9 +1398,9 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1385,9 +1398,9 @@ static inline void reorder(unsigned int j, unsigned long cursec,
if (link_statistics) { if (link_statistics) {
if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec;
batchcount++; readycount += n_ready, seeknosort += seek / 1024; batchcount++; readycount += n_ready, seeknosort += seek / 1024;
if (input_only) inputcount++; if (input_only) inputcount++;
if (overlap) { ovlcount++; seeksorted += seek / 1024; } if (overlap) { ovlcount++; seeksorted += iseek / 1024; }
else seeksorted += (iseek + maxsec - minsec) / 1024; else seeksorted += (iseek + maxsec - minsec) / 1024;
if (rev && !r) { revcount++; readysorted += n_ready; } if (rev && !r) { revcount++; readysorted += n_ready; }
if (!rev && !s) { sortcount++; readysorted += n_ready; } if (!rev && !s) { sortcount++; readysorted += n_ready; }
...@@ -1402,10 +1415,11 @@ static inline void reorder(unsigned int j, unsigned long cursec, ...@@ -1402,10 +1415,11 @@ static inline void reorder(unsigned int j, unsigned long cursec,
(ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target,
SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, SCpnt->lun, SCpnt->pid, k, flushcount, n_ready,
SCpnt->request.sector, SCpnt->request.nr_sectors, cursec, SCpnt->request.sector, SCpnt->request.nr_sectors, cursec,
YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only),
YESNO(overlap), cpp->xdir); YESNO(overlap), cpp->xdir);
} }
#endif #endif
return overlap;
} }
static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
...@@ -1427,13 +1441,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, ...@@ -1427,13 +1441,13 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
il[n_ready++] = k; il[n_ready++] = k;
} }
reorder(j, cursec, ihdlr, il, n_ready); if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1;
for (n = 0; n < n_ready; n++) { for (n = 0; n < n_ready; n++) {
k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt;
if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
printk("%s: %s, target %d.%d:%d, pid %ld, Mbox %d, adapter"\ printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\
" busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"), " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"),
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k); SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k);
HD(j)->cp_stat[k] = ABORTING; HD(j)->cp_stat[k] = ABORTING;
...@@ -1444,33 +1458,43 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, ...@@ -1444,33 +1458,43 @@ static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j,
outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
HD(j)->cp_stat[k] = IN_USE; HD(j)->cp_stat[k] = IN_USE;
} }
} }
static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { static inline void ihdlr(int irq, unsigned int j) {
Scsi_Cmnd *SCpnt; Scsi_Cmnd *SCpnt;
unsigned int i, j, k, c, status, tstatus, reg, ret; unsigned int i, k, c, status, tstatus, reg, ret;
struct mscp *spp; struct mscp *spp, *cpp;
/* Check if the interrupt must be processed by this handler */
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
if (sh[j]->irq != irq) if (sh[j]->irq != irq)
panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq); panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
/* Check if this board need to be serviced */
if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return;
HD(j)->iocount++;
if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq, if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq,
HD(j)->iocount); HD(j)->iocount);
/* Check if this board need to be serviced */ /* Check if this board is still busy */
if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return; if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n",
BN(j), irq, reg, HD(j)->iocount);
return;
}
spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM)); spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM));
cpp = spp;
/* Clear interrupt pending flag */ /* Clear interrupt pending flag */
outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
i = spp - HD(j)->cp; /* Find the mailbox to be serviced on this board */
i = cpp - HD(j)->cp;
if (spp < HD(j)->cp || spp >= HD(j)->cp + sh[j]->can_queue if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue
|| i >= sh[j]->can_queue) || i >= sh[j]->can_queue)
panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j), panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j),
(void *)ret, HD(j)->cp); (void *)ret, HD(j)->cp);
...@@ -1492,22 +1516,22 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1492,22 +1516,22 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
} }
else if (HD(j)->cp_stat[i] == IN_RESET) else if (HD(j)->cp_stat[i] == IN_RESET)
printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i);
else if (HD(j)->cp_stat[i] != IN_USE) else if (HD(j)->cp_stat[i] != IN_USE)
panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n",
BN(j), i, HD(j)->cp_stat[i]); BN(j), i, HD(j)->cp_stat[i]);
HD(j)->cp_stat[i] = FREE; HD(j)->cp_stat[i] = FREE;
SCpnt = spp->SCpnt; SCpnt = cpp->SCpnt;
if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i);
if (SCpnt->host_scribble == NULL) if (SCpnt->host_scribble == NULL)
panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i,
SCpnt->pid, SCpnt); SCpnt->pid, SCpnt);
if (*(unsigned int *)SCpnt->host_scribble != i) if (*(unsigned int *)SCpnt->host_scribble != i)
panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d, irq %d.\n", panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n",
BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble, irq); BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble);
if (linked_comm && SCpnt->device->queue_depth > 2 if (linked_comm && SCpnt->device->queue_depth > 2
&& TLDEV(SCpnt->device->type)) && TLDEV(SCpnt->device->type))
...@@ -1519,7 +1543,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1519,7 +1543,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
case ASOK: /* status OK */ case ASOK: /* status OK */
/* Forces a reset if a disk drive keeps returning BUSY */ /* Forces a reset if a disk drive keeps returning BUSY */
if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE)
status = DID_ERROR << 16; status = DID_ERROR << 16;
/* If there was a bus reset, redo operation on each target */ /* If there was a bus reset, redo operation on each target */
...@@ -1541,7 +1565,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1541,7 +1565,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
if (spp->target_status && SCpnt->device->type == TYPE_DISK) if (spp->target_status && SCpnt->device->type == TYPE_DISK)
printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
"target_status 0x%x, sense key 0x%x.\n", BN(j), "target_status 0x%x, sense key 0x%x.\n", BN(j),
SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->channel, SCpnt->target, SCpnt->lun,
SCpnt->pid, spp->target_status, SCpnt->pid, spp->target_status,
SCpnt->sense_buffer[2]); SCpnt->sense_buffer[2]);
...@@ -1568,10 +1592,10 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1568,10 +1592,10 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
case 0x96: /* Illegal SCSI command */ case 0x96: /* Illegal SCSI command */
case 0xa3: /* SCSI bus reset error */ case 0xa3: /* SCSI bus reset error */
for (c = 0; c <= sh[j]->max_channel; c++) for (c = 0; c <= sh[j]->max_channel; c++)
for (k = 0; k < sh[j]->max_id; k++) for (k = 0; k < sh[j]->max_id; k++)
HD(j)->target_redo[k][c] = TRUE; HD(j)->target_redo[k][c] = TRUE;
case 0x92: /* Data over/under-run */ case 0x92: /* Data over/under-run */
...@@ -1581,7 +1605,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1581,7 +1605,7 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
HD(j)->retries++; HD(j)->retries++;
HD(j)->last_retried_pid = SCpnt->pid; HD(j)->last_retried_pid = SCpnt->pid;
} }
else else
status = DID_ERROR << 16; status = DID_ERROR << 16;
break; break;
...@@ -1598,13 +1622,12 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1598,13 +1622,12 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
} }
SCpnt->result = status | spp->target_status; SCpnt->result = status | spp->target_status;
HD(j)->iocount++;
#if defined (DEBUG_INTERRUPT) #if defined (DEBUG_INTERRUPT)
if (SCpnt->result || do_trace) if (SCpnt->result || do_trace)
#else #else
if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) ||
(spp->adapter_status != ASOK && (spp->adapter_status != ASOK &&
spp->adapter_status != ASST && HD(j)->iocount <= 1000) || spp->adapter_status != ASST && HD(j)->iocount <= 1000) ||
do_trace || msg_byte(spp->target_status)) do_trace || msg_byte(spp->target_status))
#endif #endif
...@@ -1625,20 +1648,24 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) { ...@@ -1625,20 +1648,24 @@ static inline void ihdlr(int irq, void *shap, struct pt_regs *regs) {
return; return;
} }
static void interrupt_handler(int irq, void *shap, struct pt_regs *regs) { static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) {
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) unsigned int j;
/* Check if the interrupt must be processed by this handler */
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return;
#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95)
{
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags); spin_lock_irqsave(&io_request_lock, flags);
ihdlr(irq, shap, regs); ihdlr(irq, j);
spin_unlock_irqrestore(&io_request_lock, flags); spin_unlock_irqrestore(&io_request_lock, flags);
}
#else #else
ihdlr(irq, j);
ihdlr(irq, shap, regs);
#endif #endif
} }
int u14_34f_release(struct Scsi_Host *shpnt) { int u14_34f_release(struct Scsi_Host *shpnt) {
...@@ -1649,11 +1676,11 @@ int u14_34f_release(struct Scsi_Host *shpnt) { ...@@ -1649,11 +1676,11 @@ int u14_34f_release(struct Scsi_Host *shpnt) {
cli(); cli();
for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n", if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
driver_name); driver_name);
for (i = 0; i < sh[j]->can_queue; i++) for (i = 0; i < sh[j]->can_queue; i++)
if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist); if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
free_irq(sh[j]->irq, &sha[j]); free_irq(sh[j]->irq, &sha[j]);
......
...@@ -13,7 +13,7 @@ int u14_34f_abort(Scsi_Cmnd *); ...@@ -13,7 +13,7 @@ int u14_34f_abort(Scsi_Cmnd *);
int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_reset(Scsi_Cmnd *, unsigned int);
int u14_34f_biosparam(Disk *, kdev_t, int *); int u14_34f_biosparam(Disk *, kdev_t, int *);
#define U14_34F_VERSION "4.04.00" #define U14_34F_VERSION "4.20.00"
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
......
...@@ -108,6 +108,7 @@ static elf_addr_t * ...@@ -108,6 +108,7 @@ static elf_addr_t *
create_elf_tables(char *p, int argc, int envc, create_elf_tables(char *p, int argc, int envc,
struct elfhdr * exec, struct elfhdr * exec,
unsigned long load_addr, unsigned long load_addr,
unsigned long load_bias,
unsigned long interp_load_addr, int ibcs) unsigned long interp_load_addr, int ibcs)
{ {
elf_caddr_t *argv; elf_caddr_t *argv;
...@@ -173,7 +174,7 @@ create_elf_tables(char *p, int argc, int envc, ...@@ -173,7 +174,7 @@ create_elf_tables(char *p, int argc, int envc,
NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE); NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
NEW_AUX_ENT(4, AT_BASE, interp_load_addr); NEW_AUX_ENT(4, AT_BASE, interp_load_addr);
NEW_AUX_ENT(5, AT_FLAGS, 0); NEW_AUX_ENT(5, AT_FLAGS, 0);
NEW_AUX_ENT(6, AT_ENTRY, (elf_addr_t) exec->e_entry); NEW_AUX_ENT(6, AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT(7, AT_UID, (elf_addr_t) current->uid); NEW_AUX_ENT(7, AT_UID, (elf_addr_t) current->uid);
NEW_AUX_ENT(8, AT_EUID, (elf_addr_t) current->euid); NEW_AUX_ENT(8, AT_EUID, (elf_addr_t) current->euid);
NEW_AUX_ENT(9, AT_GID, (elf_addr_t) current->gid); NEW_AUX_ENT(9, AT_GID, (elf_addr_t) current->gid);
...@@ -584,6 +585,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -584,6 +585,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->end_data = 0; current->mm->end_data = 0;
current->mm->end_code = 0; current->mm->end_code = 0;
current->mm->mmap = NULL; current->mm->mmap = NULL;
current->flags &= ~PF_FORKNOEXEC;
elf_entry = (unsigned long) elf_ex.e_entry; elf_entry = (unsigned long) elf_ex.e_entry;
/* Do this immediately, since STACK_TOP as used in setup_arg_pages /* Do this immediately, since STACK_TOP as used in setup_arg_pages
...@@ -712,7 +714,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -712,7 +714,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
bprm->argc, bprm->argc,
bprm->envc, bprm->envc,
(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
load_addr, load_addr, load_bias,
interp_load_addr, interp_load_addr,
(interpreter_type == INTERPRETER_AOUT ? 0 : 1)); (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
/* N.B. passed_fileno might not be initialized? */ /* N.B. passed_fileno might not be initialized? */
......
/* /*
* $Id: nfsroot.c,v 1.43 1997/10/16 19:55:27 mj Exp $ * $Id: nfsroot.c,v 1.45 1998/03/07 10:44:46 mj Exp $
* *
* Copyright (C) 1995, 1996 Gero Kuhlmann <gero@gkminix.han.de> * Copyright (C) 1995, 1996 Gero Kuhlmann <gero@gkminix.han.de>
* *
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
* host IP address (but host name defaults to IP * host IP address (but host name defaults to IP
* address anyway). * address anyway).
* Martin Mares : Use root_server_addr appropriately during setup. * Martin Mares : Use root_server_addr appropriately during setup.
* Martin Mares : Rewrote parameter parsing, now hopefully giving
* correct overriding.
*/ */
#include <linux/types.h> #include <linux/types.h>
...@@ -83,11 +85,9 @@ ...@@ -83,11 +85,9 @@
/* Default path we try to mount. "%s" gets replaced by our IP address */ /* Default path we try to mount. "%s" gets replaced by our IP address */
#define NFS_ROOT "/tftpboot/%s" #define NFS_ROOT "/tftpboot/%s"
#define NFS_ROOT_NAME_LEN 256
/* Parameters passed from the kernel command line */ /* Parameters passed from the kernel command line */
static char nfs_root_name[NFS_ROOT_NAME_LEN] __initdata = "default"; static char nfs_root_name[256] __initdata = "";
static int nfs_params_parsed = 0;
/* Address of NFS server */ /* Address of NFS server */
static __u32 servaddr __initdata = 0; static __u32 servaddr __initdata = 0;
...@@ -150,19 +150,15 @@ static struct nfs_bool_opts { ...@@ -150,19 +150,15 @@ static struct nfs_bool_opts {
/* /*
* Prepare the NFS data structure and parse any options. This tries to * Extract IP address from the parameter string if needed. Note that we
* set as many values in the nfs_data structure as known right now. * need to have root_server_addr set _before_ IPConfig gets called as it
* can override it.
*/ */
__initfunc(static int root_nfs_name(char *name)) __initfunc(static void root_nfs_parse_addr(char *name))
{ {
char buf[NFS_MAXPATHLEN];
char *cp, *cq, *options, *val;
int octets = 0; int octets = 0;
char *cp, *cq;
if (nfs_params_parsed)
return nfs_params_parsed;
/* It is possible to override the server IP number here */
cp = cq = name; cp = cq = name;
while (octets < 4) { while (octets < 4) {
while (*cp >= '0' && *cp <= '9') while (*cp >= '0' && *cp <= '9')
...@@ -179,45 +175,20 @@ __initfunc(static int root_nfs_name(char *name)) ...@@ -179,45 +175,20 @@ __initfunc(static int root_nfs_name(char *name))
if (*cp == ':') if (*cp == ':')
*cp++ = '\0'; *cp++ = '\0';
root_server_addr = in_aton(name); root_server_addr = in_aton(name);
name = cp; strcpy(name, cp);
} }
}
/* Clear the nfs_data structure and setup the server hostname */
memset(&nfs_data, 0, sizeof(nfs_data));
/* Set the name of the directory to mount */
if (root_server_path[0] && !strcmp(name, "default"))
strncpy(buf, root_server_path, NFS_MAXPATHLEN-1);
else
strncpy(buf, name, NFS_MAXPATHLEN-1);
buf[NFS_MAXPATHLEN-1] = '\0';
if ((options = strchr(buf, ',')))
*options++ = '\0';
if (!strcmp(buf, "default"))
strcpy(buf, NFS_ROOT);
cp = system_utsname.nodename;
if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
return -1;
}
sprintf(nfs_path, buf, cp);
/* Set some default values */ /*
nfs_port = -1; * Parse option string.
nfs_data.version = NFS_MOUNT_VERSION; */
nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */ __initfunc(static void root_nfs_parse(char *name, char *buf))
nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE; {
nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE; char *options, *val, *cp;
nfs_data.bsize = 0;
nfs_data.timeo = 7;
nfs_data.retrans = 3;
nfs_data.acregmin = 3;
nfs_data.acregmax = 60;
nfs_data.acdirmin = 30;
nfs_data.acdirmax = 60;
/* Process any options */ if ((options = strchr(name, ','))) {
if (options) { *options++ = 0;
cp = strtok(options, ","); cp = strtok(options, ",");
while (cp) { while (cp) {
if ((val = strchr(cp, '='))) { if ((val = strchr(cp, '='))) {
...@@ -239,6 +210,50 @@ __initfunc(static int root_nfs_name(char *name)) ...@@ -239,6 +210,50 @@ __initfunc(static int root_nfs_name(char *name))
cp = strtok(NULL, ","); cp = strtok(NULL, ",");
} }
} }
if (name[0] && strcmp(name, "default")) {
strncpy(buf, name, NFS_MAXPATHLEN-1);
buf[NFS_MAXPATHLEN-1] = 0;
}
}
/*
* Prepare the NFS data structure and parse all options.
*/
__initfunc(static int root_nfs_name(char *name))
{
char buf[NFS_MAXPATHLEN];
char *cp;
/* Set some default values */
memset(&nfs_data, 0, sizeof(nfs_data));
nfs_port = -1;
nfs_data.version = NFS_MOUNT_VERSION;
nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */
nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
nfs_data.bsize = 0;
nfs_data.timeo = 7;
nfs_data.retrans = 3;
nfs_data.acregmin = 3;
nfs_data.acregmax = 60;
nfs_data.acdirmin = 30;
nfs_data.acdirmax = 60;
strcpy(buf, NFS_ROOT);
/* Process options received from the remote server */
root_nfs_parse(root_server_path, buf);
/* Override them by options set on kernel command-line */
root_nfs_parse(name, buf);
cp = system_utsname.nodename;
if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
return -1;
}
sprintf(nfs_path, buf, cp);
return 1; return 1;
} }
...@@ -317,7 +332,7 @@ __initfunc(void nfs_root_setup(char *line, int *ints)) ...@@ -317,7 +332,7 @@ __initfunc(void nfs_root_setup(char *line, int *ints))
line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0'; line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
sprintf(nfs_root_name, NFS_ROOT, line); sprintf(nfs_root_name, NFS_ROOT, line);
} }
nfs_params_parsed = root_nfs_name(nfs_root_name); root_nfs_parse_addr(nfs_root_name);
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
* include/asm-alpha/serial.h * include/asm-alpha/serial.h
*/ */
#include <linux/config.h>
/* /*
* This assumes you have a 1.8432 MHz clock for your UART. * This assumes you have a 1.8432 MHz clock for your UART.
* *
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
* include/asm-i386/serial.h * include/asm-i386/serial.h
*/ */
#include <linux/config.h>
/* /*
* This assumes you have a 1.8432 MHz clock for your UART. * This assumes you have a 1.8432 MHz clock for your UART.
* *
......
...@@ -293,7 +293,7 @@ __asm__ __volatile__ ("movw %3,0(%2)\n\t" \ ...@@ -293,7 +293,7 @@ __asm__ __volatile__ ("movw %3,0(%2)\n\t" \
"movb $0,6(%2)\n\t" \ "movb $0,6(%2)\n\t" \
"movb %%ah,7(%2)\n\t" \ "movb %%ah,7(%2)\n\t" \
"rorl $16,%%eax" \ "rorl $16,%%eax" \
: "=m"(*(n)) : "a" (addr), "r"(n), "g"(limit), "i"(type)) : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
#define set_tss_desc(n,addr) \ #define set_tss_desc(n,addr) \
_set_tssldt_desc(((char *) (n)),((int)(addr)),235,0x89) _set_tssldt_desc(((char *) (n)),((int)(addr)),235,0x89)
......
#include <linux/config.h>
#ifndef _ASM_IRQ_H #ifndef _ASM_IRQ_H
#define _ASM_IRQ_H #define _ASM_IRQ_H
......
#include <linux/config.h>
#ifndef __PPC_MMU_CONTEXT_H #ifndef __PPC_MMU_CONTEXT_H
#define __PPC_MMU_CONTEXT_H #define __PPC_MMU_CONTEXT_H
......
#include <linux/config.h>
#ifndef _PPC_PAGE_H #ifndef _PPC_PAGE_H
#define _PPC_PAGE_H #define _PPC_PAGE_H
......
#include <linux/config.h>
#ifndef _PPC_PGTABLE_H #ifndef _PPC_PGTABLE_H
#define _PPC_PGTABLE_H #define _PPC_PGTABLE_H
......
/* $Id: system.h,v 1.68 1998/03/09 14:04:51 jj Exp $ */ /* $Id: system.h,v 1.68 1998/03/09 14:04:51 jj Exp $ */
#include <linux/config.h>
#ifndef __SPARC_SYSTEM_H #ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H #define __SPARC_SYSTEM_H
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
* *
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/ */
#include <linux/config.h>
#ifndef _SPARC_TIMER_H #ifndef _SPARC_TIMER_H
#define _SPARC_TIMER_H #define _SPARC_TIMER_H
......
/* /*
* This is <linux/capability.h> * This is <linux/capability.h>
* *
* Andrew G. Morgan <morgan@parc.power.net> * Andrew G. Morgan <morgan@transmeta.com>
* Alexander Kjeldaas <astor@guardian.no> * Alexander Kjeldaas <astor@guardian.no>
* with help from Aleph1, Roland Buresund and Andrew Main. * with help from Aleph1, Roland Buresund and Andrew Main.
*/ */
......
...@@ -283,7 +283,6 @@ extern __inline__ unsigned int parport_yield_blocking(struct pardevice *dev) ...@@ -283,7 +283,6 @@ extern __inline__ unsigned int parport_yield_blocking(struct pardevice *dev)
if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice)) if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
return 0; return 0;
parport_release(dev); parport_release(dev);
schedule();
return parport_claim_or_block(dev); return parport_claim_or_block(dev);
} }
......
...@@ -113,7 +113,7 @@ int kmod_init(void) ...@@ -113,7 +113,7 @@ int kmod_init(void)
* CLONE_FILES just saves some space (we don't need any * CLONE_FILES just saves some space (we don't need any
* new file descriptors). Ditto for CLONE_SIGHAND. * new file descriptors). Ditto for CLONE_SIGHAND.
*/ */
kernel_thread(kmod_thread, NULL, CLONE_FILES |CLONE_FS | CLONE_SIGHAND); kernel_thread(kmod_thread, NULL, CLONE_FILES | CLONE_FS | CLONE_SIGHAND);
kmod_unload_timer.next = NULL; kmod_unload_timer.next = NULL;
kmod_unload_timer.prev = NULL; kmod_unload_timer.prev = NULL;
......
...@@ -273,10 +273,8 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order) ...@@ -273,10 +273,8 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order)
* "maxorder" is the highest order number that we're allowed * "maxorder" is the highest order number that we're allowed
* to empty in order to find a free page.. * to empty in order to find a free page..
*/ */
maxorder = order + NR_MEM_LISTS/3; maxorder = NR_MEM_LISTS-1;
if (gfp_mask & __GFP_MED) if (gfp_mask & __GFP_HIGH)
maxorder += NR_MEM_LISTS/3;
if ((gfp_mask & __GFP_HIGH) || maxorder > NR_MEM_LISTS)
maxorder = NR_MEM_LISTS; maxorder = NR_MEM_LISTS;
if (in_interrupt() && (gfp_mask & __GFP_WAIT)) { if (in_interrupt() && (gfp_mask & __GFP_WAIT)) {
...@@ -295,6 +293,7 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order) ...@@ -295,6 +293,7 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order)
if (gfp_mask & __GFP_WAIT) { if (gfp_mask & __GFP_WAIT) {
int freed = try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX); int freed = try_to_free_pages(gfp_mask,SWAP_CLUSTER_MAX);
gfp_mask &= ~__GFP_WAIT; /* go through this only once */ gfp_mask &= ~__GFP_WAIT; /* go through this only once */
maxorder = NR_MEM_LISTS; /* Allow anything this time */
if (freed) if (freed)
goto repeat; goto repeat;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment