summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2002-02-21 01:56:08 +0000
committermjacob <mjacob@FreeBSD.org>2002-02-21 01:56:08 +0000
commitd4fb4b6c57e2fe3fc6ff6d3bfc8f3b97d3501b89 (patch)
treeb38a3e6d077bd845fbb6aeee0a6babb40d1387d5 /sys
parentcf06489c2d4eab716cf9a022f801ae33d4a2a1ba (diff)
downloadFreeBSD-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.c46
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
OpenPOWER on IntegriCloud