diff options
author | mjacob <mjacob@cvs.openbsd.org> | 2002-08-17 17:48:46 +0000 |
---|---|---|
committer | mjacob <mjacob@cvs.openbsd.org> | 2002-08-17 17:48:46 +0000 |
commit | faafc8a25ec412082a4da831bdc33acf7fe4048c (patch) | |
tree | e750af0c723d4bd2bbea5a607b0636f511a86fde /sys | |
parent | 608e44c285d44c613a180d187247d4a2f451ca35 (diff) |
If the HBA is already 'touched', still set maxluns.
Don't whine if the name server returns "no such registered type"
when we ask it for all FC-SCSI objects.
Fix a few typos.
If we get a f/w crash, if ISP_FW_CRASH_DUMP is *not* defined, do
the isp_reinit inline, otherwise, let the platform isp_async
drive things. This is because, typically, the platform isp_async
will freeze things and wake up a thread to do the actual f/w
crash dump (really *can't* be done on the interrupt stack- the
23XX has one move on the order of 500KBytes of crash dump data).
Set up to handle default framsize && exec_throttle and iid/loopid
overrides.
If we're using ancient (pre 1.17.0) 2100 f/w (for the cards that cannot
load f/w images > 0x7fff words), set ISP_FW_ATTR_SCCLUN. We explicitly
don't believe we can find attributes if f/w is < 1.17.0, so we have to
set SCCLUN for the 1.15.37 f/w we're using manually- otherwise every
target will replicate itself across all 16 supported luns for non-SCCLUN
f/w.
Correctly set things up for 23XX and either fast posting or ZIO. The
23XX, it turns out, does not support RIO. If you put a non-zero value
in xfwoptions, this will disable fast posting. If you put ICBXOPT_ZIO
in xfwoptions, then the 23XX will do interrupt delays but post to the
response queue- apparently QLogic *now* believes that reading multiple
handles from registers is less of a win than writing (and delaying)
multiple 64 byte responses to the response queue.
At the end of taking a a good f/w crash dump, send the ISPASYNC_FW_DUMPED
event to the outer layers (who can then do things like wake a user
daemon to *fetch* the crash image, etc.).
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/isp.c | 237 |
1 files changed, 161 insertions, 76 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c index 2c7ccd1d4fc..f054db10f14 100644 --- a/sys/dev/ic/isp.c +++ b/sys/dev/ic/isp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: isp.c,v 1.26 2002/05/17 01:31:13 mjacob Exp $ */ +/* $OpenBSD: isp.c,v 1.27 2002/08/17 17:48:45 mjacob Exp $ */ /* * Machine and OS Independent (well, as best as possible) * code for the Qlogic ISP SCSI adapters. @@ -161,7 +161,7 @@ isp_reset(struct ispsoftc *isp) { mbreg_t mbs; u_int16_t code_org; - int loops, i, touched, dodnld = 1; + int loops, i, dodnld = 1; char *btype = "????"; isp->isp_state = ISP_NILSTATE; @@ -184,7 +184,7 @@ isp_reset(struct ispsoftc *isp) * case, we don't really use this yet, but we may in * the future. */ - if ((touched = isp->isp_touched) == 0) { + if (isp->isp_touched == 0) { /* * First see whether or not we're sitting in the ISP PROM. * If we've just been reset, we'll have the string "ISP " @@ -728,11 +728,17 @@ again: if (IS_FC(isp)) { /* * We do not believe firmware attributes for 2100 code less - * than 1.17.0. + * than 1.17.0, unless it's the firmware we specifically + * are loading. + * + * Note that all 22XX and 23XX f/w is greater than 1.X.0. */ - if (IS_2100(isp) && - (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0))) { + if (!(ISP_FW_NEWER_THAN(isp, 1, 17, 0))) { +#ifdef USE_SMALLER_2100_FIRMWARE + FCPARAM(isp)->isp_fwattr = ISP_FW_ATTR_SCCLUN; +#else FCPARAM(isp)->isp_fwattr = 0; +#endif } else { FCPARAM(isp)->isp_fwattr = mbs.param[6]; isp_prt(isp, ISP_LOGDEBUG0, @@ -791,19 +797,21 @@ again: * because we may be called again after firmware has been loaded once * and released. */ - if (touched == 0) { - if (IS_SCSI(isp)) { - if (dodnld) { + if (IS_SCSI(isp)) { + if (dodnld) { + if (IS_ULTRA2(isp) || IS_ULTRA3(isp)) { isp->isp_maxluns = 32; } else { isp->isp_maxluns = 8; } } else { - if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { - isp->isp_maxluns = 16384; - } else { - isp->isp_maxluns = 16; - } + isp->isp_maxluns = 8; + } + } else { + if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { + isp->isp_maxluns = 16384; + } else { + isp->isp_maxluns = 16; } } } @@ -1170,7 +1178,7 @@ isp_fibre_init(struct ispsoftc *isp) * because otherwise port database entries don't get updated after * a LIP- this is a known f/w bug for 2100 f/w less than 1.17.0. */ - if (ISP_FW_REVX(isp->isp_fwrev) < ISP_FW_REV(1, 17, 0)) { + if (!ISP_FW_NEWER_THAN(isp, 1, 17, 0)) { fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; } @@ -1242,9 +1250,17 @@ isp_fibre_init(struct ispsoftc *isp) break; } if (IS_23XX(isp)) { - if (IS_2300(isp) && isp->isp_revision < 2) { - icbp->icb_fwoptions &= ~ICBOPT_FAST_POST; - } + /* + * QLogic recommends that FAST Posting be turned + * off for 23XX cards and instead allow the HBA + * to write response queue entries and interrupt + * after a delay (ZIO). + * + * If we set ZIO, it will disable fast posting, + * so we don't need to clear it in fwoptions. + */ + icbp->icb_xfwoptions |= ICBXOPT_ZIO; + if (isp->isp_confopts & ISP_CFG_ONEGB) { icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB; } else if (isp->isp_confopts & ISP_CFG_TWOGB) { @@ -1263,21 +1279,24 @@ isp_fibre_init(struct ispsoftc *isp) * More specifically, on a 2204 I had problems with RIO * on a Linux system where I was dropping commands right * and left. It's not clear to me what the actual problem - * was, but it seems safer to only support this on the - * 23XX cards. + * was. * - * I have it disabled if we support a target mode role for - * reasons I can't now remember. + * 23XX Cards do not support RIO. Instead they support ZIO. */ - if ((isp->isp_role & ISP_ROLE_TARGET) == 0 && IS_23XX(isp)) { +#if 0 + if (!IS_23XX(isp) && ISP_FW_NEWER_THAN(isp, 1, 17, 0)) { icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT; icbp->icb_racctimer = 4; icbp->icb_idelaytimer = 8; } #endif +#endif - if ((IS_2200(isp) && ISP_FW_REVX(isp->isp_fwrev) >= - ISP_FW_REV(2, 1, 26)) || IS_23XX(isp)) { + /* + * For 22XX > 2.1.26 && 23XX, set someoptions. + * XXX: Probably okay for newer 2100 f/w too. + */ + if (ISP_FW_NEWER_THAN(isp, 2, 26, 0)) { /* * Turn on LIP F8 async event (1) * Turn on generate AE 8013 on all LIP Resets (2) @@ -1324,8 +1343,9 @@ isp_fibre_init(struct ispsoftc *isp) icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma); icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma); icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma); - isp_prt(isp, ISP_LOGDEBUG1, - "isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions); + isp_prt(isp, ISP_LOGDEBUG0, + "isp_fibre_init: fwopt 0x%x xfwopt 0x%x zfwopt 0x%x", + icbp->icb_fwoptions, icbp->icb_xfwoptions, icbp->icb_zfwoptions); FC_SCRATCH_ACQUIRE(isp); isp_put_icb(isp, icbp, (isp_icb_t *)fcp->isp_scratch); @@ -1583,11 +1603,20 @@ isp_fclink_test(struct ispsoftc *isp, int usdelay) */ fcp->isp_onfabric = 0; - if (IS_2100(isp)) - check_for_fabric = 1; - else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) + if (IS_2100(isp)) { + /* + * Don't bother with fabric if we are using really old + * 2100 firmware. It's just not worth it. + */ + if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) { + check_for_fabric = 1; + } else { + check_for_fabric = 0; + } + } else if (fcp->isp_topo == TOPO_FL_PORT || + fcp->isp_topo == TOPO_F_PORT) { check_for_fabric = 1; - else + } else check_for_fabric = 0; if (check_for_fabric && isp_getpdb(isp, FL_PORT_ID, &pdb) == 0) { @@ -2412,7 +2441,13 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) rs0 = (sns_ga_nxt_rsp_t *) ((u_int8_t *)fcp->isp_scratch+0x100); isp_get_ga_nxt_response(isp, rs0, rs1); if (rs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GA_NXT", + int level; + if (rs1->snscb_cthdr.ct_reason == 9 && + rs1->snscb_cthdr.ct_explanation == 7) + level = ISP_LOGDEBUG0; + else + level = ISP_LOGWARN; + isp_prt(isp, level, swrej, "GA_NXT", rs1->snscb_cthdr.ct_reason, rs1->snscb_cthdr.ct_explanation, portid); FC_SCRATCH_RELEASE(isp); @@ -2425,6 +2460,10 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) (((u_int32_t) rs1->snscb_port_id[2])); /* + * XXX: We should check to make sure that this entry + * XXX: supports the type(s) we are interested in. + */ + /* * Okay, we now have information about a fabric object. * If it is the type we're interested in, tell the outer layers * about it. The outer layer needs to know: Port ID, WWNN, @@ -2557,7 +2596,13 @@ isp_scan_fabric(struct ispsoftc *isp, int ftype) rs0 = (sns_gid_ft_rsp_t *) ((u_int8_t *)fcp->isp_scratch+IGPOFF); isp_get_gid_ft_response(isp, rs0, rs1, NGENT); if (rs1->snscb_cthdr.ct_response != FS_ACC) { - isp_prt(isp, ISP_LOGWARN, swrej, "GID_FT", + int level; + if (rs1->snscb_cthdr.ct_reason == 9 && + rs1->snscb_cthdr.ct_explanation == 7) + level = ISP_LOGDEBUG0; + else + level = ISP_LOGWARN; + isp_prt(isp, level, swrej, "GID_FT", rs1->snscb_cthdr.ct_reason, rs1->snscb_cthdr.ct_explanation, 0); FC_SCRATCH_RELEASE(isp); @@ -3024,7 +3069,7 @@ isp_start(XS_T *xs) return (CMD_RQLATER); } if (fcp->isp_fwstate != FW_READY || - fcp->isp_loopstate < LOOP_PDB_RCVD) { + fcp->isp_loopstate < LOOP_FSCAN_DONE) { return (CMD_RQLATER); } } @@ -3200,7 +3245,7 @@ isp_start(XS_T *xs) XS_SETERR(xs, HBA_NOERROR); isp_prt(isp, ISP_LOGDEBUG2, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", - XS_CHANNEL(xs), target, XS_LUN(xs), XS_CDBP(xs)[0], + XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs)); ISP_ADD_REQUEST(isp, nxti); isp->isp_nactive++; @@ -3440,7 +3485,8 @@ again: } else if (isp_parse_async(isp, mbox) < 0) { return; } - if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) { + if ((IS_FC(isp) && mbox != ASYNC_RIO_RESP) || + isp->isp_state != ISP_RUNSTATE) { ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); ISP_WRITE(isp, BIU_SEMA, 0); return; @@ -3666,11 +3712,15 @@ again: * Only whine if this isn't the expected fallout of * aborting the command. */ - if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE || - ts != RQCS_ABORTED) { + if (sp->req_header.rqs_entry_type != RQSTYPE_RESPONSE) { isp_prt(isp, ISP_LOGERR, - "cannot find handle 0x%x in xflist", - sp->req_handle); + "cannot find handle 0x%x (type 0x%x)", + sp->req_handle, + sp->req_header.rqs_entry_type); + } else if (ts != RQCS_ABORTED) { + isp_prt(isp, ISP_LOGERR, + "cannot find handle 0x%x (status 0x%x)", + sp->req_handle, ts); } WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); continue; @@ -3860,8 +3910,20 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) isp_async(isp, ISPASYNC_BUS_RESET, &bus); break; case ASYNC_SYSTEM_ERROR: +#ifdef ISP_FW_CRASH_DUMP + /* + * If we have crash dumps enabled, it's up to the handler + * for isp_async to reinit stuff and restart the firmware + * after performing the crash dump. The reason we do things + * this way is that we may need to activate a kernel thread + * to do all the crash dump goop. + */ isp_async(isp, ISPASYNC_FW_CRASH, NULL); - /* no point continuing after this */ +#else + isp_async(isp, ISPASYNC_FW_CRASH, NULL); + isp_reinit(isp); + isp_async(isp, ISPASYNC_FW_RESTARTED, NULL); +#endif rval = -1; break; @@ -3980,7 +4042,7 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) break; case ASYNC_RIO_RESP: - break; + return (rval); case ASYNC_CTIO_DONE: { @@ -4121,11 +4183,9 @@ isp_parse_async(struct ispsoftc *isp, u_int16_t mbox) break; case ISP_CONN_FATAL: isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR"); + isp_async(isp, ISPASYNC_FW_CRASH, NULL); isp_reinit(isp); -#ifdef ISP_TARGET_MODE - (void) isp_target_async(isp, bus, ASYNC_SYSTEM_ERROR); -#endif - /* no point continuing after this */ + isp_async(isp, ISPASYNC_FW_RESTARTED, NULL); return (-1); case ISP_CONN_LOOPBACK: isp_prt(isp, ISP_LOGWARN, @@ -4323,6 +4383,16 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) case RQCS_TIMEOUT: isp_prt(isp, ISP_LOGWARN, "command timed out for %d.%d.%d", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); + /* + * Check to see if we logged out the device. + */ + if (IS_FC(isp)) { + if ((sp->req_completion_status & RQSTF_LOGOUT) && + FCPARAM(isp)->portdb[XS_TGT(xs)].valid && + FCPARAM(isp)->portdb[XS_TGT(xs)].fabric_dev) { + FCPARAM(isp)->portdb[XS_TGT(xs)].relogin = 1; + } + } if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_CMDTIMEOUT); } @@ -5468,6 +5538,13 @@ isp_update_bus(struct ispsoftc *isp, int bus) } } +#ifndef DEFAULT_FRAMESIZE +#define DEFAULT_FRAMESIZE(isp) ICB_DFLT_FRMLEN +#endif +#ifndef DEFAULT_EXEC_THROTTLE +#define DEFAULT_EXEC_THROTTLE(isp) ISP_EXEC_THROTTLE +#endif + static void isp_setdfltparm(struct ispsoftc *isp, int channel) { @@ -5484,9 +5561,9 @@ isp_setdfltparm(struct ispsoftc *isp, int channel) return; } fcp->isp_gotdparms = 1; - fcp->isp_maxfrmlen = ICB_DFLT_FRMLEN; + fcp->isp_maxfrmlen = DEFAULT_FRAMESIZE(isp); fcp->isp_maxalloc = ICB_DFLT_ALLOC; - fcp->isp_execthrottle = ISP_EXEC_THROTTLE; + fcp->isp_execthrottle = DEFAULT_EXEC_THROTTLE(isp); fcp->isp_retry_delay = ICB_DFLT_RDELAY; fcp->isp_retry_count = ICB_DFLT_RCOUNT; /* Platform specific.... */ @@ -5703,19 +5780,16 @@ isp_reinit(struct ispsoftc *isp) isp_reset(isp); if (isp->isp_state != ISP_RESETSTATE) { isp_prt(isp, ISP_LOGERR, "isp_reinit cannot reset card"); - goto skip; - } - isp_init(isp); - if (isp->isp_role == ISP_ROLE_NONE) { - goto skip; - } - if (isp->isp_state == ISP_INITSTATE) { - isp->isp_state = ISP_RUNSTATE; - } - if (isp->isp_state != ISP_RUNSTATE) { - isp_prt(isp, ISP_LOGERR, "isp_reinit cannot restart card"); + } else if (isp->isp_role != ISP_ROLE_NONE) { + isp_init(isp); + if (isp->isp_state == ISP_INITSTATE) { + isp->isp_state = ISP_RUNSTATE; + } + if (isp->isp_state != ISP_RUNSTATE) { + isp_prt(isp, ISP_LOGERR, + "isp_reinit cannot restart card"); + } } -skip: isp->isp_nactive = 0; for (handle = 1; (int) handle <= isp->isp_maxcmds; handle++) { @@ -5887,8 +5961,9 @@ isp_parse_nvram_1020(struct ispsoftc *isp, u_int8_t *nvram_data) ISP_NVRAM_FIFO_THRESHOLD(nvram_data) | (ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2); - sdp->isp_initiator_id = - ISP_NVRAM_INITIATOR_ID(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) + sdp->isp_initiator_id = + ISP_NVRAM_INITIATOR_ID(nvram_data); sdp->isp_bus_reset_delay = ISP_NVRAM_BUS_RESET_DELAY(nvram_data); @@ -6013,8 +6088,9 @@ isp_parse_nvram_1080(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) sdp->isp_fifo_threshold = ISP1080_NVRAM_FIFO_THRESHOLD(nvram_data); - sdp->isp_initiator_id = - ISP1080_NVRAM_INITIATOR_ID(nvram_data, bus); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) + sdp->isp_initiator_id = + ISP1080_NVRAM_INITIATOR_ID(nvram_data, bus); sdp->isp_bus_reset_delay = ISP1080_NVRAM_BUS_RESET_DELAY(nvram_data, bus); @@ -6104,8 +6180,9 @@ isp_parse_nvram_12160(struct ispsoftc *isp, int bus, u_int8_t *nvram_data) sdp->isp_fifo_threshold = ISP12160_NVRAM_FIFO_THRESHOLD(nvram_data); - sdp->isp_initiator_id = - ISP12160_NVRAM_INITIATOR_ID(nvram_data, bus); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) + sdp->isp_initiator_id = + ISP12160_NVRAM_INITIATOR_ID(nvram_data, bus); sdp->isp_bus_reset_delay = ISP12160_NVRAM_BUS_RESET_DELAY(nvram_data, bus); @@ -6250,23 +6327,29 @@ isp_parse_nvram_2100(struct ispsoftc *isp, u_int8_t *nvram_data) } } + isp_prt(isp, ISP_LOGDEBUG0, + "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x", + ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data), + ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data), + ISP2100_NVRAM_OPTIONS(nvram_data), + ISP2100_NVRAM_HARDLOOPID(nvram_data)); + fcp->isp_maxalloc = ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); - fcp->isp_maxfrmlen = - ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNFSZ) == 0) + fcp->isp_maxfrmlen = + ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data); fcp->isp_retry_delay = ISP2100_NVRAM_RETRY_DELAY(nvram_data); fcp->isp_retry_count = ISP2100_NVRAM_RETRY_COUNT(nvram_data); - fcp->isp_loopid = - ISP2100_NVRAM_HARDLOOPID(nvram_data); - fcp->isp_execthrottle = - ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNLOOPID) == 0) + fcp->isp_loopid = + ISP2100_NVRAM_HARDLOOPID(nvram_data); + if ((isp->isp_confopts & ISP_CFG_OWNEXCTHROTTLE) == 0) + fcp->isp_execthrottle = + ISP2100_NVRAM_EXECUTION_THROTTLE(nvram_data); fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data); - isp_prt(isp, ISP_LOGDEBUG0, - "NVRAM: maxfrmlen %d execthrottle %d fwoptions 0x%x loopid %x", - fcp->isp_maxfrmlen, fcp->isp_execthrottle, fcp->isp_fwoptions, - fcp->isp_loopid); } #ifdef ISP_FW_CRASH_DUMP @@ -6414,6 +6497,7 @@ isp2200_fw_dump(struct ispsoftc *isp) *ptr++ = isp->isp_mboxtmp[2]; isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped succesfully"); FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */ + (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0); } static void @@ -6576,6 +6660,7 @@ isp2300_fw_dump(struct ispsoftc *isp) *ptr++ = mbs.param[2]; isp_prt(isp, ISP_LOGALL, "isp_fw_dump: SRAM dumped succesfully"); FCPARAM(isp)->isp_dump_data[0] = isp->isp_type; /* now used */ + (void) isp_async(isp, ISPASYNC_FW_DUMPED, 0); } void |