Cleanup response queue processing.
MFC after: 2 weeks
This commit is contained in:
parent
ae2373da91
commit
2d24b6af63
@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$");
|
||||
/*
|
||||
* Local static data
|
||||
*/
|
||||
static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
|
||||
static const char notresp[] = "Unknown IOCB in RESPONSE Queue (type 0x%x) @ idx %d (next %d)";
|
||||
static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
|
||||
static const char lipd[] = "Chan %d LIP destroyed %d active commands";
|
||||
static const char sacq[] = "unable to acquire scratch area";
|
||||
@ -98,8 +98,8 @@ static const uint8_t alpa_map[] = {
|
||||
static void isp_parse_async(ispsoftc_t *, uint16_t);
|
||||
static void isp_parse_async_fc(ispsoftc_t *, uint16_t);
|
||||
static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *);
|
||||
static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, long *);
|
||||
static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, long *);
|
||||
static void isp_parse_status(ispsoftc_t *, ispstatusreq_t *, XS_T *, uint32_t *);
|
||||
static void isp_parse_status_24xx(ispsoftc_t *, isp24xx_statusreq_t *, XS_T *, uint32_t *);
|
||||
static void isp_fastpost_complete(ispsoftc_t *, uint32_t);
|
||||
static void isp_scsi_init(ispsoftc_t *);
|
||||
static void isp_scsi_channel_init(ispsoftc_t *, int);
|
||||
@ -4970,21 +4970,18 @@ isp_intr_mbox(ispsoftc_t *isp, uint16_t mbox0)
|
||||
MBOX_NOTIFY_COMPLETE(isp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit our stack depth by sticking with the max likely number
|
||||
* of completions on a request queue at any one time.
|
||||
*/
|
||||
#ifndef MAX_REQUESTQ_COMPLETIONS
|
||||
#define MAX_REQUESTQ_COMPLETIONS 32
|
||||
#endif
|
||||
|
||||
void
|
||||
isp_intr_respq(ispsoftc_t *isp)
|
||||
{
|
||||
XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
|
||||
uint32_t iptr, optr, junk;
|
||||
int i, nlooked = 0, ndone = 0, continuations_expected = 0;
|
||||
int etype, last_etype = 0;
|
||||
XS_T *xs, *cont_xs;
|
||||
uint8_t qe[QENTRY_LEN];
|
||||
ispstatusreq_t *sp = (ispstatusreq_t *)qe;
|
||||
isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe;
|
||||
isphdr_t *hp;
|
||||
uint8_t *resp, *snsp;
|
||||
int buddaboom, completion_status, cont = 0, etype, i;
|
||||
int req_status_flags, req_state_flags, scsi_status;
|
||||
uint32_t iptr, junk, cptr, optr, rlen, slen, sptr, totslen, resid;
|
||||
|
||||
/*
|
||||
* We can't be getting this now.
|
||||
@ -5006,38 +5003,30 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
|
||||
optr = isp->isp_resodx;
|
||||
while (optr != iptr) {
|
||||
uint8_t qe[QENTRY_LEN];
|
||||
ispstatusreq_t *sp = (ispstatusreq_t *) qe;
|
||||
isphdr_t *hp;
|
||||
int buddaboom, scsi_status, completion_status;
|
||||
int req_status_flags, req_state_flags;
|
||||
uint8_t *snsp, *resp;
|
||||
uint32_t rlen, slen, totslen;
|
||||
long resid;
|
||||
uint16_t oop;
|
||||
|
||||
hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, optr);
|
||||
oop = optr;
|
||||
sptr = cptr = optr;
|
||||
hp = (isphdr_t *) ISP_QUEUE_ENTRY(isp->isp_result, cptr);
|
||||
optr = ISP_NXT_QENTRY(optr, RESULT_QUEUE_LEN(isp));
|
||||
nlooked++;
|
||||
read_again:
|
||||
buddaboom = req_status_flags = req_state_flags = 0;
|
||||
resid = 0L;
|
||||
|
||||
/*
|
||||
* Synchronize our view of this response queue entry.
|
||||
*/
|
||||
MEMORYBARRIER(isp, SYNC_RESULT, oop, QENTRY_LEN, -1);
|
||||
MEMORYBARRIER(isp, SYNC_RESULT, cptr, QENTRY_LEN, -1);
|
||||
if (isp->isp_dblev & ISP_LOGDEBUG1)
|
||||
isp_print_qentry(isp, "Response Queue Entry", oop, hp);
|
||||
isp_print_qentry(isp, "Response Queue Entry", cptr, hp);
|
||||
isp_get_hdr(isp, hp, &sp->req_header);
|
||||
etype = sp->req_header.rqs_entry_type;
|
||||
|
||||
/* We expected Status Continuation, but got different IOCB. */
|
||||
if (cont > 0 && etype != RQSTYPE_STATUS_CONT) {
|
||||
cont = 0;
|
||||
isp_done(cont_xs);
|
||||
}
|
||||
|
||||
if (IS_24XX(isp) && etype == RQSTYPE_RESPONSE) {
|
||||
isp24xx_statusreq_t *sp2 = (isp24xx_statusreq_t *)qe;
|
||||
isp_get_24xx_response(isp, (isp24xx_statusreq_t *)hp, sp2);
|
||||
scsi_status = sp2->req_scsi_status;
|
||||
completion_status = sp2->req_completion_status;
|
||||
req_status_flags = 0;
|
||||
if ((scsi_status & 0xff) != 0)
|
||||
req_state_flags = RQSF_GOT_STATUS;
|
||||
else
|
||||
@ -5057,79 +5046,52 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
isp_fastpost_complete(isp, rio->req_handles[i]);
|
||||
}
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
continue;
|
||||
} else if (etype == RQSTYPE_RIO2) {
|
||||
isp_prt(isp, ISP_LOGERR, "dropping RIO2 response");
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
continue;
|
||||
} else if (etype == RQSTYPE_STATUS_CONT) {
|
||||
isp_get_cont_response(isp, (ispstatus_cont_t *) hp, (ispstatus_cont_t *) sp);
|
||||
if (last_etype == RQSTYPE_RESPONSE && continuations_expected && ndone > 0 && (xs = complist[ndone-1]) != NULL) {
|
||||
ispstatus_cont_t *scp = (ispstatus_cont_t *) sp;
|
||||
XS_SENSE_APPEND(xs, scp->req_sense_data, sizeof (scp->req_sense_data));
|
||||
isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, "%d more Status Continuations expected", --continuations_expected);
|
||||
ispstatus_cont_t *scp = (ispstatus_cont_t *)qe;
|
||||
isp_get_cont_response(isp, (ispstatus_cont_t *)hp, scp);
|
||||
if (cont > 0) {
|
||||
i = min(cont, sizeof(scp->req_sense_data));
|
||||
XS_SENSE_APPEND(cont_xs, scp->req_sense_data, i);
|
||||
cont -= i;
|
||||
if (cont == 0) {
|
||||
isp_done(cont_xs);
|
||||
} else {
|
||||
isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
|
||||
"Expecting Status Continuations for %u bytes",
|
||||
cont);
|
||||
}
|
||||
} else {
|
||||
isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
|
||||
}
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
continue;
|
||||
} else if (isp_handle_other_response(isp, etype, hp, &cptr)) {
|
||||
/* More then one IOCB could be consumed. */
|
||||
while (sptr != cptr) {
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
sptr = ISP_NXT_QENTRY(sptr, RESULT_QUEUE_LEN(isp));
|
||||
hp = (isphdr_t *)ISP_QUEUE_ENTRY(isp->isp_result, sptr);
|
||||
}
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
optr = ISP_NXT_QENTRY(cptr, RESULT_QUEUE_LEN(isp));
|
||||
continue;
|
||||
} else {
|
||||
/*
|
||||
* Somebody reachable via isp_handle_other_response
|
||||
* may have updated the response queue pointers for
|
||||
* us, so we reload our goal index.
|
||||
*/
|
||||
int r;
|
||||
uint32_t tsto = oop;
|
||||
r = isp_handle_other_response(isp, etype, hp, &tsto);
|
||||
if (r < 0) {
|
||||
goto read_again;
|
||||
}
|
||||
/*
|
||||
* If somebody updated the output pointer, then reset
|
||||
* optr to be one more than the updated amount.
|
||||
*/
|
||||
while (tsto != oop) {
|
||||
optr = ISP_NXT_QENTRY(tsto, RESULT_QUEUE_LEN(isp));
|
||||
}
|
||||
if (r > 0) {
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* After this point, we'll just look at the header as
|
||||
* we don't know how to deal with the rest of the
|
||||
* response.
|
||||
*/
|
||||
|
||||
/*
|
||||
* It really has to be a bounced request just copied
|
||||
* from the request queue to the response queue. If
|
||||
* not, something bad has happened.
|
||||
*/
|
||||
if (etype != RQSTYPE_REQUEST) {
|
||||
isp_prt(isp, ISP_LOGERR, notresp, etype, oop, optr, nlooked);
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
continue;
|
||||
}
|
||||
buddaboom = 1;
|
||||
scsi_status = sp->req_scsi_status;
|
||||
completion_status = sp->req_completion_status;
|
||||
req_status_flags = sp->req_status_flags;
|
||||
req_state_flags = sp->req_state_flags;
|
||||
resid = sp->req_resid;
|
||||
/* We don't know what was this -- log and skip. */
|
||||
isp_prt(isp, ISP_LOGERR, notresp, etype, cptr, optr);
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
continue;
|
||||
}
|
||||
|
||||
buddaboom = 0;
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_MASK) {
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
|
||||
isp_print_qentry(isp, "unexpected continuation segment",
|
||||
oop, hp);
|
||||
last_etype = etype;
|
||||
cptr, hp);
|
||||
continue;
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
|
||||
@ -5140,23 +5102,22 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_BADHEADER) {
|
||||
isp_print_qentry(isp, "bad header flag",
|
||||
oop, hp);
|
||||
cptr, hp);
|
||||
buddaboom++;
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_BADPACKET) {
|
||||
isp_print_qentry(isp, "bad request packet",
|
||||
oop, hp);
|
||||
cptr, hp);
|
||||
buddaboom++;
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_BADCOUNT) {
|
||||
isp_print_qentry(isp, "invalid entry count",
|
||||
oop, hp);
|
||||
cptr, hp);
|
||||
buddaboom++;
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_BADORDER) {
|
||||
isp_print_qentry(isp, "invalid IOCB ordering",
|
||||
oop, hp);
|
||||
last_etype = etype;
|
||||
cptr, hp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -5174,7 +5135,6 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", sp->req_handle, ts);
|
||||
}
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
continue;
|
||||
}
|
||||
if (req_status_flags & RQSTF_BUS_RESET) {
|
||||
@ -5189,13 +5149,11 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
|
||||
resp = NULL;
|
||||
rlen = 0;
|
||||
snsp = NULL;
|
||||
totslen = slen = 0;
|
||||
resp = snsp = NULL;
|
||||
rlen = slen = totslen = 0;
|
||||
if (IS_24XX(isp) && (scsi_status & (RQCS_RV|RQCS_SV)) != 0) {
|
||||
resp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
|
||||
rlen = ((isp24xx_statusreq_t *)sp)->req_response_len;
|
||||
resp = sp2->req_rsp_sense;
|
||||
rlen = sp2->req_response_len;
|
||||
} else if (IS_FC(isp) && (scsi_status & RQCS_RV) != 0) {
|
||||
resp = sp->req_response;
|
||||
rlen = sp->req_response_len;
|
||||
@ -5208,204 +5166,116 @@ isp_intr_respq(ispsoftc_t *isp)
|
||||
*/
|
||||
req_state_flags |= RQSF_GOT_STATUS|RQSF_GOT_SENSE;
|
||||
if (IS_24XX(isp)) {
|
||||
snsp = ((isp24xx_statusreq_t *)sp)->req_rsp_sense;
|
||||
snsp = sp2->req_rsp_sense;
|
||||
snsp += rlen;
|
||||
totslen = ((isp24xx_statusreq_t *)sp)->req_sense_len;
|
||||
slen = (sizeof (((isp24xx_statusreq_t *)sp)->req_rsp_sense)) - rlen;
|
||||
if (totslen < slen)
|
||||
slen = totslen;
|
||||
totslen = sp2->req_sense_len;
|
||||
slen = sizeof(sp2->req_rsp_sense) - rlen;
|
||||
} else {
|
||||
snsp = sp->req_sense_data;
|
||||
totslen = sp->req_sense_len;
|
||||
slen = sizeof (sp->req_sense_data);
|
||||
if (totslen < slen)
|
||||
slen = totslen;
|
||||
slen = sizeof(sp->req_sense_data);
|
||||
}
|
||||
} else if (IS_SCSI(isp) && (req_state_flags & RQSF_GOT_SENSE)) {
|
||||
snsp = sp->req_sense_data;
|
||||
totslen = sp->req_sense_len;
|
||||
slen = sizeof (sp->req_sense_data);
|
||||
if (totslen < slen)
|
||||
slen = totslen;
|
||||
}
|
||||
if (req_state_flags & RQSF_GOT_STATUS) {
|
||||
if (slen > totslen)
|
||||
slen = totslen;
|
||||
if (req_state_flags & RQSF_GOT_STATUS)
|
||||
*XS_STSP(xs) = scsi_status & 0xff;
|
||||
}
|
||||
|
||||
switch (etype) {
|
||||
case RQSTYPE_RESPONSE:
|
||||
if (resp && rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
|
||||
const char *ptr;
|
||||
char lb[64];
|
||||
const char *rnames[10] = {
|
||||
"Task Management function complete",
|
||||
"FCP_DATA length different than FCP_BURST_LEN",
|
||||
"FCP_CMND fields invalid",
|
||||
"FCP_DATA parameter mismatch with FCP_DATA_RO",
|
||||
"Task Management function rejected",
|
||||
"Task Management function failed",
|
||||
NULL,
|
||||
NULL,
|
||||
"Task Management function succeeded",
|
||||
"Task Management function incorrect logical unit number",
|
||||
};
|
||||
uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
|
||||
if (code >= 10 || rnames[code] == NULL) {
|
||||
ISP_SNPRINTF(lb, sizeof(lb),
|
||||
"Unknown FCP Response Code 0x%x",
|
||||
code);
|
||||
ptr = lb;
|
||||
} else {
|
||||
ptr = rnames[code];
|
||||
}
|
||||
isp_xs_prt(isp, xs, ISP_LOGWARN,
|
||||
"FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
|
||||
rlen, ptr, XS_CDBP(xs)[0] & 0xff);
|
||||
if (code != 0 && code != 8)
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
if (IS_24XX(isp)) {
|
||||
isp_parse_status_24xx(isp, (isp24xx_statusreq_t *)sp, xs, &resid);
|
||||
if (rlen >= 4 && resp[FCP_RSPNS_CODE_OFFSET] != 0) {
|
||||
const char *ptr;
|
||||
char lb[64];
|
||||
const char *rnames[10] = {
|
||||
"Task Management function complete",
|
||||
"FCP_DATA length different than FCP_BURST_LEN",
|
||||
"FCP_CMND fields invalid",
|
||||
"FCP_DATA parameter mismatch with FCP_DATA_RO",
|
||||
"Task Management function rejected",
|
||||
"Task Management function failed",
|
||||
NULL,
|
||||
NULL,
|
||||
"Task Management function succeeded",
|
||||
"Task Management function incorrect logical unit number",
|
||||
};
|
||||
uint8_t code = resp[FCP_RSPNS_CODE_OFFSET];
|
||||
if (code >= 10 || rnames[code] == NULL) {
|
||||
ISP_SNPRINTF(lb, sizeof(lb),
|
||||
"Unknown FCP Response Code 0x%x", code);
|
||||
ptr = lb;
|
||||
} else {
|
||||
isp_parse_status(isp, (void *)sp, xs, &resid);
|
||||
ptr = rnames[code];
|
||||
}
|
||||
if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) && (*XS_STSP(xs) == SCSI_BUSY)) {
|
||||
XS_SETERR(xs, HBA_TGTBSY);
|
||||
isp_xs_prt(isp, xs, ISP_LOGWARN,
|
||||
"FCP RESPONSE, LENGTH %u: %s CDB0=0x%02x",
|
||||
rlen, ptr, XS_CDBP(xs)[0] & 0xff);
|
||||
if (code != 0 && code != 8)
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
if (IS_24XX(isp))
|
||||
isp_parse_status_24xx(isp, sp2, xs, &resid);
|
||||
else
|
||||
isp_parse_status(isp, sp, xs, &resid);
|
||||
if ((XS_NOERR(xs) || XS_ERR(xs) == HBA_NOERROR) &&
|
||||
(*XS_STSP(xs) == SCSI_BUSY))
|
||||
XS_SETERR(xs, HBA_TGTBSY);
|
||||
if (IS_SCSI(isp)) {
|
||||
XS_SET_RESID(xs, resid);
|
||||
/*
|
||||
* A new synchronous rate was negotiated for
|
||||
* this target. Mark state such that we'll go
|
||||
* look up that which has changed later.
|
||||
*/
|
||||
if (req_status_flags & RQSTF_NEGOTIATION) {
|
||||
int t = XS_TGT(xs);
|
||||
sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
|
||||
sdp->isp_devparam[t].dev_refresh = 1;
|
||||
sdp->update = 1;
|
||||
}
|
||||
if (IS_SCSI(isp)) {
|
||||
} else {
|
||||
if (req_status_flags & RQSF_XFER_COMPLETE) {
|
||||
XS_SET_RESID(xs, 0);
|
||||
} else if (scsi_status & RQCS_RESID) {
|
||||
XS_SET_RESID(xs, resid);
|
||||
/*
|
||||
* A new synchronous rate was negotiated for
|
||||
* this target. Mark state such that we'll go
|
||||
* look up that which has changed later.
|
||||
*/
|
||||
if (req_status_flags & RQSTF_NEGOTIATION) {
|
||||
int t = XS_TGT(xs);
|
||||
sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
|
||||
sdp->isp_devparam[t].dev_refresh = 1;
|
||||
sdp->update = 1;
|
||||
}
|
||||
} else {
|
||||
if (req_status_flags & RQSF_XFER_COMPLETE) {
|
||||
XS_SET_RESID(xs, 0);
|
||||
} else if (scsi_status & RQCS_RESID) {
|
||||
XS_SET_RESID(xs, resid);
|
||||
} else {
|
||||
XS_SET_RESID(xs, 0);
|
||||
}
|
||||
XS_SET_RESID(xs, 0);
|
||||
}
|
||||
if (snsp && slen) {
|
||||
if (totslen > slen) {
|
||||
continuations_expected += ((totslen - slen + QENTRY_LEN - 5) / (QENTRY_LEN - 4));
|
||||
if (ndone > (MAX_REQUESTQ_COMPLETIONS - continuations_expected - 1)) {
|
||||
/* we'll lose some stats, but that's a small price to pay */
|
||||
for (i = 0; i < ndone; i++) {
|
||||
if (complist[i])
|
||||
isp_done(complist[i]);
|
||||
}
|
||||
ndone = 0;
|
||||
}
|
||||
isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN, "Expecting %d more Status Continuations for total sense length of %u",
|
||||
continuations_expected, totslen);
|
||||
}
|
||||
XS_SAVE_SENSE(xs, snsp, totslen, slen);
|
||||
} else if ((req_status_flags & RQSF_GOT_STATUS) && (scsi_status & 0xff) == SCSI_CHECK && IS_FC(isp)) {
|
||||
isp_prt(isp, ISP_LOGWARN, "CHECK CONDITION w/o sense data for CDB=0x%x", XS_CDBP(xs)[0] & 0xff);
|
||||
isp_print_qentry(isp, "CC with no Sense",
|
||||
oop, hp);
|
||||
}
|
||||
isp_prt(isp, ISP_LOGDEBUG2, "asked for %ld got raw resid %ld settled for %ld", (long) XS_XFRLEN(xs), resid, (long) XS_GET_RESID(xs));
|
||||
break;
|
||||
case RQSTYPE_REQUEST:
|
||||
case RQSTYPE_A64:
|
||||
case RQSTYPE_T2RQS:
|
||||
case RQSTYPE_T3RQS:
|
||||
case RQSTYPE_T7RQS:
|
||||
if (!IS_24XX(isp) && (sp->req_header.rqs_flags & RQSFLAG_FULL)) {
|
||||
/*
|
||||
* Force Queue Full status.
|
||||
*/
|
||||
*XS_STSP(xs) = SCSI_QFULL;
|
||||
XS_SETERR(xs, HBA_NOERROR);
|
||||
} else if (XS_NOERR(xs)) {
|
||||
isp_prt(isp, ISP_LOG_WARN1,
|
||||
"%d.%d.%jx badness at %s:%u",
|
||||
XS_CHANNEL(xs), XS_TGT(xs),
|
||||
(uintmax_t)XS_LUN(xs),
|
||||
__func__, __LINE__);
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
XS_SET_RESID(xs, XS_XFRLEN(xs));
|
||||
break;
|
||||
default:
|
||||
isp_print_qentry(isp, "Unhandled Response Type",
|
||||
oop, hp);
|
||||
if (XS_NOERR(xs)) {
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (slen > 0) {
|
||||
XS_SAVE_SENSE(xs, snsp, slen);
|
||||
if (totslen > slen) {
|
||||
cont = totslen - slen;
|
||||
cont_xs = xs;
|
||||
isp_prt(isp, ISP_LOGDEBUG0|ISP_LOG_CWARN,
|
||||
"Expecting Status Continuations for %u bytes",
|
||||
cont);
|
||||
}
|
||||
}
|
||||
isp_prt(isp, ISP_LOGDEBUG2, "asked for %lu got raw resid %lu settled for %lu",
|
||||
(u_long)XS_XFRLEN(xs), (u_long)resid, (u_long)XS_GET_RESID(xs));
|
||||
|
||||
/*
|
||||
* Free any DMA resources. As a side effect, this may
|
||||
* also do any cache flushing necessary for data coherence.
|
||||
*/
|
||||
if (XS_XFRLEN(xs)) {
|
||||
if (XS_XFRLEN(xs))
|
||||
ISP_DMAFREE(isp, xs, sp->req_handle);
|
||||
}
|
||||
isp_destroy_handle(isp, sp->req_handle);
|
||||
|
||||
complist[ndone++] = xs; /* defer completion call until later */
|
||||
ISP_MEMZERO(hp, QENTRY_LEN); /* PERF */
|
||||
last_etype = etype;
|
||||
if (ndone == MAX_REQUESTQ_COMPLETIONS) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Complete command if we expect no Status Continuations. */
|
||||
if (cont == 0)
|
||||
isp_done(xs);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we looked at any commands, then it's valid to find out
|
||||
* what the outpointer is. It also is a trigger to update the
|
||||
* ISP's notion of what we've seen so far.
|
||||
*/
|
||||
if (nlooked) {
|
||||
/* We haven't received all Status Continuations, but that is it. */
|
||||
if (cont > 0)
|
||||
isp_done(cont_xs);
|
||||
|
||||
/* If we processed any IOCBs, let ISP know about it. */
|
||||
if (optr != isp->isp_resodx) {
|
||||
ISP_WRITE(isp, isp->isp_respoutrp, optr);
|
||||
isp->isp_resodx = optr;
|
||||
}
|
||||
|
||||
for (i = 0; i < ndone; i++) {
|
||||
xs = complist[i];
|
||||
if (xs) {
|
||||
if (((isp->isp_dblev & (ISP_LOGDEBUG1|ISP_LOGDEBUG2|ISP_LOGDEBUG3))) ||
|
||||
((isp->isp_dblev & (ISP_LOGDEBUG0|ISP_LOG_CWARN) && ((!XS_NOERR(xs)) || (*XS_STSP(xs) != SCSI_GOOD))))) {
|
||||
isp_prt_endcmd(isp, xs);
|
||||
}
|
||||
isp_done(xs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Support routines.
|
||||
*/
|
||||
|
||||
void
|
||||
isp_prt_endcmd(ispsoftc_t *isp, XS_T *xs)
|
||||
{
|
||||
char cdbstr[16 * 5 + 1];
|
||||
int i, lim;
|
||||
|
||||
lim = XS_CDBLEN(xs) > 16? 16 : XS_CDBLEN(xs);
|
||||
ISP_SNPRINTF(cdbstr, sizeof (cdbstr), "0x%02x ", XS_CDBP(xs)[0]);
|
||||
for (i = 1; i < lim; i++) {
|
||||
ISP_SNPRINTF(cdbstr, sizeof (cdbstr), "%s0x%02x ", cdbstr, XS_CDBP(xs)[i]);
|
||||
}
|
||||
if (XS_SENSE_VALID(xs)) {
|
||||
isp_xs_prt(isp, xs, ISP_LOGALL, "FIN dl%d resid %ld CDB=%s SenseLength=%u/%u KEY/ASC/ASCQ=0x%02x/0x%02x/0x%02x",
|
||||
XS_XFRLEN(xs), (long) XS_GET_RESID(xs), cdbstr, XS_CUR_SNSLEN(xs), XS_TOT_SNSLEN(xs), XS_SNSKEY(xs), XS_SNSASC(xs), XS_SNSASCQ(xs));
|
||||
} else {
|
||||
isp_xs_prt(isp, xs, ISP_LOGALL, "FIN dl%d resid %ld CDB=%s STS 0x%x XS_ERR=0x%x", XS_XFRLEN(xs), (long) XS_GET_RESID(xs), cdbstr, *XS_STSP(xs), XS_ERR(xs));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5989,34 +5859,17 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt
|
||||
case RQSTYPE_ABTS_RCVD:
|
||||
case RQSTYPE_ABTS_RSP:
|
||||
#ifdef ISP_TARGET_MODE
|
||||
if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp))
|
||||
return (1);
|
||||
return (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp));
|
||||
#endif
|
||||
/* FALLTHROUGH */
|
||||
case RQSTYPE_REQUEST:
|
||||
default:
|
||||
ISP_DELAY(100);
|
||||
if (type != isp_get_response_type(isp, hp)) {
|
||||
/*
|
||||
* This is questionable- we're just papering over
|
||||
* something we've seen on SMP linux in target
|
||||
* mode- we don't really know what's happening
|
||||
* here that causes us to think we've gotten
|
||||
* an entry, but that either the entry isn't
|
||||
* filled out yet or our CPU read data is stale.
|
||||
*/
|
||||
isp_prt(isp, ISP_LOGINFO,
|
||||
"unstable type in response queue");
|
||||
return (-1);
|
||||
}
|
||||
isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
|
||||
isp_get_response_type(isp, hp));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
|
||||
isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, uint32_t *rp)
|
||||
{
|
||||
switch (sp->req_completion_status & 0xff) {
|
||||
case RQCS_COMPLETE:
|
||||
@ -6344,7 +6197,7 @@ isp_parse_status(ispsoftc_t *isp, ispstatusreq_t *sp, XS_T *xs, long *rp)
|
||||
}
|
||||
|
||||
static void
|
||||
isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, long *rp)
|
||||
isp_parse_status_24xx(ispsoftc_t *isp, isp24xx_statusreq_t *sp, XS_T *xs, uint32_t *rp)
|
||||
{
|
||||
int ru_marked, sv_marked;
|
||||
int chan = XS_CHANNEL(xs);
|
||||
|
@ -731,8 +731,6 @@ isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
|
||||
if (ISP_PCMD(ccb)) {
|
||||
#ifdef ISP_TARGET_MODE
|
||||
PISP_PCMD(ccb)->datalen = 0;
|
||||
PISP_PCMD(ccb)->totslen = 0;
|
||||
PISP_PCMD(ccb)->cumslen = 0;
|
||||
PISP_PCMD(ccb)->crn = 0;
|
||||
#endif
|
||||
PISP_PCMD(ccb)->next = isp->isp_osinfo.pcmd_free;
|
||||
@ -2581,7 +2579,6 @@ isp_watchdog(void *arg)
|
||||
isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", __func__, handle);
|
||||
xs->ccb_h.status &= ~CAM_STATUS_MASK;
|
||||
xs->ccb_h.status |= CAM_CMD_TIMEOUT;
|
||||
isp_prt_endcmd(isp, xs);
|
||||
isp_done(xs);
|
||||
} else {
|
||||
if (ohandle != ISP_HANDLE_FREE) {
|
||||
|
@ -176,8 +176,6 @@ struct isp_pcmd {
|
||||
struct ispsoftc * isp; /* containing isp */
|
||||
struct callout wdog; /* watchdog timer */
|
||||
uint32_t datalen; /* data length for this command (target mode only) */
|
||||
uint8_t totslen; /* sense length on status response */
|
||||
uint8_t cumslen; /* sense length on status response */
|
||||
uint8_t crn; /* command reference number */
|
||||
};
|
||||
#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1
|
||||
@ -569,26 +567,19 @@ default: \
|
||||
|
||||
#define XS_INITERR(ccb) XS_SETERR(ccb, CAM_REQ_INPROG), ccb->sense_resid = ccb->sense_len
|
||||
|
||||
#define XS_SAVE_SENSE(xs, sense_ptr, totslen, slen) do { \
|
||||
uint32_t tlen = slen; \
|
||||
if (tlen > (xs)->sense_len) \
|
||||
tlen = (xs)->sense_len; \
|
||||
PISP_PCMD(xs)->totslen = imin((xs)->sense_len, totslen); \
|
||||
PISP_PCMD(xs)->cumslen = tlen; \
|
||||
memcpy(&(xs)->sense_data, sense_ptr, tlen); \
|
||||
(xs)->sense_resid = (xs)->sense_len - tlen; \
|
||||
(xs)->ccb_h.status |= CAM_AUTOSNS_VALID; \
|
||||
#define XS_SAVE_SENSE(xs, sp, len) do { \
|
||||
uint32_t amt = min(len, (xs)->sense_len); \
|
||||
memcpy(&(xs)->sense_data, sp, amt); \
|
||||
(xs)->sense_resid = (xs)->sense_len - amt; \
|
||||
(xs)->ccb_h.status |= CAM_AUTOSNS_VALID; \
|
||||
} while (0)
|
||||
|
||||
#define XS_SENSE_APPEND(xs, xsnsp, xsnsl) do { \
|
||||
uint32_t off = PISP_PCMD(xs)->cumslen; \
|
||||
uint8_t *ptr = &((uint8_t *)(&(xs)->sense_data))[off]; \
|
||||
uint32_t amt = imin(xsnsl, PISP_PCMD(xs)->totslen - off); \
|
||||
if (amt) { \
|
||||
memcpy(ptr, xsnsp, amt); \
|
||||
(xs)->sense_resid -= amt; \
|
||||
PISP_PCMD(xs)->cumslen += amt; \
|
||||
} \
|
||||
#define XS_SENSE_APPEND(xs, sp, len) do { \
|
||||
uint8_t *ptr = (uint8_t *)(&(xs)->sense_data) + \
|
||||
((xs)->sense_len - (xs)->sense_resid); \
|
||||
uint32_t amt = min((len), (xs)->sense_resid); \
|
||||
memcpy(ptr, sp, amt); \
|
||||
(xs)->sense_resid -= amt; \
|
||||
} while (0)
|
||||
|
||||
#define XS_SENSE_VALID(xs) (((xs)->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
|
||||
|
@ -913,11 +913,6 @@ void isp_async(ispsoftc_t *, ispasync_t, ...);
|
||||
#define ISPASYNC_CHANGE_SNS 1
|
||||
#define ISPASYNC_CHANGE_OTHER 2
|
||||
|
||||
/*
|
||||
* Platform Independent Error Prinout
|
||||
*/
|
||||
void isp_prt_endcmd(ispsoftc_t *, XS_T *);
|
||||
|
||||
/*
|
||||
* Platform Dependent Error and Debug Printout
|
||||
*
|
||||
@ -1039,8 +1034,7 @@ void isp_prt_endcmd(ispsoftc_t *, XS_T *);
|
||||
* XS_NOERR(xs) there is no error currently set
|
||||
* XS_INITERR(xs) initialize error state
|
||||
*
|
||||
* XS_SAVE_SENSE(xs, sp, total_len, this_len) save sense data (total and current amount)
|
||||
*
|
||||
* XS_SAVE_SENSE(xs, sp, len) save sense data
|
||||
* XS_APPEND_SENSE(xs, sp, len) append more sense data
|
||||
*
|
||||
* XS_SENSE_VALID(xs) indicates whether sense is valid
|
||||
|
Loading…
Reference in New Issue
Block a user