summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-04-02 10:57:19 +0000
committermav <mav@FreeBSD.org>2017-04-02 10:57:19 +0000
commitfe1ff12d3e59bfbe12ad74705e3c55e84b702521 (patch)
tree54d0c549ddda59263f60657727a1b61ecb0bbae3
parent09e546f130f9d83464f64d5f9cfd6eb5566a5269 (diff)
downloadFreeBSD-src-fe1ff12d3e59bfbe12ad74705e3c55e84b702521.zip
FreeBSD-src-fe1ff12d3e59bfbe12ad74705e3c55e84b702521.tar.gz
MFC r315681: 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.
-rw-r--r--sys/dev/isp/isp.c6
-rw-r--r--sys/dev/isp/isp_freebsd.c37
-rw-r--r--sys/dev/isp/isp_freebsd.h5
-rw-r--r--sys/dev/isp/ispvar.h2
4 files changed, 14 insertions, 36 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b93a367..1328a4f 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -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) {
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 1affa51..9fee4f0 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -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)
{
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 2fb122f..16726bb 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -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 *);
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index a5be98c..e42133c 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -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 ""
OpenPOWER on IntegriCloud