diff options
author | mjacob <mjacob@FreeBSD.org> | 2002-02-21 01:56:08 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2002-02-21 01:56:08 +0000 |
commit | d4fb4b6c57e2fe3fc6ff6d3bfc8f3b97d3501b89 (patch) | |
tree | b38a3e6d077bd845fbb6aeee0a6babb40d1387d5 /sys | |
parent | cf06489c2d4eab716cf9a022f801ae33d4a2a1ba (diff) | |
download | FreeBSD-src-d4fb4b6c57e2fe3fc6ff6d3bfc8f3b97d3501b89.zip FreeBSD-src-d4fb4b6c57e2fe3fc6ff6d3bfc8f3b97d3501b89.tar.gz |
Fix a problem where a local loop disk logs out- and we get a PORT LOGGED
OUT status. We are, apparently, required to force the f/w to log back in
if we want to try and talk to that disk again. This means either issuing
a LOGIN LOCAL LOOP PORT mailbox command, or by issuing a LIP. I've elected
to issue a LIP because this has a better chance of waking up the disk which
clearly just crashed and burned.
These should not occur at all. If they do, they should be darned rare.
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/isp/isp.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 6e10691..8f0ddaa 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -130,7 +130,7 @@ static int isp_scan_loop(struct ispsoftc *); static int isp_scan_fabric(struct ispsoftc *); static void isp_register_fc4_type(struct ispsoftc *); static void isp_fw_state(struct ispsoftc *); -static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *); +static void isp_mboxcmd_qnw(struct ispsoftc *, mbreg_t *, int); static void isp_mboxcmd(struct ispsoftc *, mbreg_t *, int); static void isp_update(struct ispsoftc *); @@ -1140,7 +1140,7 @@ isp_fibre_init(struct ispsoftc *isp) return; } - loopid = DEFAULT_LOOPID(isp); + loopid = fcp->isp_loopid; MEMZERO(icbp, sizeof (*icbp)); icbp->icb_version = ICB_VERSION1; @@ -4108,6 +4108,24 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs) */ isp_prt(isp, ISP_LOGINFO, "port logout for target %d", XS_TGT(xs)); + /* + * If we're on a local loop, force a LIP (which is overkill) + * to force a re-login of this unit. + */ + if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT || + FCPARAM(isp)->isp_topo == TOPO_FL_PORT) { + mbreg_t mbs; + mbs.param[0] = MBOX_INIT_LIP; + isp_mboxcmd_qnw(isp, &mbs, 1); + } + + /* + * Probably overkill. + */ + isp->isp_sendmarker = 1; + FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD; + isp_mark_getpdb_all(isp); + isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER); if (XS_NOERR(xs)) { XS_SETERR(xs, HBA_SELTIMEOUT); } @@ -4216,7 +4234,7 @@ isp_mbox_continue(struct ispsoftc *isp) isp->isp_mbxworkp = ptr; mbs.param[0] = isp->isp_lastmbxcmd; isp->isp_mbxwrk0 -= 1; - isp_mboxcmd_qnw(isp, &mbs); + isp_mboxcmd_qnw(isp, &mbs, 0); return (0); } @@ -4690,7 +4708,7 @@ static char *fc_mbcmd_names[] = { #endif static void -isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp) +isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp, int nodelay) { unsigned int lim, ibits, obits, box, opcode; u_int16_t *mcp; @@ -4709,12 +4727,24 @@ isp_mboxcmd_qnw(struct ispsoftc *isp, mbreg_t *mbp) if (ibits & (1 << box)) { ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } - isp->isp_mboxtmp[box] = mbp->param[box] = 0; + if (nodelay == 0) { + isp->isp_mboxtmp[box] = mbp->param[box] = 0; + } + } + if (nodelay == 0) { + isp->isp_lastmbxcmd = opcode; + isp->isp_obits = obits; + isp->isp_mboxbsy = 1; } - isp->isp_lastmbxcmd = opcode; - isp->isp_obits = obits; - isp->isp_mboxbsy = 1; ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); + /* + * Oddly enough, if we're not delaying for an answer, + * delay a bit to give the f/w a chance to pick up the + * command. + */ + if (nodelay) { + USEC_DELAY(1000); + } } static void |