From ccea943059f8c59175d6a86b9d1b6b4163b7efa4 Mon Sep 17 00:00:00 2001 From: mjacob Date: Wed, 1 May 2002 21:58:36 +0000 Subject: 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 --- sys/dev/isp/isp.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 2070df7..6bdacd8 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -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: */ -- cgit v1.1