diff options
Diffstat (limited to 'drivers/scsi/sym53c8xx_2')
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_defs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_glue.c | 205 | ||||
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_glue.h | 2 | ||||
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_hipd.c | 113 | ||||
-rw-r--r-- | drivers/scsi/sym53c8xx_2/sym_hipd.h | 2 |
5 files changed, 118 insertions, 206 deletions
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h index 3659dd7b9d76..defccc477d1e 100644 --- a/drivers/scsi/sym53c8xx_2/sym_defs.h +++ b/drivers/scsi/sym53c8xx_2/sym_defs.h @@ -40,7 +40,7 @@ #ifndef SYM_DEFS_H #define SYM_DEFS_H -#define SYM_VERSION "2.2.2" +#define SYM_VERSION "2.2.3" #define SYM_DRIVER_NAME "sym-" SYM_VERSION /* diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 1fffd2b3c654..9c83b4d39a26 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -134,66 +134,17 @@ static void sym2_setup_params(void) } } -/* - * We used to try to deal with 64-bit BARs here, but don't any more. - * There are many parts of this driver which would need to be modified - * to handle a 64-bit base address, including scripts. I'm uncomfortable - * with making those changes when I have no way of testing it, so I'm - * just going to disable it. - * - * Note that some machines (eg HP rx8620 and Superdome) have bus addresses - * below 4GB and physical addresses above 4GB. These will continue to work. - */ -static int __devinit -pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep) -{ - u32 tmp; - unsigned long base; -#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2)) - - pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp); - base = tmp; - if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp); - if (tmp > 0) { - dev_err(&pdev->dev, - "BAR %d is 64-bit, disabling\n", index - 1); - base = 0; - } - } - - if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { - base &= PCI_BASE_ADDRESS_IO_MASK; - } else { - base &= PCI_BASE_ADDRESS_MEM_MASK; - } - - *basep = base; - return index; -#undef PCI_BAR_OFFSET -} - static struct scsi_transport_template *sym2_transport_template = NULL; /* - * Used by the eh thread to wait for command completion. - * It is allocated on the eh thread stack. - */ -struct sym_eh_wait { - struct completion done; - struct timer_list timer; - void (*old_done)(struct scsi_cmnd *); - int to_do; - int timed_out; -}; - -/* * Driver private area in the SCSI command structure. */ struct sym_ucmd { /* Override the SCSI pointer structure */ - dma_addr_t data_mapping; - u_char data_mapped; - struct sym_eh_wait *eh_wait; + dma_addr_t data_mapping; + unsigned char data_mapped; + unsigned char to_do; /* For error handling */ + void (*old_done)(struct scsi_cmnd *); /* For error handling */ + struct completion *eh_done; /* For error handling */ }; #define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp)) @@ -514,8 +465,6 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struc */ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp) { - struct sym_tcb *tp = &np->target[cp->target]; - struct sym_lcb *lp = sym_lp(tp, cp->lun); u32 lastp, goalp; int dir; @@ -596,7 +545,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s /* * activate this job. */ - sym_start_next_ccbs(np, lp, 2); + sym_put_start_queue(np, cp); return 0; out_abort: @@ -751,80 +700,54 @@ static void sym53c8xx_timer(unsigned long npref) * What we will do regarding the involved SCSI command. */ #define SYM_EH_DO_IGNORE 0 -#define SYM_EH_DO_COMPLETE 1 #define SYM_EH_DO_WAIT 2 /* - * Our general completion handler. + * scsi_done() alias when error recovery is in progress. */ -static void __sym_eh_done(struct scsi_cmnd *cmd, int timed_out) +static void sym_eh_done(struct scsi_cmnd *cmd) { - struct sym_eh_wait *ep = SYM_UCMD_PTR(cmd)->eh_wait; - if (!ep) - return; - - /* Try to avoid a race here (not 100% safe) */ - if (!timed_out) { - ep->timed_out = 0; - if (ep->to_do == SYM_EH_DO_WAIT && !del_timer(&ep->timer)) - return; - } + struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); + BUILD_BUG_ON(sizeof(struct scsi_pointer) < sizeof(struct sym_ucmd)); - /* Revert everything */ - SYM_UCMD_PTR(cmd)->eh_wait = NULL; - cmd->scsi_done = ep->old_done; + cmd->scsi_done = ucmd->old_done; - /* Wake up the eh thread if it wants to sleep */ - if (ep->to_do == SYM_EH_DO_WAIT) - complete(&ep->done); + if (ucmd->to_do == SYM_EH_DO_WAIT) + complete(ucmd->eh_done); } /* - * scsi_done() alias when error recovery is in progress. - */ -static void sym_eh_done(struct scsi_cmnd *cmd) { __sym_eh_done(cmd, 0); } - -/* - * Some timeout handler to avoid waiting too long. - */ -static void sym_eh_timeout(u_long p) { __sym_eh_done((struct scsi_cmnd *)p, 1); } - -/* * Generic method for our eh processing. * The 'op' argument tells what we have to do. */ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) { struct sym_hcb *np = SYM_SOFTC_PTR(cmd); + struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd); + struct Scsi_Host *host = cmd->device->host; SYM_QUEHEAD *qp; int to_do = SYM_EH_DO_IGNORE; int sts = -1; - struct sym_eh_wait eh, *ep = &eh; + struct completion eh_done; dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname); + spin_lock_irq(host->host_lock); /* This one is queued in some place -> to wait for completion */ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); if (cp->cmd == cmd) { to_do = SYM_EH_DO_WAIT; - goto prepare; + break; } } -prepare: - /* Prepare stuff to either ignore, complete or wait for completion */ - switch(to_do) { - default: - case SYM_EH_DO_IGNORE: - break; - case SYM_EH_DO_WAIT: - init_completion(&ep->done); - /* fall through */ - case SYM_EH_DO_COMPLETE: - ep->old_done = cmd->scsi_done; + if (to_do == SYM_EH_DO_WAIT) { + init_completion(&eh_done); + ucmd->old_done = cmd->scsi_done; + ucmd->eh_done = &eh_done; + wmb(); cmd->scsi_done = sym_eh_done; - SYM_UCMD_PTR(cmd)->eh_wait = ep; } /* Try to proceed the operation we have been asked for */ @@ -851,29 +774,19 @@ prepare: /* On error, restore everything and cross fingers :) */ if (sts) { - SYM_UCMD_PTR(cmd)->eh_wait = NULL; - cmd->scsi_done = ep->old_done; + cmd->scsi_done = ucmd->old_done; to_do = SYM_EH_DO_IGNORE; } - ep->to_do = to_do; - /* Complete the command with locks held as required by the driver */ - if (to_do == SYM_EH_DO_COMPLETE) - sym_xpt_done2(np, cmd, DID_ABORT); + ucmd->to_do = to_do; + spin_unlock_irq(host->host_lock); - /* Wait for completion with locks released, as required by kernel */ if (to_do == SYM_EH_DO_WAIT) { - init_timer(&ep->timer); - ep->timer.expires = jiffies + (5*HZ); - ep->timer.function = sym_eh_timeout; - ep->timer.data = (u_long)cmd; - ep->timed_out = 1; /* Be pessimistic for once :) */ - add_timer(&ep->timer); - spin_unlock_irq(np->s.host->host_lock); - wait_for_completion(&ep->done); - spin_lock_irq(np->s.host->host_lock); - if (ep->timed_out) + if (!wait_for_completion_timeout(&eh_done, 5*HZ)) { + ucmd->to_do = SYM_EH_DO_IGNORE; + wmb(); sts = -2; + } } dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname, sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed"); @@ -886,46 +799,22 @@ prepare: */ static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd) { - int rc; - - spin_lock_irq(cmd->device->host->host_lock); - rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd); - spin_unlock_irq(cmd->device->host->host_lock); - - return rc; + return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd); } static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd) { - int rc; - - spin_lock_irq(cmd->device->host->host_lock); - rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd); - spin_unlock_irq(cmd->device->host->host_lock); - - return rc; + return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd); } static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd) { - int rc; - - spin_lock_irq(cmd->device->host->host_lock); - rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd); - spin_unlock_irq(cmd->device->host->host_lock); - - return rc; + return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd); } static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd) { - int rc; - - spin_lock_irq(cmd->device->host->host_lock); - rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd); - spin_unlock_irq(cmd->device->host->host_lock); - - return rc; + return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd); } /* @@ -944,15 +833,12 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags) if (reqtags > lp->s.scdev_depth) reqtags = lp->s.scdev_depth; - lp->started_limit = reqtags ? reqtags : 2; - lp->started_max = 1; lp->s.reqtags = reqtags; if (reqtags != oldtags) { dev_info(&tp->starget->dev, "tagged command queuing %s, command queue depth %d.\n", - lp->s.reqtags ? "enabled" : "disabled", - lp->started_limit); + lp->s.reqtags ? "enabled" : "disabled", reqtags); } } @@ -1866,15 +1752,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device) static void __devinit sym_init_device(struct pci_dev *pdev, struct sym_device *device) { - int i; + int i = 2; + struct pci_bus_region bus_addr; device->host_id = SYM_SETUP_HOST_ID; device->pdev = pdev; - i = pci_get_base_address(pdev, 1, &device->mmio_base); - pci_get_base_address(pdev, i, &device->ram_base); + pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]); + device->mmio_base = bus_addr.start; + + /* + * If the BAR is 64-bit, resource 2 will be occupied by the + * upper 32 bits + */ + if (!pdev->resource[i].flags) + i++; + pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]); + device->ram_base = bus_addr.start; -#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED +#ifdef CONFIG_SCSI_SYM53C8XX_MMIO if (device->mmio_base) device->s.ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1)); @@ -1978,7 +1874,8 @@ static struct scsi_host_template sym2_template = { .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, .eh_host_reset_handler = sym53c8xx_eh_host_reset_handler, .this_id = 7, - .use_clustering = DISABLE_CLUSTERING, + .use_clustering = ENABLE_CLUSTERING, + .max_sectors = 0xFFFF, #ifdef SYM_LINUX_PROC_INFO_SUPPORT .proc_info = sym53c8xx_proc_info, .proc_name = NAME53C8XX, diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h index cc92d0c70cd7..a446cda3f64c 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.h +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h @@ -68,7 +68,7 @@ */ #define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2) -#define SYM_OPT_HANDLE_DEVICE_QUEUEING +#undef SYM_OPT_HANDLE_DEVICE_QUEUEING #define SYM_OPT_LIMIT_COMMAND_REORDERING /* diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 60850cbe3a85..a671bdc07450 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -72,7 +72,10 @@ static void sym_printl_hex(u_char *p, int n) static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg) { - sym_print_addr(cp->cmd, "%s: ", label); + if (label) + sym_print_addr(cp->cmd, "%s: ", label); + else + sym_print_addr(cp->cmd, ""); spi_print_msg(msg); printf("\n"); @@ -472,7 +475,7 @@ static int sym_getpciclock (struct sym_hcb *np) * calculations more simple. */ #define _5M 5000000 -static u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; +static const u32 div_10M[] = {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; /* * Get clock factor and sync divisor for a given @@ -645,6 +648,37 @@ static void sym_save_initial_setting (struct sym_hcb *np) } /* + * Set SCSI BUS mode. + * - LVD capable chips (895/895A/896/1010) report the current BUS mode + * through the STEST4 IO register. + * - For previous generation chips (825/825A/875), the user has to tell us + * how to check against HVD, since a 100% safe algorithm is not possible. + */ +static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram) +{ + if (np->scsi_mode) + return; + + np->scsi_mode = SMODE_SE; + if (np->features & (FE_ULTRA2|FE_ULTRA3)) + np->scsi_mode = (np->sv_stest4 & SMODE); + else if (np->features & FE_DIFF) { + if (SYM_SETUP_SCSI_DIFF == 1) { + if (np->sv_scntl3) { + if (np->sv_stest2 & 0x20) + np->scsi_mode = SMODE_HVD; + } else if (nvram->type == SYM_SYMBIOS_NVRAM) { + if (!(INB(np, nc_gpreg) & 0x08)) + np->scsi_mode = SMODE_HVD; + } + } else if (SYM_SETUP_SCSI_DIFF == 2) + np->scsi_mode = SMODE_HVD; + } + if (np->scsi_mode == SMODE_HVD) + np->rv_stest2 |= 0x20; +} + +/* * Prepare io register values used by sym_start_up() * according to selected and supported features. */ @@ -654,10 +688,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru u32 period; int i; - /* - * Wide ? - */ - np->maxwide = (np->features & FE_WIDE)? 1 : 0; + np->maxwide = (np->features & FE_WIDE) ? 1 : 0; /* * Guess the frequency of the chip's clock. @@ -838,6 +869,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * Get parity checking, host ID and verbose mode from NVRAM */ np->myaddr = 255; + np->scsi_mode = 0; sym_nvram_setup_host(shost, np, nvram); /* @@ -854,33 +886,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru */ sym_init_burst(np, burst_max); - /* - * Set SCSI BUS mode. - * - LVD capable chips (895/895A/896/1010) report the - * current BUS mode through the STEST4 IO register. - * - For previous generation chips (825/825A/875), - * user has to tell us how to check against HVD, - * since a 100% safe algorithm is not possible. - */ - np->scsi_mode = SMODE_SE; - if (np->features & (FE_ULTRA2|FE_ULTRA3)) - np->scsi_mode = (np->sv_stest4 & SMODE); - else if (np->features & FE_DIFF) { - if (SYM_SETUP_SCSI_DIFF == 1) { - if (np->sv_scntl3) { - if (np->sv_stest2 & 0x20) - np->scsi_mode = SMODE_HVD; - } - else if (nvram->type == SYM_SYMBIOS_NVRAM) { - if (!(INB(np, nc_gpreg) & 0x08)) - np->scsi_mode = SMODE_HVD; - } - } - else if (SYM_SETUP_SCSI_DIFF == 2) - np->scsi_mode = SMODE_HVD; - } - if (np->scsi_mode == SMODE_HVD) - np->rv_stest2 |= 0x20; + sym_set_bus_mode(np, nvram); /* * Set LED support from SCRIPTS. @@ -973,8 +979,8 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru * * Has to be called with interrupts disabled. */ -#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED -static int sym_regtest (struct sym_hcb *np) +#ifdef CONFIG_SCSI_SYM53C8XX_MMIO +static int sym_regtest(struct sym_hcb *np) { register volatile u32 data; /* @@ -992,20 +998,25 @@ static int sym_regtest (struct sym_hcb *np) #endif printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", (unsigned) data); - return (0x10); + return 0x10; } - return (0); + return 0; +} +#else +static inline int sym_regtest(struct sym_hcb *np) +{ + return 0; } #endif -static int sym_snooptest (struct sym_hcb *np) +static int sym_snooptest(struct sym_hcb *np) { - u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat; - int i, err=0; -#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED - err |= sym_regtest (np); - if (err) return (err); -#endif + u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat; + int i, err; + + err = sym_regtest(np); + if (err) + return err; restart_test: /* * Enable Master Parity Checking as we intend @@ -1094,7 +1105,7 @@ restart_test: err |= 4; } - return (err); + return err; } /* @@ -1464,7 +1475,7 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp /* * Insert a job into the start queue. */ -static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp) +void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp) { u_short qidx; @@ -4481,7 +4492,7 @@ static void sym_int_sir (struct sym_hcb *np) switch (np->msgin [2]) { case M_X_MODIFY_DP: if (DEBUG_FLAGS & DEBUG_POINTER) - sym_print_msg(cp,"modify DP",np->msgin); + sym_print_msg(cp, NULL, np->msgin); tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + (np->msgin[5]<<8) + (np->msgin[6]); sym_modify_dp(np, tp, cp, tmp); @@ -4508,7 +4519,7 @@ static void sym_int_sir (struct sym_hcb *np) */ case M_IGN_RESIDUE: if (DEBUG_FLAGS & DEBUG_POINTER) - sym_print_msg(cp,"ign wide residue", np->msgin); + sym_print_msg(cp, NULL, np->msgin); if (cp->host_flags & HF_SENSE) OUTL_DSP(np, SCRIPTA_BA(np, clrack)); else @@ -4597,7 +4608,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t * Debugging purpose. */ #ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING - assert(lp->busy_itl == 0); + if (lp->busy_itl != 0) + goto out_free; #endif /* * Allocate resources for tags if not yet. @@ -4642,7 +4654,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t * Debugging purpose. */ #ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING - assert(lp->busy_itl == 0 && lp->busy_itlq == 0); + if (lp->busy_itl != 0 || lp->busy_itlq != 0) + goto out_free; #endif /* * Count this nexus for this LUN. diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 2456090bb241..79ab6a177039 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -1049,6 +1049,8 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int); struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision); #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn); +#else +void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp); #endif void sym_start_up(struct sym_hcb *np, int reason); void sym_interrupt(struct sym_hcb *np); |