Improve command timeout handling.

Let firmware do its best first, and if it can't, try software recovery.
I would remove software timeout handler completely, but found bunch of
complains on command timeout on sparc64 mailing list few years ago, so
better be safe in case of interrupt loss.

MFC after:	2 weeks
This commit is contained in:
Alexander Motin 2017-03-21 13:10:37 +00:00
parent 1d44b7e821
commit 31c161a615
4 changed files with 14 additions and 36 deletions

View File

@ -4500,13 +4500,9 @@ isp_start(XS_T *xs)
cdbp = t2->req_cdb;
}
}
*tptr = XS_TIME(xs);
ISP_MEMCPY(cdbp, XS_CDBP(xs), cdblen);
*tptr = (XS_TIME(xs) + 999) / 1000;
if (IS_24XX(isp) && *tptr > 0x1999) {
*tptr = 0x1999;
}
/* Whew. Thankfully the same for type 7 requests */
reqp->req_handle = isp_allocate_handle(isp, xs, ISP_HANDLE_INITIATOR);
if (reqp->req_handle == 0) {

View File

@ -1241,7 +1241,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how)
cto->ct_iid_hi = atp->sid >> 16;
cto->ct_oxid = atp->oxid;
cto->ct_vpidx = ISP_GET_VPIDX(isp, XS_CHANNEL(ccb));
cto->ct_timeout = (XS_TIME(ccb) + 999) / 1000;
cto->ct_timeout = XS_TIME(ccb);
cto->ct_flags = atp->tattr << CT7_TASK_ATTR_SHIFT;
/*
@ -1390,7 +1390,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how)
cto->ct_lun = ccb->ccb_h.target_lun;
}
}
cto->ct_timeout = (XS_TIME(ccb) + 999) / 1000;
cto->ct_timeout = XS_TIME(ccb);
cto->ct_rxid = cso->tag_id;
/*
@ -2958,9 +2958,10 @@ isp_abort_inot(ispsoftc_t *isp, union ccb *ccb)
static void
isp_action(struct cam_sim *sim, union ccb *ccb)
{
int bus, tgt, ts, error;
int bus, tgt, error;
ispsoftc_t *isp;
struct ccb_trans_settings *cts;
sbintime_t ts;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
@ -3010,15 +3011,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
switch (error) {
case CMD_QUEUED:
ccb->ccb_h.status |= CAM_SIM_QUEUED;
if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
if (ccb->ccb_h.timeout == CAM_TIME_INFINITY)
break;
}
ts = ccb->ccb_h.timeout;
if (ts == CAM_TIME_DEFAULT) {
ts = 60*1000;
}
ts = isp_mstohz(ts);
callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb);
/* Give firmware extra 10s to handle timeout. */
ts = SBT_1MS * ccb->ccb_h.timeout + 10 * SBT_1S;
callout_reset_sbt(&PISP_PCMD(ccb)->wdog, ts, 0,
isp_watchdog, ccb, 0);
break;
case CMD_RQLATER:
isp_prt(isp, ISP_LOGDEBUG0, "%d.%jx retry later",
@ -4097,23 +4095,6 @@ isp_fc_scratch_acquire(ispsoftc_t *isp, int chan)
return (ret);
}
int
isp_mstohz(int ms)
{
int hz;
struct timeval t;
t.tv_sec = ms / 1000;
t.tv_usec = (ms % 1000) * 1000;
hz = tvtohz(&t);
if (hz < 0) {
hz = 0x7fffffff;
}
if (hz == 0) {
hz = 1;
}
return (hz);
}
void
isp_platform_intr(void *arg)
{

View File

@ -520,7 +520,9 @@ default: \
#define XS_CDBLEN(ccb) (ccb)->cdb_len
#define XS_XFRLEN(ccb) (ccb)->dxfer_len
#define XS_TIME(ccb) (ccb)->ccb_h.timeout
#define XS_TIME(ccb) \
(((ccb)->ccb_h.timeout > 0xffff * 1000 - 999) ? 0 : \
(((ccb)->ccb_h.timeout + 999) / 1000))
#define XS_GET_RESID(ccb) (ccb)->resid
#define XS_SET_RESID(ccb, r) (ccb)->resid = r
#define XS_STSP(ccb) (&(ccb)->scsi_status)
@ -711,7 +713,6 @@ void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
void isp_mbox_notify_done(ispsoftc_t *);
void isp_mbox_release(ispsoftc_t *);
int isp_fc_scratch_acquire(ispsoftc_t *, int);
int isp_mstohz(int);
void isp_platform_intr(void *);
void isp_platform_intr_resp(void *);
void isp_platform_intr_atio(void *);

View File

@ -1011,7 +1011,7 @@ void isp_prt_endcmd(ispsoftc_t *, XS_T *);
* XS_CDBP(xs) gets a pointer to the scsi CDB ""
* XS_CDBLEN(xs) gets the CDB's length ""
* XS_XFRLEN(xs) gets the associated data transfer length ""
* XS_TIME(xs) gets the time (in milliseconds) for this command
* XS_TIME(xs) gets the time (in seconds) for this command
* XS_GET_RESID(xs) gets the current residual count
* XS_GET_RESID(xs, resid) sets the current residual count
* XS_STSP(xs) gets a pointer to the SCSI status byte ""