From 3cc4e27d361f5cb8ab5b3b0f1c0244e66a3aa5ea Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:11:45 -0500 Subject: [PATCH] Import 2.0.34pre16 --- arch/alpha/kernel/cia.c | 2 +- arch/alpha/kernel/lca.c | 2 +- arch/alpha/kernel/t2.c | 2 +- arch/i386/kernel/head.S | 100 +------ drivers/net/Changelog.tlan | 2 +- drivers/net/Makefile | 2 +- drivers/net/tlan.c | 4 +- drivers/scsi/eata.c | 495 ++++++++++++++++++++++++++--------- drivers/scsi/eata.h | 50 ++-- drivers/scsi/ppa.c | 2 +- drivers/scsi/u14-34f.c | 502 +++++++++++++++++++++++++++--------- drivers/scsi/u14-34f.h | 50 ++-- include/linux/modversions.h | 30 --- scripts/Menuconfig | 4 +- 14 files changed, 828 insertions(+), 419 deletions(-) delete mode 100644 include/linux/modversions.h diff --git a/arch/alpha/kernel/cia.c b/arch/alpha/kernel/cia.c index 6b4648bfd3af..7a0bd5189845 100644 --- a/arch/alpha/kernel/cia.c +++ b/arch/alpha/kernel/cia.c @@ -659,7 +659,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr, printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n", vector, la_ptr, regs->pc); - /* dump the the logout area to give all info: */ + /* dump the logout area to give all info: */ ptr = (unsigned long *)la_ptr; for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { diff --git a/arch/alpha/kernel/lca.c b/arch/alpha/kernel/lca.c index 65a8aef532ff..71100c8c6256 100644 --- a/arch/alpha/kernel/lca.c +++ b/arch/alpha/kernel/lca.c @@ -500,7 +500,7 @@ void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs * printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size); } - /* dump the the logout area to give all info: */ + /* dump the logout area to give all info: */ ptr = (unsigned long *) la; for (i = 0; i < el.c->size / sizeof(long); i += 2) { diff --git a/arch/alpha/kernel/t2.c b/arch/alpha/kernel/t2.c index dbcc5b645421..a0bef6e2d20a 100644 --- a/arch/alpha/kernel/t2.c +++ b/arch/alpha/kernel/t2.c @@ -642,7 +642,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr, printk(KERN_CRIT " T2 machine check: %s%s\n", reason, mchk_header->elfl_retry ? " (retryable)" : ""); - /* dump the the logout area to give all info: */ + /* dump the logout area to give all info: */ ptr = (unsigned long *)la_ptr; for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 65893690c0eb..4c3d6c5b8060 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -109,86 +109,7 @@ checkCPUtype: * apply at our cpl of 0 and the stack ought to be aligned already, and * we don't need to preserve eflags. */ - /* - * A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2 - * (and it _must_ be 5 divided by 2) while other CPUs change - * them in undefined ways. We need to know this since we may - * need to enable the CPUID instruction at least. - */ - xor %ax,%ax - sahf - movb $5,%ax - movb $2,%bx - div %bl - lahf - cmpb $2,%ah - jne ncyrix - - /* - * It behaves like a Cyrix/IBM 6x86(L) so put "Cyrix" in the - * vendor id field. It may be overwritten later with the - * real thing if CPUID works. - */ - movl $0x69727943,SYMBOL_NAME(x86_vendor_id) # low 4 chars - movl $0x00000078,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars - - /* - * N.B. The pattern of accesses to 0x22 and 0x23 is *essential* - * so do not try to "optimize" it! For the same reason we - * do all this with interrupts off. - */ -#define setCx86(reg, val) \ - movb reg,%al; \ - outb %al,$0x22; \ - movb val,%al; \ - outb %al,$0x23 - -#define getCx86(reg) \ - movb reg,%al; \ - outb %al,$0x22; \ - inb $0x23,%al - - /* - * Cyrix screwed this up. You have to do the basic cyrix - * detect then pray its right in order to turn CPUID on - * to see if you have a Cyrix. If its a future non Cyrix - * chip that seems to be a cyrix but crashes on IO 0x22/0x23 - * don't blame us... - * - * If we don't set this minimal group however then it breaks - * our delay loops and stuff so we have to do something - * for this contraption. - * - * Note; We do the minimal here. The xchg bug and other stuff - * can be tweaked with user mode tools. - */ - - cli - getCx86($0xc3) # get CCR3 - movb %al,%cl # Save old value - movb %al,%bl - andb $0x0f,%bl # Enable access to all config registers - orb $0x10,%bl # by setting bit 4 - setCx86($0xc3,%bl) - - getCx86($0xe8) # now we can get CCR4 - orb $0x80,%al # and set bit 7 (CPUIDEN) - movb %al,%bl # to enable CPUID execution - setCx86($0xe8,%bl) - - getCx86($0xfe) # DIR0 : let's check this is a 6x86(L) - andb $0xf0,%al # should be 3xh - cmpb $0x30,%al # - jne n6x86 - getCx86($0xe9) # CCR5 : we reset the SLOP bit - andb $0xfd,%al # so that udelay calculation - movb %al,%bl # is correct on 6x86(L) CPUs - setCx86($0xe9,%bl) - -n6x86: setCx86($0xc3,%cl) # Restore old CCR3 - sti - -ncyrix: movl $3, SYMBOL_NAME(x86) + movl $3, SYMBOL_NAME(x86) pushfl # push EFLAGS popl %eax # get EFLAGS movl %eax,%ecx # save original EFLAGS @@ -232,25 +153,8 @@ isnew: pushl %ecx # restore original EFLAGS andb $0x0f, %cl # mask mask revision movb %cl,SYMBOL_NAME(x86_mask) movl %edx,SYMBOL_NAME(x86_capability) - -#ifdef SOMEONE_FIXED_ME - /* - * This trips some PPro/PII's and overwrites the mask - * with crap. Removed until the Linux/Cyrix guys fix it. - */ - xorl %eax,%eax # test again for Cyrix CPU - sahf - movb $5,%al - movb $2,%bl - div %bl - lahf - cmpb $2,%ah - jne ncyrx2 # skip if not Cyrix CPU - getCx86($0xff) # DIR1 : let's check the stepping - movb %al,SYMBOL_NAME(x86_mask) -#endif /* get vendor info */ -ncyrx2: xorl %eax, %eax # call CPUID with 0 -> return vendor ID + xorl %eax, %eax # call CPUID with 0 -> return vendor ID #ifdef GAS_KNOWS_CPUID cpuid #else diff --git a/drivers/net/Changelog.tlan b/drivers/net/Changelog.tlan index 36b9d7663685..d026ede2b0e0 100644 --- a/drivers/net/Changelog.tlan +++ b/drivers/net/Changelog.tlan @@ -19,7 +19,7 @@ TLan Device Driver change log. 100Mbs should work now on 0xAE32. - Fixed a small bug where heartbeat and PHY interrupts were always being enabled. - - Force the the driver into Unmanaged PHY mode for 0xF130 devices, + - Force the driver into Unmanaged PHY mode for 0xF130 devices, even if a managed (ie, the built-in one) PHY is detected. - Moved the PHY initialization to after the onboard PHY is enabled, if selected. diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b0ab1cb5e90a..e3744f6680a9 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -148,7 +148,7 @@ ifeq ($(CONFIG_ULTRA32),y) L_OBJS += smc-ultra32.o CONFIG_8390_BUILTIN = y else - ifeq ($(CONFIG_ULTRA),m) + ifeq ($(CONFIG_ULTRA32),m) CONFIG_8390_MODULE = y M_OBJS += smc-ultra32.o endif diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 43f0e2897625..ce10ebcd8727 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1092,7 +1092,7 @@ u32 TLan_HandleStatOverflow( struct device *dev, u16 host_int ) * of the list. If the frame was the last in the Rx * channel (EOC), the function restarts the receive channel * by sending an Rx Go command to the adapter. Then it - * activates/continues the the activity LED. + * activates/continues the activity LED. * **************************************************************/ @@ -1508,7 +1508,7 @@ void TLan_ResetLists( struct device *dev ) * io_base Base IO port of the device of * which to print DIO registers. * - * This function prints out all the the internal (DIO) + * This function prints out all the internal (DIO) * registers of a TLAN chip. * **************************************************************/ diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index ffd1e00e1091..09f301cef6a5 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1,6 +1,18 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 16 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102 + * Improved abort handling during the eh recovery process. + * + * 13 May 1998 Rev. 4.30 for linux 2.0.33 and 2.1.101 + * The driver is now fully SMP safe, including the + * abort and reset routines. + * Added command line options (eh:[y|n]) to choose between + * new_eh_code and the old scsi code. + * If linux verion >= 2.1.101 the default is eh:y, while the eh + * option is ignored for previous releases and the old scsi code + * is used. + * * 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97 * Reworked interrupt handler. * @@ -237,6 +249,8 @@ * After the optional list of detection probes, other possible command line * options are: * + * eh:y use new scsi code (linux 2.2 only); + * eh:n use old scsi code; * lc:y enables linked commands; * lc:n disables linked commands; * tc:y enables tagged commands; @@ -248,13 +262,14 @@ * mq:xx set the max queue depth to the value xx (2 <= xx <= 32). * * The default value is: "eata=lc:n,tc:n,mq:16,tm:0". An example using - * the list of detection probes could be: "eata=0x7410,0x230,lc:y,tc:n,mq:4". + * the list of detection probes could be: + * "eata=0x7410,0x230,lc:y,tc:n,mq:4,eh:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * * modprobe eata io_port=0x7410,0x230 linked_comm=1 tagged_comm=0 \ - * max_queue_depth=4 tag_mode=0 + * max_queue_depth=4 tag_mode=0 use_new_eh_code=0 * * ---------------------------------------------------------------------------- * In this implementation, linked commands are designed to work with any DISK @@ -310,6 +325,7 @@ MODULE_PARM(tagged_comm, "i"); MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); MODULE_PARM(tag_mode, "i"); +MODULE_PARM(use_new_eh_code, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif @@ -323,11 +339,6 @@ MODULE_AUTHOR("Dario Ballabio"); #include #include #include - -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) -#include -#endif - #include #include #include "scsi.h" @@ -352,6 +363,34 @@ MODULE_AUTHOR("Dario Ballabio"); #define __init #endif +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) +#include +#define IRQ_FLAGS +#define IRQ_LOCK +#define IRQ_LOCK_SAVE +#define IRQ_UNLOCK +#define IRQ_UNLOCK_RESTORE +#define SPIN_FLAGS unsigned long spin_flags; +#define SPIN_LOCK spin_lock_irq(&io_request_lock); +#define SPIN_LOCK_SAVE spin_lock_irqsave(&io_request_lock, spin_flags); +#define SPIN_UNLOCK spin_unlock_irq(&io_request_lock); +#define SPIN_UNLOCK_RESTORE \ + spin_unlock_irqrestore(&io_request_lock, spin_flags); +static int use_new_eh_code = TRUE; +#else +#define IRQ_FLAGS unsigned long irq_flags; +#define IRQ_LOCK cli(); +#define IRQ_LOCK_SAVE do {save_flags(irq_flags); cli();} while (0); +#define IRQ_UNLOCK sti(); +#define IRQ_UNLOCK_RESTORE do {restore_flags(irq_flags);} while (0); +#define SPIN_FLAGS +#define SPIN_LOCK +#define SPIN_LOCK_SAVE +#define SPIN_UNLOCK +#define SPIN_UNLOCK_RESTORE +static int use_new_eh_code = FALSE; +#endif + struct proc_dir_entry proc_scsi_eata2x = { PROC_SCSI_EATA2X, 6, "eata2x", S_IFDIR | S_IRUGO | S_IXUGO, 2 @@ -368,6 +407,8 @@ struct proc_dir_entry proc_scsi_eata2x = { #undef DEBUG_PCI_DETECT #undef DEBUG_INTERRUPT #undef DEBUG_RESET +#undef DEBUG_GENERATE_ERRORS +#undef DEBUG_GENERATE_ABORTS #define MAX_ISA 4 #define MAX_VESA 0 @@ -619,19 +660,19 @@ static int setup_done = FALSE; static int link_statistics = 0; static int tag_mode = TAG_MIXED; -#if defined (CONFIG_SCSI_EATA_TAGGED_QUEUE) +#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) static int tagged_comm = TRUE; #else static int tagged_comm = FALSE; #endif -#if defined (CONFIG_SCSI_EATA_LINKED_COMMANDS) +#if defined(CONFIG_SCSI_EATA_LINKED_COMMANDS) static int linked_comm = TRUE; #else static int linked_comm = FALSE; #endif -#if defined CONFIG_SCSI_EATA_MAX_TAGS +#if defined(CONFIG_SCSI_EATA_MAX_TAGS) static int max_queue_depth = CONFIG_SCSI_EATA_MAX_TAGS; #else static int max_queue_depth = MAX_CMD_PER_LUN; @@ -640,11 +681,9 @@ static int max_queue_depth = MAX_CMD_PER_LUN; static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { Scsi_Device *dev; int j, ntag = 0, nuntag = 0, tqd, utqd; - unsigned long flags; - - save_flags(flags); - cli(); + IRQ_FLAGS + IRQ_LOCK_SAVE j = ((struct hostdata *) host->hostdata)->board_number; for(dev = devlist; dev; dev = dev->next) { @@ -697,7 +736,7 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { dev->queue_depth, link_suffix, tag_suffix); } - restore_flags(flags); + IRQ_UNLOCK_RESTORE return; } @@ -899,7 +938,7 @@ __initfunc (static inline int port_detect \ return FALSE; } -#if defined (FORCE_CONFIG) +#if defined(FORCE_CONFIG) { struct eata_config config; @@ -1016,21 +1055,32 @@ __initfunc (static inline int port_detect \ } else tag_type = 'n'; - printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d, tc:%c, lc:%c, "\ - "mq:%d.\n", BN(j), HD(j)->protocol_rev, bus_type, - (unsigned long)sh[j]->io_port, sh[j]->irq, dma_name, - sh[j]->sg_tablesize, sh[j]->can_queue, tag_type, YESNO(linked_comm), - max_queue_depth); +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + sh[j]->hostt->use_new_eh_code = use_new_eh_code; +#else + use_new_eh_code = FALSE; +#endif + + if (j == 0) { + printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n"); + printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c.\n", + driver_name, tag_type, YESNO(linked_comm), + max_queue_depth, YESNO(use_new_eh_code)); + } + + printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n", + BN(j), HD(j)->protocol_rev, bus_type, (unsigned long)sh[j]->io_port, + sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); for (i = 0; i <= sh[j]->max_channel; i++) - printk("%s: SCSI channel %u enabled, host target ID %u.\n", + printk("%s: SCSI channel %u enabled, host target ID %d.\n", BN(j), i, info.host_addr[3 - i]); -#if defined (DEBUG_DETECT) +#if defined(DEBUG_DETECT) printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\ "sec. %u, infol %ld, cpl %ld spl %ld.\n", name, info.version, info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, @@ -1077,6 +1127,7 @@ __initfunc (void eata2x_setup(char *str, int *ints)) { else if (!strncmp(cur, "tm:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; + else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; if ((cur = strchr(cur, ','))) ++cur; } @@ -1151,14 +1202,12 @@ __initfunc (static void add_pci_ports(void)) { } __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { - unsigned long flags; unsigned int j = 0, k; + IRQ_FLAGS + IRQ_LOCK_SAVE tpnt->proc_dir = &proc_scsi_eata2x; - save_flags(flags); - cli(); - #if defined(MODULE) /* io_port could have been modified when loading as a module */ if(io_port[0] != SKIP) { @@ -1178,11 +1227,8 @@ __initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; } - if (j > 0) - printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n"); - num_boards = j; - restore_flags(flags); + IRQ_UNLOCK_RESTORE return j; } @@ -1201,8 +1247,7 @@ static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list))); } -int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned long flags; +static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; struct mssp *spp; @@ -1219,22 +1264,12 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5 }; - save_flags(flags); - cli(); /* j is the board number */ j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; - if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); - - if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) { - SCpnt->result = DID_OK << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n", - BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } + if (SCpnt->host_scribble) + panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", + BN(j), SCpnt->pid, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -1251,19 +1286,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { } if (k == sh[j]->can_queue) { - printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); - - if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); - else if (eata2x_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) - == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); - - SCpnt->result = DID_BUS_BUSY << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); - restore_flags(flags); - done(SCpnt); + printk("%s: qcomm, no free mailbox.\n", BN(j)); return 1; } @@ -1346,40 +1369,41 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; flush_dev(SCpnt->device, SCpnt->request.sector, j, FALSE); - restore_flags(flags); return 0; } /* Send control packet to the board */ if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) { - SCpnt->result = DID_ERROR << 16; SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\ - " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, - SCpnt->pid); - restore_flags(flags); - done(SCpnt); + printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n", + BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); return 1; } HD(j)->cp_stat[i] = IN_USE; - restore_flags(flags); return 0; } -int eata2x_abort(Scsi_Cmnd *SCarg) { - unsigned long flags; +int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_qcomm(SCpnt, done); + IRQ_UNLOCK_RESTORE + return rtn; +} + +static inline int do_old_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; - save_flags(flags); - cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - if (SCarg->host_scribble == NULL - || SCarg->serial_number != SCarg->serial_number_at_timeout) { + if (SCarg->host_scribble == NULL || + (SCarg->serial_number_at_timeout && + (SCarg->serial_number != SCarg->serial_number_at_timeout))) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1392,13 +1416,11 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: abort, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == FREE) { printk("%s: abort, mbox %d is free.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1412,19 +1434,16 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_SNOOZE; } if (HD(j)->cp_stat[i] == IN_RESET) { printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == LOCKED) { printk("%s: abort, mbox %d is locked.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1435,45 +1454,128 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", BN(j), i, SCarg->pid); SCarg->scsi_done(SCarg); - restore_flags(flags); return SCSI_ABORT_SUCCESS; } - restore_flags(flags); panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - unsigned long flags; +int eata2x_old_abort(Scsi_Cmnd *SCarg) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_old_abort(SCarg); + IRQ_UNLOCK_RESTORE + return rtn; +} + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + +static inline int do_abort(Scsi_Cmnd *SCarg) { + unsigned int i, j; + + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + + if (SCarg->host_scribble == NULL) { + printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + return SUCCESS; + } + + i = *(unsigned int *)SCarg->host_scribble; + printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + + if (i >= sh[j]->can_queue) + panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); + + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { + printk("%s: abort, timeout error.\n", BN(j)); + return FAILED; + } + + if (HD(j)->cp_stat[i] == FREE) { + printk("%s: abort, mbox %d is free.\n", BN(j), i); + return SUCCESS; + } + + if (HD(j)->cp_stat[i] == IN_USE) { + printk("%s: abort, mbox %d is in use.\n", BN(j), i); + + if (SCarg != HD(j)->cp[i].SCpnt) + panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", + BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + + if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) + printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); + + if (SCarg->eh_state == SCSI_STATE_TIMEOUT) { + SCarg->host_scribble = NULL; + HD(j)->cp_stat[i] = FREE; + printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n", + BN(j), i, SCarg->pid); + return SUCCESS; + } + + return FAILED; + } + + if (HD(j)->cp_stat[i] == IN_RESET) { + printk("%s: abort, mbox %d is in reset.\n", BN(j), i); + return FAILED; + } + + if (HD(j)->cp_stat[i] == LOCKED) { + printk("%s: abort, mbox %d is locked.\n", BN(j), i); + return SUCCESS; + } + + if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { + SCarg->result = DID_ABORT << 16; + SCarg->host_scribble = NULL; + HD(j)->cp_stat[i] = FREE; + printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", + BN(j), i, SCarg->pid); + SCarg->scsi_done(SCarg); + return SUCCESS; + } + + panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); +} + +int eata2x_abort(Scsi_Cmnd *SCarg) { + + return do_abort(SCarg); +} + +#endif /* new_eh_code */ + +static inline int do_old_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; - save_flags(flags); - cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, - reset_flags); + printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (SCarg->host_scribble == NULL) printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - if (SCarg->serial_number != SCarg->serial_number_at_timeout) { + if (SCarg->serial_number_at_timeout && + (SCarg->serial_number != SCarg->serial_number_at_timeout)) { printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid); - restore_flags(flags); return SCSI_RESET_NOT_RUNNING; } if (HD(j)->in_reset) { printk("%s: reset, exit, already in reset.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, exit, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } @@ -1524,21 +1626,22 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); -#if defined (DEBUG_RESET) +#if defined(DEBUG_RESET) do_trace = TRUE; #endif HD(j)->in_reset = TRUE; - sti(); + SPIN_UNLOCK + IRQ_UNLOCK time = jiffies; while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); - cli(); + IRQ_LOCK + SPIN_LOCK printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); for (i = 0; i < sh[j]->can_queue; i++) { @@ -1572,14 +1675,12 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { /* Any other mailbox has already been set free by interrupt */ continue; - restore_flags(flags); SCpnt->scsi_done(SCpnt); - cli(); + IRQ_LOCK } HD(j)->in_reset = FALSE; do_trace = FALSE; - restore_flags(flags); if (arg_done) { printk("%s: reset, exit, success.\n", BN(j)); @@ -1591,6 +1692,156 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { } } +int eata2x_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_old_reset(SCarg); + IRQ_UNLOCK_RESTORE + return rtn; +} + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + +static inline int do_reset(Scsi_Cmnd *SCarg) { + unsigned int i, j, time, k, c, limit = 0; + int arg_done = FALSE; + Scsi_Cmnd *SCpnt; + + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + + if (SCarg->host_scribble == NULL) + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + + if (HD(j)->in_reset) { + printk("%s: reset, exit, already in reset.\n", BN(j)); + return FAILED; + } + + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { + printk("%s: reset, exit, timeout error.\n", BN(j)); + return FAILED; + } + + HD(j)->retries = 0; + + 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; + HD(j)->target_to[k][c] = 0; + } + + for (i = 0; i < sh[j]->can_queue; i++) { + + if (HD(j)->cp_stat[i] == FREE) continue; + + if (HD(j)->cp_stat[i] == LOCKED) { + HD(j)->cp_stat[i] = FREE; + printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); + continue; + } + + if (!(SCpnt = HD(j)->cp[i].SCpnt)) + panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); + + if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { + HD(j)->cp_stat[i] = ABORTING; + printk("%s: reset, mbox %d aborting, pid %ld.\n", + BN(j), i, SCpnt->pid); + } + + else { + HD(j)->cp_stat[i] = IN_RESET; + printk("%s: reset, mbox %d in reset, pid %ld.\n", + BN(j), i, SCpnt->pid); + } + + if (SCpnt->host_scribble == NULL) + panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); + + if (*(unsigned int *)SCpnt->host_scribble != i) + panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); + + if (SCpnt->scsi_done == NULL) + panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); + + if (SCpnt == SCarg) arg_done = TRUE; + } + + if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { + printk("%s: reset, cannot reset, timeout error.\n", BN(j)); + return FAILED; + } + + printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); + +#if defined(DEBUG_RESET) + do_trace = TRUE; +#endif + + HD(j)->in_reset = TRUE; + SPIN_UNLOCK + IRQ_UNLOCK + time = jiffies; + while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); + IRQ_LOCK + SPIN_LOCK + printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); + + for (i = 0; i < sh[j]->can_queue; i++) { + + if (HD(j)->cp_stat[i] == IN_RESET) { + SCpnt = HD(j)->cp[i].SCpnt; + SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; + + /* This mailbox is still waiting for its interrupt */ + HD(j)->cp_stat[i] = LOCKED; + + printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", + BN(j), i, SCpnt->pid); + } + + else if (HD(j)->cp_stat[i] == ABORTING) { + SCpnt = HD(j)->cp[i].SCpnt; + SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; + + /* This mailbox was never queued to the adapter */ + HD(j)->cp_stat[i] = FREE; + + printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", + BN(j), i, SCpnt->pid); + } + + else + + /* Any other mailbox has already been set free by interrupt */ + continue; + + SCpnt->scsi_done(SCpnt); + IRQ_LOCK + } + + HD(j)->in_reset = FALSE; + do_trace = FALSE; + + if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); + else printk("%s: reset, exit.\n", BN(j)); + + return SUCCESS; +} + +int eata2x_reset(Scsi_Cmnd *SCarg) { + + return do_reset(SCarg); +} + +#endif /* new_eh_code */ + static void sort(unsigned long sk[], unsigned int da[], unsigned int n, unsigned int rev) { unsigned int i, j, k, y; @@ -1698,7 +1949,7 @@ static inline int reorder(unsigned int j, unsigned long cursec, if (!rev && !s) { sortcount++; readysorted += n_ready; } } -#if defined (DEBUG_LINKED_COMMANDS) +#if defined(DEBUG_LINKED_COMMANDS) if (link_statistics && (overlap || !(flushcount % link_statistics))) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; @@ -1789,16 +2040,20 @@ static inline void ihdlr(int irq, unsigned int j) { reg = inb(sh[j]->io_port + REG_STATUS); /* Reject any sp with supspect data */ - if (spp->eoc == FALSE) + if (spp->eoc == FALSE) printk("%s: ihdlr, spp->eoc == FALSE, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); - if (spp->cpp == NULL) + 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; cpp = spp->cpp; +#if defined(DEBUG_GENERATE_ABORTS) + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return; +#endif + /* Find the mailbox to be serviced on this board */ i = cpp - HD(j)->cp; @@ -1847,6 +2102,11 @@ static inline void ihdlr(int irq, unsigned int j) { tstatus = status_byte(spp->target_status); +#if defined(DEBUG_GENERATE_ERRORS) + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 200) < 2)) + spp->adapter_status = 0x01; +#endif + switch (spp->adapter_status) { case ASOK: /* status OK */ @@ -1905,7 +2165,12 @@ static inline void ihdlr(int irq, unsigned int j) { if (SCpnt->device->type != TYPE_TAPE && HD(j)->retries < MAX_INTERNAL_RETRIES) { + +#if defined(DID_SOFT_ERROR) + status = DID_SOFT_ERROR << 16; +#else status = DID_BUS_BUSY << 16; +#endif HD(j)->retries++; HD(j)->last_retried_pid = SCpnt->pid; } @@ -1928,7 +2193,7 @@ static inline void ihdlr(int irq, unsigned int j) { SCpnt->result = status | spp->target_status; -#if defined (DEBUG_INTERRUPT) +#if defined(DEBUG_INTERRUPT) if (SCpnt->result || do_trace) #else if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || @@ -1954,31 +2219,25 @@ static inline void ihdlr(int irq, unsigned int j) { } static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) { - unsigned int j; + IRQ_FLAGS + SPIN_FLAGS /* 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; - spin_lock_irqsave(&io_request_lock, flags); + SPIN_LOCK_SAVE + IRQ_LOCK_SAVE ihdlr(irq, j); - spin_unlock_irqrestore(&io_request_lock, flags); - } -#else - ihdlr(irq, j); -#endif - + IRQ_UNLOCK_RESTORE + SPIN_UNLOCK_RESTORE } int eata2x_release(struct Scsi_Host *shpnt) { - unsigned long flags; unsigned int i, j; + IRQ_FLAGS - save_flags(flags); - cli(); + IRQ_LOCK_SAVE for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); @@ -1994,7 +2253,7 @@ int eata2x_release(struct Scsi_Host *shpnt) { release_region(sh[j]->io_port, sh[j]->n_io_port); scsi_unregister(sh[j]); - restore_flags(flags); + IRQ_UNLOCK_RESTORE return FALSE; } diff --git a/drivers/scsi/eata.h b/drivers/scsi/eata.h index 2eb04f657493..e495b2d14343 100644 --- a/drivers/scsi/eata.h +++ b/drivers/scsi/eata.h @@ -11,41 +11,47 @@ int eata2x_detect(Scsi_Host_Template *); int eata2x_release(struct Scsi_Host *); int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int eata2x_abort(Scsi_Cmnd *); -int eata2x_reset(Scsi_Cmnd *, unsigned int); +int eata2x_old_abort(Scsi_Cmnd *); +int eata2x_reset(Scsi_Cmnd *); +int eata2x_old_reset(Scsi_Cmnd *, unsigned int); -#define EATA_VERSION "4.20.00" +#define EATA_VERSION "4.31.00" #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88) +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) #define EATA { \ name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ - detect: eata2x_detect, \ - release: eata2x_release, \ - queuecommand: eata2x_queuecommand, \ - abort: eata2x_abort, \ - reset: eata2x_reset, \ - bios_param: scsicam_bios_param, \ - this_id: 7, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 /* Enable new error code */ \ + detect: eata2x_detect, \ + release: eata2x_release, \ + queuecommand: eata2x_queuecommand, \ + abort: eata2x_old_abort, \ + reset: eata2x_old_reset, \ + eh_abort_handler: eata2x_abort, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: eata2x_reset, \ + bios_param: scsicam_bios_param, \ + this_id: 7, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* Enable new error code */ \ } #else /* Use old scsi code */ #define EATA { \ name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ - detect: eata2x_detect, \ - release: eata2x_release, \ - queuecommand: eata2x_queuecommand, \ - abort: eata2x_abort, \ - reset: eata2x_reset, \ - bios_param: scsicam_bios_param, \ - this_id: 7, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING \ + detect: eata2x_detect, \ + release: eata2x_release, \ + queuecommand: eata2x_queuecommand, \ + abort: eata2x_old_abort, \ + reset: eata2x_old_reset, \ + bios_param: scsicam_bios_param, \ + this_id: 7, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING \ } #endif diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 4e47775fe36b..73b1b0152a2d 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -1198,7 +1198,7 @@ int ppa_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) } /* - * Apparently the the disk->capacity attribute is off by 1 sector + * Apparently the disk->capacity attribute is off by 1 sector * for all disk drives. We add the one here, but it should really * be done in sd.c. Even if it gets fixed there, this will still * work. diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 6263e22586e2..5dd63f0d3eca 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1,6 +1,18 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 18 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102 + * Improved abort handling during the eh recovery process. + * + * 13 May 1998 Rev. 4.30 for linux 2.0.33 and 2.1.101 + * The driver is now fully SMP safe, including the + * abort and reset routines. + * Added command line options (eh:[y|n]) to choose between + * new_eh_code and the old scsi code. + * If linux verion >= 2.1.101 the default is eh:y, while the eh + * option is ignored for previous releases and the old scsi code + * is used. + * * 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97 * Reworked interrupt handler. * @@ -227,6 +239,8 @@ * After the optional list of detection probes, other possible command line * options are: * + * eh:y use new scsi code (linux 2.2 only); + * eh:n use old scsi code; * lc:y enables linked commands; * lc:n disables linked commands; * of:y enables old firmware support; @@ -234,13 +248,13 @@ * mq:xx set the max queue depth to the value xx (2 <= xx <= 8). * * The default value is: "u14-34f=lc:n,of:n,mq:8". An example using the list - * of detection probes could be: "u14-34f=0x230,0x340,lc:y,of:n,mq:4". + * of detection probes could be: "u14-34f=0x230,0x340,lc:y,of:n,mq:4,eh:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * * modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \ - * max_queue_depth=4 + * max_queue_depth=4 use_new_eh_code=0 * * ---------------------------------------------------------------------------- * In this implementation, linked commands are designed to work with any DISK @@ -295,6 +309,7 @@ MODULE_PARM(linked_comm, "i"); MODULE_PARM(have_old_firmware, "i"); MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); +MODULE_PARM(use_new_eh_code, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif @@ -308,11 +323,6 @@ MODULE_AUTHOR("Dario Ballabio"); #include #include #include - -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,95) -#include -#endif - #include #include #include "scsi.h" @@ -332,6 +342,34 @@ MODULE_AUTHOR("Dario Ballabio"); #define __init #endif +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) +#include +#define IRQ_FLAGS +#define IRQ_LOCK +#define IRQ_LOCK_SAVE +#define IRQ_UNLOCK +#define IRQ_UNLOCK_RESTORE +#define SPIN_FLAGS unsigned long spin_flags; +#define SPIN_LOCK spin_lock_irq(&io_request_lock); +#define SPIN_LOCK_SAVE spin_lock_irqsave(&io_request_lock, spin_flags); +#define SPIN_UNLOCK spin_unlock_irq(&io_request_lock); +#define SPIN_UNLOCK_RESTORE \ + spin_unlock_irqrestore(&io_request_lock, spin_flags); +static int use_new_eh_code = TRUE; +#else +#define IRQ_FLAGS unsigned long irq_flags; +#define IRQ_LOCK cli(); +#define IRQ_LOCK_SAVE do {save_flags(irq_flags); cli();} while (0); +#define IRQ_UNLOCK sti(); +#define IRQ_UNLOCK_RESTORE do {restore_flags(irq_flags);} while (0); +#define SPIN_FLAGS +#define SPIN_LOCK +#define SPIN_LOCK_SAVE +#define SPIN_UNLOCK +#define SPIN_UNLOCK_RESTORE +static int use_new_eh_code = FALSE; +#endif + struct proc_dir_entry proc_scsi_u14_34f = { PROC_SCSI_U14_34F, 6, "u14_34f", S_IFDIR | S_IRUGO | S_IXUGO, 2 @@ -361,6 +399,8 @@ struct proc_dir_entry proc_scsi_u14_34f = { #undef DEBUG_DETECT #undef DEBUG_INTERRUPT #undef DEBUG_RESET +#undef DEBUG_GENERATE_ERRORS +#undef DEBUG_GENERATE_ABORTS #define MAX_ISA 3 #define MAX_VESA 1 @@ -513,19 +553,19 @@ static int do_trace = FALSE; static int setup_done = FALSE; static int link_statistics = 0; -#if defined (HAVE_OLD_UX4F_FIRMWARE) +#if defined(HAVE_OLD_UX4F_FIRMWARE) static int have_old_firmware = TRUE; #else static int have_old_firmware = FALSE; #endif -#if defined (CONFIG_SCSI_U14_34F_LINKED_COMMANDS) +#if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS) static int linked_comm = TRUE; #else static int linked_comm = FALSE; #endif -#if defined CONFIG_SCSI_U14_34F_MAX_TAGS +#if defined(CONFIG_SCSI_U14_34F_MAX_TAGS) static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS; #else static int max_queue_depth = MAX_CMD_PER_LUN; @@ -534,11 +574,9 @@ static int max_queue_depth = MAX_CMD_PER_LUN; static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { Scsi_Device *dev; int j, ntag = 0, nuntag = 0, tqd, utqd; - unsigned long flags; - - save_flags(flags); - cli(); + IRQ_FLAGS + IRQ_LOCK_SAVE j = ((struct hostdata *) host->hostdata)->board_number; for(dev = devlist; dev; dev = dev->next) { @@ -586,7 +624,7 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { dev->queue_depth, link_suffix, tag_suffix); } - restore_flags(flags); + IRQ_UNLOCK_RESTORE return; } @@ -629,10 +667,12 @@ static int board_inquiry(unsigned int j) { /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); - sti(); + SPIN_UNLOCK + IRQ_UNLOCK time = jiffies; while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L); - cli(); + IRQ_LOCK + SPIN_LOCK if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) { HD(j)->cp_stat[0] = FREE; @@ -721,6 +761,14 @@ __initfunc (static inline int port_detect \ return FALSE; } + if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING; + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + tpnt->use_new_eh_code = use_new_eh_code; +#else + use_new_eh_code = FALSE; +#endif + sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); if (sh[j] == NULL) { @@ -754,6 +802,9 @@ __initfunc (static inline int port_detect \ } #endif + /* Probably a bogus host scsi id, set it to the dummy value */ + if (sh[j]->this_id == 0) sh[j]->this_id = -1; + /* If BIOS is disabled, force enable interrupts */ if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK); @@ -781,9 +832,6 @@ __initfunc (static inline int port_detect \ clear_dma_ff(dma_channel); set_dma_mode(dma_channel, DMA_MODE_CASCADE); enable_dma(dma_channel); - - if (have_old_firmware) sh[j]->hostt->use_clustering = DISABLE_CLUSTERING; - sh[j]->dma_channel = dma_channel; sprintf(BN(j), "U14F%d", j); bus_type = "ISA"; @@ -822,18 +870,23 @@ __initfunc (static inline int port_detect \ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; - printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d, of:%c, "\ - "lc:%c, mq:%d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port, - (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize, - sh[j]->can_queue, YESNO(have_old_firmware), YESNO(linked_comm), - max_queue_depth); + if (j == 0) { + printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n"); + printk("%s config options -> of:%c, lc:%c, mq:%d, eh:%c.\n", + driver_name, YESNO(have_old_firmware), YESNO(linked_comm), + max_queue_depth, YESNO(use_new_eh_code)); + } + + printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", + BN(j), bus_type, (unsigned long)sh[j]->io_port, (int)sh[j]->base, + sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); for (i = 0; i <= sh[j]->max_channel; i++) - printk("%s: SCSI channel %u enabled, host target ID %u.\n", + printk("%s: SCSI channel %u enabled, host target ID %d.\n", BN(j), i, sh[j]->this_id); return TRUE; @@ -864,6 +917,7 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) { else if (!strncmp(cur, "of:", 3)) have_old_firmware = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; + else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; if ((cur = strchr(cur, ','))) ++cur; } @@ -872,14 +926,12 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) { } __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) { - unsigned long flags; unsigned int j = 0, k; + IRQ_FLAGS + IRQ_LOCK_SAVE tpnt->proc_dir = &proc_scsi_u14_34f; - save_flags(flags); - cli(); - #if defined(MODULE) /* io_port could have been modified when loading as a module */ if(io_port[0] != SKIP) { @@ -897,11 +949,8 @@ __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) { if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++; } - if (j > 0) - printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n"); - num_boards = j; - restore_flags(flags); + IRQ_UNLOCK_RESTORE return j; } @@ -922,8 +971,7 @@ static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { cpp->data_len = H2DEV(data_len); } -int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - unsigned long flags; +static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; @@ -939,22 +987,12 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5 }; - save_flags(flags); - cli(); /* j is the board number */ j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; - if (!done) panic("%s: qcomm, pid %ld, null done.\n", BN(j), SCpnt->pid); - - if (SCpnt->cmnd[0] == REQUEST_SENSE && SCpnt->sense_buffer[0]) { - SCpnt->result = DID_OK << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d.%d:%d, pid %ld, request sense ignored.\n", - BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); - restore_flags(flags); - done(SCpnt); - return 0; - } + if (SCpnt->host_scribble) + panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", + BN(j), SCpnt->pid, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -971,19 +1009,7 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { } if (k == sh[j]->can_queue) { - printk("%s: qcomm, no free mailbox, resetting.\n", BN(j)); - - if (HD(j)->in_reset) - printk("%s: qcomm, already in reset.\n", BN(j)); - else if (u14_34f_reset(SCpnt, SCSI_RESET_SUGGEST_BUS_RESET) - == SCSI_RESET_SUCCESS) - panic("%s: qcomm, SCSI_RESET_SUCCESS.\n", BN(j)); - - SCpnt->result = DID_BUS_BUSY << 16; - SCpnt->host_scribble = NULL; - printk("%s: qcomm, pid %ld, DID_BUS_BUSY, done.\n", BN(j), SCpnt->pid); - restore_flags(flags); - done(SCpnt); + printk("%s: qcomm, no free mailbox.\n", BN(j)); return 1; } @@ -1038,18 +1064,13 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; flush_dev(SCpnt->device, SCpnt->request.sector, j, FALSE); - restore_flags(flags); return 0; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - SCpnt->result = DID_ERROR << 16; SCpnt->host_scribble = NULL; - printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\ - " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, - SCpnt->pid); - restore_flags(flags); - done(SCpnt); + printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n", + BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); return 1; } @@ -1060,23 +1081,29 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); HD(j)->cp_stat[i] = IN_USE; - restore_flags(flags); return 0; } -int u14_34f_abort(Scsi_Cmnd *SCarg) { - unsigned long flags; +int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_qcomm(SCpnt, done); + IRQ_UNLOCK_RESTORE + return rtn; +} + +static inline int do_old_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; - save_flags(flags); - cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - if (SCarg->host_scribble == NULL - || SCarg->serial_number != SCarg->serial_number_at_timeout) { + if (SCarg->host_scribble == NULL || + (SCarg->serial_number_at_timeout && + (SCarg->serial_number != SCarg->serial_number_at_timeout))) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1089,13 +1116,11 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) { if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: abort, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == FREE) { printk("%s: abort, mbox %d is free.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1109,19 +1134,16 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) { if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_SNOOZE; } if (HD(j)->cp_stat[i] == IN_RESET) { printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == LOCKED) { printk("%s: abort, mbox %d is locked.\n", BN(j), i); - restore_flags(flags); return SCSI_ABORT_NOT_RUNNING; } @@ -1132,45 +1154,128 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) { printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", BN(j), i, SCarg->pid); SCarg->scsi_done(SCarg); - restore_flags(flags); return SCSI_ABORT_SUCCESS; } - restore_flags(flags); panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - unsigned long flags; +int u14_34f_old_abort(Scsi_Cmnd *SCarg) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_old_abort(SCarg); + IRQ_UNLOCK_RESTORE + return rtn; +} + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + +static inline int do_abort(Scsi_Cmnd *SCarg) { + unsigned int i, j; + + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + + if (SCarg->host_scribble == NULL) { + printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + return SUCCESS; + } + + i = *(unsigned int *)SCarg->host_scribble; + printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", + BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + + if (i >= sh[j]->can_queue) + panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); + + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { + printk("%s: abort, timeout error.\n", BN(j)); + return FAILED; + } + + if (HD(j)->cp_stat[i] == FREE) { + printk("%s: abort, mbox %d is free.\n", BN(j), i); + return SUCCESS; + } + + if (HD(j)->cp_stat[i] == IN_USE) { + printk("%s: abort, mbox %d is in use.\n", BN(j), i); + + if (SCarg != HD(j)->cp[i].SCpnt) + panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", + BN(j), i, SCarg, HD(j)->cp[i].SCpnt); + + if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) + printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); + + if (SCarg->eh_state == SCSI_STATE_TIMEOUT) { + SCarg->host_scribble = NULL; + HD(j)->cp_stat[i] = FREE; + printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n", + BN(j), i, SCarg->pid); + return SUCCESS; + } + + return FAILED; + } + + if (HD(j)->cp_stat[i] == IN_RESET) { + printk("%s: abort, mbox %d is in reset.\n", BN(j), i); + return FAILED; + } + + if (HD(j)->cp_stat[i] == LOCKED) { + printk("%s: abort, mbox %d is locked.\n", BN(j), i); + return SUCCESS; + } + + if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { + SCarg->result = DID_ABORT << 16; + SCarg->host_scribble = NULL; + HD(j)->cp_stat[i] = FREE; + printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", + BN(j), i, SCarg->pid); + SCarg->scsi_done(SCarg); + return SUCCESS; + } + + panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); +} + +int u14_34f_abort(Scsi_Cmnd *SCarg) { + + return do_abort(SCarg); +} + +#endif /* new_eh_code */ + +static inline int do_old_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; - save_flags(flags); - cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid, - reset_flags); + printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); if (SCarg->host_scribble == NULL) printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - if (SCarg->serial_number != SCarg->serial_number_at_timeout) { + if (SCarg->serial_number_at_timeout && + (SCarg->serial_number != SCarg->serial_number_at_timeout)) { printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid); - restore_flags(flags); return SCSI_RESET_NOT_RUNNING; } if (HD(j)->in_reset) { printk("%s: reset, exit, already in reset.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, exit, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } @@ -1221,22 +1326,23 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - restore_flags(flags); return SCSI_RESET_ERROR; } outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); -#if defined (DEBUG_RESET) +#if defined(DEBUG_RESET) do_trace = TRUE; #endif HD(j)->in_reset = TRUE; - sti(); + SPIN_UNLOCK + IRQ_UNLOCK time = jiffies; while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); - cli(); + IRQ_LOCK + SPIN_LOCK printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); for (i = 0; i < sh[j]->can_queue; i++) { @@ -1270,14 +1376,12 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { /* Any other mailbox has already been set free by interrupt */ continue; - restore_flags(flags); SCpnt->scsi_done(SCpnt); - cli(); + IRQ_LOCK } HD(j)->in_reset = FALSE; do_trace = FALSE; - restore_flags(flags); if (arg_done) { printk("%s: reset, exit, success.\n", BN(j)); @@ -1289,6 +1393,157 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { } } +int u14_34f_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { + int rtn; + IRQ_FLAGS + + IRQ_LOCK_SAVE + rtn = do_old_reset(SCarg); + IRQ_UNLOCK_RESTORE + return rtn; +} + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) + +static inline int do_reset(Scsi_Cmnd *SCarg) { + unsigned int i, j, time, k, c, limit = 0; + int arg_done = FALSE; + Scsi_Cmnd *SCpnt; + + j = ((struct hostdata *) SCarg->host->hostdata)->board_number; + printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", + BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); + + if (SCarg->host_scribble == NULL) + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + + if (HD(j)->in_reset) { + printk("%s: reset, exit, already in reset.\n", BN(j)); + return FAILED; + } + + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { + printk("%s: reset, exit, timeout error.\n", BN(j)); + return FAILED; + } + + HD(j)->retries = 0; + + 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; + HD(j)->target_to[k][c] = 0; + } + + for (i = 0; i < sh[j]->can_queue; i++) { + + if (HD(j)->cp_stat[i] == FREE) continue; + + if (HD(j)->cp_stat[i] == LOCKED) { + HD(j)->cp_stat[i] = FREE; + printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); + continue; + } + + if (!(SCpnt = HD(j)->cp[i].SCpnt)) + panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); + + if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { + HD(j)->cp_stat[i] = ABORTING; + printk("%s: reset, mbox %d aborting, pid %ld.\n", + BN(j), i, SCpnt->pid); + } + + else { + HD(j)->cp_stat[i] = IN_RESET; + printk("%s: reset, mbox %d in reset, pid %ld.\n", + BN(j), i, SCpnt->pid); + } + + if (SCpnt->host_scribble == NULL) + panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); + + if (*(unsigned int *)SCpnt->host_scribble != i) + panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); + + if (SCpnt->scsi_done == NULL) + panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); + + if (SCpnt == SCarg) arg_done = TRUE; + } + + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { + printk("%s: reset, cannot reset, timeout error.\n", BN(j)); + return FAILED; + } + + outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); + printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); + +#if defined(DEBUG_RESET) + do_trace = TRUE; +#endif + + HD(j)->in_reset = TRUE; + SPIN_UNLOCK + IRQ_UNLOCK + time = jiffies; + while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); + IRQ_LOCK + SPIN_LOCK + printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); + + for (i = 0; i < sh[j]->can_queue; i++) { + + if (HD(j)->cp_stat[i] == IN_RESET) { + SCpnt = HD(j)->cp[i].SCpnt; + SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; + + /* This mailbox is still waiting for its interrupt */ + HD(j)->cp_stat[i] = LOCKED; + + printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", + BN(j), i, SCpnt->pid); + } + + else if (HD(j)->cp_stat[i] == ABORTING) { + SCpnt = HD(j)->cp[i].SCpnt; + SCpnt->result = DID_RESET << 16; + SCpnt->host_scribble = NULL; + + /* This mailbox was never queued to the adapter */ + HD(j)->cp_stat[i] = FREE; + + printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", + BN(j), i, SCpnt->pid); + } + + else + + /* Any other mailbox has already been set free by interrupt */ + continue; + + SCpnt->scsi_done(SCpnt); + IRQ_LOCK + } + + HD(j)->in_reset = FALSE; + do_trace = FALSE; + + if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); + else printk("%s: reset, exit.\n", BN(j)); + + return SUCCESS; +} + +int u14_34f_reset(Scsi_Cmnd *SCarg) { + + return do_reset(SCarg); +} + +#endif /* new_eh_code */ + int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { unsigned int j = 0; int size = disk->capacity; @@ -1406,7 +1661,7 @@ static inline int reorder(unsigned int j, unsigned long cursec, if (!rev && !s) { sortcount++; readysorted += n_ready; } } -#if defined (DEBUG_LINKED_COMMANDS) +#if defined(DEBUG_LINKED_COMMANDS) if (link_statistics && (overlap || !(flushcount % link_statistics))) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; @@ -1491,6 +1746,10 @@ static inline void ihdlr(int irq, unsigned int j) { /* Clear interrupt pending flag */ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); +#if defined(DEBUG_GENERATE_ABORTS) + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return; +#endif + /* Find the mailbox to be serviced on this board */ i = cpp - HD(j)->cp; @@ -1539,6 +1798,11 @@ static inline void ihdlr(int irq, unsigned int j) { tstatus = status_byte(spp->target_status); +#if defined(DEBUG_GENERATE_ERRORS) + if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 200) < 2)) + spp->adapter_status = 0x01; +#endif + switch (spp->adapter_status) { case ASOK: /* status OK */ @@ -1601,7 +1865,13 @@ static inline void ihdlr(int irq, unsigned int j) { if (SCpnt->device->type != TYPE_TAPE && HD(j)->retries < MAX_INTERNAL_RETRIES) { + +#if defined(DID_SOFT_ERROR) + status = DID_SOFT_ERROR << 16; +#else status = DID_BUS_BUSY << 16; +#endif + HD(j)->retries++; HD(j)->last_retried_pid = SCpnt->pid; } @@ -1623,7 +1893,7 @@ static inline void ihdlr(int irq, unsigned int j) { SCpnt->result = status | spp->target_status; -#if defined (DEBUG_INTERRUPT) +#if defined(DEBUG_INTERRUPT) if (SCpnt->result || do_trace) #else if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || @@ -1649,31 +1919,25 @@ static inline void ihdlr(int irq, unsigned int j) { } static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) { - unsigned int j; + IRQ_FLAGS + SPIN_FLAGS /* 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; - spin_lock_irqsave(&io_request_lock, flags); + SPIN_LOCK_SAVE + IRQ_LOCK_SAVE ihdlr(irq, j); - spin_unlock_irqrestore(&io_request_lock, flags); - } -#else - ihdlr(irq, j); -#endif - + IRQ_UNLOCK_RESTORE + SPIN_UNLOCK_RESTORE } int u14_34f_release(struct Scsi_Host *shpnt) { - unsigned long flags; unsigned int i, j; + IRQ_FLAGS - save_flags(flags); - cli(); + IRQ_LOCK_SAVE for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); @@ -1689,7 +1953,7 @@ int u14_34f_release(struct Scsi_Host *shpnt) { release_region(sh[j]->io_port, sh[j]->n_io_port); scsi_unregister(sh[j]); - restore_flags(flags); + IRQ_UNLOCK_RESTORE return FALSE; } diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h index 3c5e4a75cf01..470296419488 100644 --- a/drivers/scsi/u14-34f.h +++ b/drivers/scsi/u14-34f.h @@ -10,42 +10,48 @@ int u14_34f_detect(Scsi_Host_Template *); int u14_34f_release(struct Scsi_Host *); int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int u14_34f_abort(Scsi_Cmnd *); -int u14_34f_reset(Scsi_Cmnd *, unsigned int); +int u14_34f_old_abort(Scsi_Cmnd *); +int u14_34f_reset(Scsi_Cmnd *); +int u14_34f_old_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "4.20.00" +#define U14_34F_VERSION "4.31.00" #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,88) +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ - detect: u14_34f_detect, \ - release: u14_34f_release, \ - queuecommand: u14_34f_queuecommand, \ - abort: u14_34f_abort, \ - reset: u14_34f_reset, \ - bios_param: u14_34f_biosparam, \ - this_id: 7, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 /* Enable new error code */ \ + detect: u14_34f_detect, \ + release: u14_34f_release, \ + queuecommand: u14_34f_queuecommand, \ + abort: u14_34f_old_abort, \ + reset: u14_34f_old_reset, \ + eh_abort_handler: u14_34f_abort, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: u14_34f_reset, \ + bios_param: u14_34f_biosparam, \ + this_id: 7, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* Enable new error code */ \ } #else /* Use old scsi code */ #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ - detect: u14_34f_detect, \ - release: u14_34f_release, \ - queuecommand: u14_34f_queuecommand, \ - abort: u14_34f_abort, \ - reset: u14_34f_reset, \ - bios_param: u14_34f_biosparam, \ - this_id: 7, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ + detect: u14_34f_detect, \ + release: u14_34f_release, \ + queuecommand: u14_34f_queuecommand, \ + abort: u14_34f_old_abort, \ + reset: u14_34f_old_reset, \ + bios_param: u14_34f_biosparam, \ + this_id: 7, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING \ } #endif diff --git a/include/linux/modversions.h b/include/linux/modversions.h deleted file mode 100644 index 1103f939de1b..000000000000 --- a/include/linux/modversions.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifdef MODVERSIONS -#undef CONFIG_MODVERSIONS -#define CONFIG_MODVERSIONS -#ifndef _set_ver -#define _set_ver(sym,vers) sym ## _R ## vers -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#undef CONFIG_MODVERSIONS -#endif diff --git a/scripts/Menuconfig b/scripts/Menuconfig index 76404b0d0b98..48e93c8e8c03 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -70,10 +70,10 @@ function comment () { } # -# Don't need this yet, but we don't want to puke either. +# Define a boolean to a specific value. # function define_bool () { - : + eval $1=$2 } # -- 2.39.5