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:
parent
47a45d1b17
commit
f77e6d9569
@ -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: */
|
||||
|
Loading…
Reference in New Issue
Block a user