If we get a DATA UNDERRUN error from QLogic FC cards, but the RQCS_RU bit

is not set in the scsi completion status, or if the residual is clearly
nonsense, then this was a command that suffered the loss of one or more
FC frames in the middle of the exchange.

Set HBA_BOTCH and hope it will get retried. It's the only thing we can do.

MFC after:	1 day
This commit is contained in:
Matt Jacob 2002-05-01 21:58:36 +00:00
parent 47a45d1b17
commit f77e6d9569

View File

@ -107,6 +107,8 @@ static const char sc1[] =
static const char sc2[] = "%s CHAN %d TGT %d FLAGS 0x%x 0x%x/0x%x";
static const char sc3[] = "Generated";
static const char sc4[] = "NVRAM";
static const char bun[] =
"bad underrun for %d.%d (count %d, resid %d, status %s)";
/*
* Local function prototypes.
@ -4397,11 +4399,25 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
break;
case RQCS_DATA_UNDERRUN:
{
if (IS_FC(isp)) {
int ru_marked = (sp->req_scsi_status & RQCS_RU) != 0;
if (!ru_marked || sp->req_resid > XS_XFRLEN(xs)) {
isp_prt(isp, ISP_LOGWARN, bun, XS_TGT(xs),
XS_LUN(xs), XS_XFRLEN(xs), sp->req_resid,
(ru_marked)? "marked" : "not marked");
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_BOTCH);
}
return;
}
}
XS_RESID(xs) = sp->req_resid;
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_NOERROR);
}
return;
}
case RQCS_XACT_ERR1:
isp_prt(isp, ISP_LOGERR, xact1, XS_CHANNEL(xs),
@ -4424,8 +4440,8 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
case RQCS_QUEUE_FULL:
isp_prt(isp, ISP_LOGDEBUG0,
"internal queues full for %d.%d.%d status 0x%x", XS_TGT(xs),
XS_LUN(xs), XS_CHANNEL(xs), *XS_STSP(xs));
"internal queues full for %d.%d.%d status 0x%x",
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), *XS_STSP(xs));
/*
* If QFULL or some other status byte is set, then this
@ -4507,13 +4523,14 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
*/
if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
isp_prt(isp, ISP_LOGINFO,
"Port Unavailable for target %d", XS_TGT(xs));
"port unavailable for target %d", XS_TGT(xs));
else
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.
* to force a re-login of this unit. If we're on fabric,
* then we'll have to relogin as a matter of course.
*/
if (FCPARAM(isp)->isp_topo == TOPO_NL_PORT ||
FCPARAM(isp)->isp_topo == TOPO_FL_PORT) {
@ -4933,8 +4950,8 @@ static u_int16_t mbpfc[] = {
ISPOPMAP(0x00, 0x00), /* 0x58: */
ISPOPMAP(0x00, 0x00), /* 0x59: */
ISPOPMAP(0x00, 0x00), /* 0x5a: */
ISPOPMAP(0x00, 0x00), /* 0x5b: */
ISPOPMAP(0x00, 0x00), /* 0x5c: */
ISPOPMAP(0x03, 0x01), /* 0x5b: MBOX_DRIVER_HEARTBEAT */
ISPOPMAP(0xcf, 0x01), /* 0x5c: MBOX_FW_HEARTBEAT */
ISPOPMAP(0x07, 0x03), /* 0x5d: MBOX_GET_SET_DATA_RATE */
ISPOPMAP(0x00, 0x00), /* 0x5e: */
ISPOPMAP(0x00, 0x00), /* 0x5f: */