diff --git a/qla_isp/common/isp.c b/qla_isp/common/isp.c index ca6efae36..96e866ad3 100644 --- a/qla_isp/common/isp.c +++ b/qla_isp/common/isp.c @@ -1,4 +1,4 @@ -/* $Id: isp.c,v 1.190 2008/01/07 19:07:06 mjacob Exp $ */ +/* $Id: isp.c,v 1.192 2008/01/08 22:14:29 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -210,6 +210,11 @@ isp_reset(ispsoftc_t *isp) static const char dcrc[] = "Downloaded RISC Code Checksum Failure"; isp->isp_state = ISP_NILSTATE; + if (isp->isp_dead) { + isp_shutdown(isp); + ISP_DISABLE_INTS(isp); + return; + } /* * Basic types (SCSI, FibreChannel and PCI or SBus) @@ -223,6 +228,7 @@ isp_reset(ispsoftc_t *isp) ISP_DISABLE_INTS(isp); + /* * Pick an initial maxcmds value which will be used * to allocate xflist pointer space. It may be changed @@ -1118,6 +1124,11 @@ isp_reset(ispsoftc_t *isp) for (i = 0; i < isp->isp_nchan; i++) { isp_fw_state(isp, i); } + if (isp->isp_dead) { + isp_shutdown(isp); + ISP_DISABLE_INTS(isp); + return; + } isp->isp_state = ISP_RESETSTATE; @@ -1902,10 +1913,15 @@ isp_fibre_init_2400(ispsoftc_t *isp) icbp->icb_fwoptions2 = fcp->isp_xfwoptions; switch(isp->isp_confopts & ISP_CFG_PORT_PREF) { +#if 0 case ISP_CFG_NPORT: + /* + * XXX: This causes the f/w to crash. + */ icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP; break; +#endif case ISP_CFG_NPORT_ONLY: icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK; icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY; @@ -5581,6 +5597,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp_async(isp, ISPASYNC_BUS_RESET, chan); break; case ASYNC_SYSTEM_ERROR: + isp->isp_dead = 1; isp->isp_state = ISP_CRASHED; if (IS_FC(isp)) { FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL; @@ -6034,6 +6051,8 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) "Point-to-Point -> Loop mode (BAD LIP)"); break; case ISP_CONN_FATAL: + isp->isp_dead = 1; + isp->isp_state = ISP_CRASHED; isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR"); isp_async(isp, ISPASYNC_FW_CRASH); return (-1); @@ -7937,7 +7956,6 @@ isp_reinit(ispsoftc_t *isp) isp_done(xs); } #ifdef ISP_TARGET_MODE -/* XXXXXXXXX NOT SUFFICCIENT XXXXXXXXX */ MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **)); #endif } diff --git a/qla_isp/common/ispvar.h b/qla_isp/common/ispvar.h index ee2aab5bf..f5ed946b0 100644 --- a/qla_isp/common/ispvar.h +++ b/qla_isp/common/ispvar.h @@ -1,4 +1,4 @@ -/* $Id: ispvar.h,v 1.90 2008/01/04 16:46:10 mjacob Exp $ */ +/* $Id: ispvar.h,v 1.91 2008/01/08 20:40:22 mjacob Exp $ */ /*- * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -563,7 +563,8 @@ struct ispsoftc { */ volatile uint32_t : 8, - : 3, + : 2, + isp_dead : 1, isp_in_intr : 1, isp_mboxbsy : 1, /* mailbox command active */ isp_state : 3, diff --git a/qla_isp/linux/isp_cb_ops.c b/qla_isp/linux/isp_cb_ops.c index 0c06d5f74..b0ce32268 100644 --- a/qla_isp/linux/isp_cb_ops.c +++ b/qla_isp/linux/isp_cb_ops.c @@ -1,4 +1,4 @@ -/* $Id: isp_cb_ops.c,v 1.83 2008/01/07 19:07:32 mjacob Exp $ */ +/* $Id: isp_cb_ops.c,v 1.84 2008/01/08 18:31:21 mjacob Exp $ */ /* * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -399,7 +399,7 @@ isp_close(struct inode *ip, struct file *fp) return (0); } -static int isp_tur_test(ispsoftc_t *, isp_turtst_t *); +static int isp_perf_test(ispsoftc_t *, isp_perftst_t *); static int isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg) @@ -795,15 +795,15 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg) } break; } - case ISP_FC_TURTST: + case ISP_FC_PERFTST: { - isp_turtst_t local, *tt = &local; + isp_perftst_t local, *tt = &local; if (COPYIN((void *)arg, tt, sizeof (*tt))) { rv = -EFAULT; break; } - rv = isp_tur_test(isp, tt); + rv = isp_perf_test(isp, tt); break; } default: @@ -1839,7 +1839,7 @@ out: } static int -isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) +isp_perf_test(ispsoftc_t *isp, isp_perftst_t *tt) { struct scsi_device *dev = NULL; Scsi_Cmnd *Cmnd = NULL; @@ -1847,19 +1847,35 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) struct Scsi_Host *host = NULL; uint32_t nxti, optr, handle; uint8_t local[QENTRY_LEN]; - ispreq_t *reqp = (ispreq_t *) local; - int result = 0, i; + int result = 0, i, iswrite, amt; void *qep, *qel = local; DECLARE_MUTEX_LOCKED(rsem); unsigned long flags; + if (IS_SCSI(isp)) { + return (-ENODEV); + } if (tt->target < 0 || tt->target >= MAX_FC_TARG) { return (-ENODEV); } + if (tt->channel < 0 || tt->channel >= isp->isp_nchan) { return (-ENODEV); } + iswrite = 0; + if (tt->ioszdir) { + amt = tt->ioszdir; + if (amt < 0) { + iswrite = 1; + amt = -amt; + } + if (amt > ISP_FC_SCRLEN) { + return (-ENOMEM); + } + } else { + amt = 0; + } i = FCPARAM(isp, tt->channel)->isp_ini_map[tt->target] - 1; if (i < 0 || i >= MAX_FC_TARG) { return (-ENXIO); @@ -1880,6 +1896,7 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) isp_kfree(Cmnd, sizeof (Scsi_Cmnd)); return (-ENOMEM); } + Cmnd->device = dev; dev->host = host; Cmnd->scsi_done = isp_run_cmd_done; @@ -1887,11 +1904,11 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) Cmnd->cmd_len = 6; Cmnd->sc_data_direction = SCSI_DATA_NONE; - reqp->req_header.rqs_entry_count = 1; if (IS_24XX(isp)) { ispreqt7_t *t7 = (ispreqt7_t *) local; - reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS; + t7->req_header.rqs_entry_type = RQSTYPE_T7RQS; + t7->req_header.rqs_entry_count = 1; t7->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE; t7->req_nphdl = lp->handle; t7->req_tidlo = lp->portid; @@ -1902,36 +1919,56 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) } t7->req_lun[1] = tt->lun & 0xff; t7->req_time = 30; - t7->req_seg_count = 0; - t7->req_vpidx = tt->channel; - MEMZERO(t7->req_cdb, sizeof (t7->req_cdb)); - } else if (IS_FC(isp)) { - ispreqt2_t *t2 = (ispreqt2_t *) local; - - reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; - t2->req_flags = REQFLAG_STAG; - - if (ISP_CAP_2KLOGIN(isp)) { - ((ispreqt2e_t *)reqp)->req_target = lp->handle; - ((ispreqt2e_t *)reqp)->req_scclun = tt->lun; - } else if (ISP_CAP_SCCFW(isp)) { - t2->req_target = lp->handle; - t2->req_scclun = tt->lun; + if (amt) { + t7->req_seg_count = 1; + if (iswrite) { + t7->req_alen_datadir = FCP_CMND_DATA_WRITE; + t7->req_cdb[0] = 0xa; + } else { + t7->req_alen_datadir = FCP_CMND_DATA_READ; + t7->req_cdb[0] = 0x8; + } + t7->req_cdb[4] = amt >> 9; + t7->req_dl = amt; + t7->req_dataseg.ds_base = DMA_LO32(FCPARAM(isp, tt->channel)->isp_scdma); + t7->req_dataseg.ds_basehi = DMA_HI32(FCPARAM(isp, tt->channel)->isp_scdma); + t7->req_dataseg.ds_count = amt; } else { - t2->req_target = lp->handle; - t2->req_lun_trn = tt->lun; + t7->req_seg_count = 0; } - MEMZERO(t2->req_cdb, sizeof (t2->req_cdb)); - t2->req_time = 30; + t7->req_vpidx = tt->channel; } else { - reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST; - reqp->req_flags = REQFLAG_STAG; - reqp->req_target = tt->target; - reqp->req_target |= (tt->channel << 7); - reqp->req_lun_trn = tt->lun; - reqp->req_cdblen = 6; - MEMZERO(reqp->req_cdb, sizeof (reqp->req_cdb)); - reqp->req_time = 30; + ispreqt3_t *t3 = (ispreqt3_t *) local; + + t3->req_header.rqs_entry_type = RQSTYPE_T3RQS; + t3->req_header.rqs_entry_count = 1; + t3->req_flags = REQFLAG_STAG; + + if (amt) { + if (iswrite) { + t3->req_flags |= REQFLAG_DATA_OUT; + t3->req_cdb[0] = 0xa; + } else { + t3->req_flags |= REQFLAG_DATA_IN; + t3->req_cdb[0] = 0x8; + } + t3->req_cdb[4] = amt >> 9; + t3->req_dataseg[0].ds_base = DMA_LO32(FCPARAM(isp, tt->channel)->isp_scdma); + t3->req_dataseg[0].ds_basehi = DMA_HI32(FCPARAM(isp, tt->channel)->isp_scdma); + t3->req_dataseg[0].ds_count = amt; + t3->req_totalcnt = amt; + } + if (ISP_CAP_2KLOGIN(isp)) { + ((ispreqt3e_t *)t3)->req_target = lp->handle; + ((ispreqt3e_t *)t3)->req_scclun = tt->lun; + } else if (ISP_CAP_SCCFW(isp)) { + t3->req_target = lp->handle; + t3->req_scclun = tt->lun; + } else { + t3->req_target = lp->handle; + t3->req_lun_trn = tt->lun; + } + t3->req_time = 30; } for (i = 0; i < tt->count; i++) { @@ -1953,17 +1990,15 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt) } else { handle = ISP_SPCL_HANDLE; } - reqp->req_handle = handle; + ((ispreq_t *)local)->req_handle = handle; if (IS_24XX(isp)) { isp_put_request_t7(isp, qel, qep); - } else if (IS_FC(isp)) { + } else { if (ISP_CAP_2KLOGIN(isp)) { isp_put_request_t2e(isp, qel, qep); } else { isp_put_request_t2(isp, qel, qep); } - } else { - isp_put_request(isp, qel, qep); } ISP_ADD_REQUEST(isp, nxti); if (handle != ISP_SPCL_HANDLE) { diff --git a/qla_isp/linux/isp_ioctl.h b/qla_isp/linux/isp_ioctl.h index c0797f6c7..9d0578bc3 100644 --- a/qla_isp/linux/isp_ioctl.h +++ b/qla_isp/linux/isp_ioctl.h @@ -1,4 +1,4 @@ -/* $Id: isp_ioctl.h,v 1.26 2008/01/07 19:07:32 mjacob Exp $ */ +/* $Id: isp_ioctl.h,v 1.27 2008/01/08 18:31:21 mjacob Exp $ */ /* * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -235,10 +235,11 @@ typedef struct { /* * This is a trigger for a performance test. */ -#define ISP_FC_TURTST (ISP_IOC | 44) +#define ISP_FC_PERFTST (ISP_IOC | 44) typedef struct { uint32_t channel, target, lun, count; -} isp_turtst_t; + int32_t ioszdir; +} isp_perftst_t; /* * vim:ts=4:sw=4:expandtab */ diff --git a/qla_isp/linux/isp_linux.c b/qla_isp/linux/isp_linux.c index 5c489e3d0..fb0fdaf62 100644 --- a/qla_isp/linux/isp_linux.c +++ b/qla_isp/linux/isp_linux.c @@ -1,4 +1,4 @@ -/* $Id: isp_linux.c,v 1.216 2008/01/04 18:00:20 mjacob Exp $ */ +/* $Id: isp_linux.c,v 1.219 2008/01/08 22:15:01 mjacob Exp $ */ /* * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -181,7 +181,7 @@ isplinux_append_to_waitq(ispsoftc_t *isp, Scsi_Cmnd *Cmnd) * If we're a fibre channel card and we consider the loop to be * down, we just finish the command here and now. */ - if (IS_FC(isp) && ISP_DATA(isp, XS_CHANNEL(Cmnd))->deadloop) { + if ((IS_FC(isp) && ISP_DATA(isp, XS_CHANNEL(Cmnd))->deadloop) || isp->isp_dead) { XS_INITERR(Cmnd); XS_SETERR(Cmnd, DID_NO_CONNECT); /* @@ -2705,8 +2705,9 @@ isp_enable_lun(ispsoftc_t *isp, uint16_t bus, uint16_t lun) } /* - * Validity check with our enable ruleset. We can't enable busses > 1 - * without enabling bus 0 first in some kind of role. + * Validity check with our enable ruleset. + * We can't enable busses > 1 without enabling bus 0 + * first in some kind of role. */ if (IS_FC(isp) && bus != 0 && (((FCPARAM(isp, 0)->role & ISP_ROLE_TARGET) && nolunsenabled(isp, 0)) || (FCPARAM(isp, 0)->role == ISP_ROLE_NONE))) { isp_prt(isp, ISP_LOGWARN, "%s: must enable Chan 0 before Chan %u", __FUNCTION__, bus); @@ -3770,21 +3771,13 @@ isplinux_get_default_id(ispsoftc_t *isp, int chan) int isplinux_get_default_role(ispsoftc_t *isp, int chan) { - if (IS_FC(isp)) { - return (ISP_DATA(isp, chan)->role); - } else { - return (isp->isp_osinfo.role); - } + return (ISP_DATA(isp, chan)->role); } void isplinux_set_default_role(ispsoftc_t *isp, int chan, int role) { - if (IS_FC(isp)) { - ISP_DATA(isp, chan)->role = role; - } else { - isp->isp_osinfo.role = role; - } + ISP_DATA(isp, chan)->role = role; } /* @@ -3896,14 +3889,16 @@ isplinux_timer(unsigned long arg) ISP_ILOCK_SOFTC(isp); isp->isp_osinfo.dogcnt++; - if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { - isp_intr(isp, isr, sema, mbox); - if (isp->intsok) { - ISP_ENABLE_INTS(isp); - } + if (isp->isp_dead == 0) { + if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) { + isp_intr(isp, isr, sema, mbox); + if (isp->intsok) { + ISP_ENABLE_INTS(isp); + } #ifdef ISP_TARGET_MODE - didintr = 1; + didintr = 1; #endif + } } for (i = 0; i < isp->isp_nchan; i++) { if (ISP_DATA(isp, i)->qfdelay) { @@ -4021,7 +4016,7 @@ isplinux_intr(int irq, void *arg PTARG) * roles=DEVID=role[,...] */ static int -isp_parse_rolearg(ispsoftc_t *isp, char *roles) +isp_parse_rolearg(ispsoftc_t *isp, int chan, char *roles) { char *role = roles; @@ -4190,14 +4185,12 @@ isplinux_common_init(ispsoftc_t *isp) } if (IS_FC(isp)) { - if (IS_2200(isp) || IS_2300(isp)) { - if (isp_nport_only & (1 << isp->isp_unit)) { - isp->isp_confopts |= ISP_CFG_NPORT_ONLY; - } else if (isp_loop_only & (1 << isp->isp_unit)) { - isp->isp_confopts |= ISP_CFG_LPORT_ONLY; - } else { - isp->isp_confopts |= ISP_CFG_NPORT; - } + if (isp_nport_only & (1 << isp->isp_unit)) { + isp->isp_confopts |= ISP_CFG_NPORT_ONLY; + } else if (isp_loop_only & (1 << isp->isp_unit)) { + isp->isp_confopts |= ISP_CFG_LPORT_ONLY; + } else { + isp->isp_confopts |= ISP_CFG_NPORT; } isp->isp_osinfo.host->this_id = MAX_FC_TARG+1; #ifdef ISP_FW_CRASH_DUMP @@ -4228,7 +4221,6 @@ isplinux_common_init(ispsoftc_t *isp) } isp->isp_osinfo.host->max_id = MAX_FC_TARG; isp->isp_osinfo.host->max_cmd_len = 16; - isp->isp_osinfo.role = isp_parse_rolearg(isp, isp_roles); for (chan = 0; chan < isp->isp_nchan; chan++) { isp_data *fc = ISP_DATA(isp, chan); @@ -4247,12 +4239,17 @@ isplinux_common_init(ispsoftc_t *isp) } else { DEFAULT_EXEC_THROTTLE(isp) = ICB_DFLT_THROTTLE; } - fc->role = isp->isp_osinfo.role; + fc->role = isp_parse_rolearg(isp, chan, isp_roles); + SET_DEFAULT_ROLE(isp, chan, fc->role); } } else { isp->isp_osinfo.host->max_id = MAX_TARGETS; isp->isp_osinfo.host->max_cmd_len = 12; isp->isp_osinfo.host->this_id = 7; /* temp default */ + for (chan = 0; chan < isp->isp_nchan; chan++) { + SDPARAM(isp, chan)->role = isp_parse_rolearg(isp, chan, isp_roles); + SET_DEFAULT_ROLE(isp, chan, SDPARAM(isp, chan)->role); + } } if (isp_own_id) { @@ -4342,6 +4339,7 @@ isplinux_reinit(ispsoftc_t *isp) } isp->isp_osinfo.host->max_lun = min(maxluns, ISP_MAX_LUNS(isp)); +#if 0 /* * If we're not taking a role, set some 'defaults' and turn off lasers (for FC cards). */ @@ -4353,6 +4351,12 @@ isplinux_reinit(ispsoftc_t *isp) isp_shutdown(isp); return (0); } +#else + isp->isp_osinfo.host->can_queue = 16; + isp->isp_osinfo.host->can_queue = 1; + isp->isp_osinfo.host->cmd_per_lun = 1; + isp->isp_osinfo.host->this_id = IS_FC(isp)? MAX_FC_TARG : 7; +#endif isp_init(isp); if (isp->isp_state != ISP_INITSTATE) { @@ -4525,23 +4529,25 @@ isp_task_thread(void *arg) break; #endif case ISP_THREAD_REINIT: - { - int level; - ISP_LOCKU_SOFTC(isp); - level = (isp->isp_osinfo.role == ISP_ROLE_NONE)? ISP_RESETSTATE : ISP_INITSTATE; - isp_reinit(isp); - for (i = 0; i < isp->isp_nchan; i++) { - ISP_DATA(isp, i)->blocked = 0; + if (isp->isp_dead) { + isp_prt(isp, ISP_LOGERR, "chip marked dead- not restarting"); + isp_shutdown(isp); + ISP_DISABLE_INTS(isp); + ISP_UNLKU_SOFTC(isp); + break; } - if (isp->isp_state >= level) { + isp_reinit(isp); + if (isp->isp_state == ISP_RUNSTATE) { + for (i = 0; i < isp->isp_nchan; i++) { + ISP_DATA(isp, i)->blocked = 0; + } isp_async(isp, ISPASYNC_FW_RESTARTED); } else { isp_prt(isp, ISP_LOGERR, "unable to restart chip"); } ISP_UNLKU_SOFTC(isp); break; - } case ISP_THREAD_FC_RESCAN: { fcparam *fcp = tap->arg; diff --git a/qla_isp/linux/isp_linux.h b/qla_isp/linux/isp_linux.h index 52a09b44d..61c210e9f 100644 --- a/qla_isp/linux/isp_linux.h +++ b/qla_isp/linux/isp_linux.h @@ -139,20 +139,6 @@ typedef struct scsi_host_template Scsi_Host_Template; #include #endif -/* - * These bits and pieces of keeping track of Linux versions - * and some of the various foo items for locking/unlocking - * gratefully borrowed from (amongst others) Doug Ledford - * and Gerard Roudier. - */ - -#define PWRB(p, o, r) pci_write_config_byte(p->pci_dev, o, r) -#define PWRW(p, o, r) pci_write_config_word(p->pci_dev, o, r) -#define PWRL(p, o, r) pci_write_config_dword(p->pci_dev, o, r) -#define PRDW(p, o, r) pci_read_config_word(p->pci_dev, o, r) -#define PRDD(p, o, r) pci_read_config_dword(p->pci_dev, o, r) -#define PRDB(p, o, r) pci_read_config_byte(p->pci_dev, o, r) - /* * Efficiency- get rid of SBus code && tests unless we need them. */ @@ -744,9 +730,6 @@ extern int api_channel; #ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #endif -#ifndef ARGSUSED -#define ARGSUSED(x) x = x -#endif /* * Platform specific 'inline' or support functions