summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_freebsd.c
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2010-02-03 21:09:32 +0000
committermjacob <mjacob@FreeBSD.org>2010-02-03 21:09:32 +0000
commitdf42a0ca6b960167d6735a4fb358950b6d690ce6 (patch)
treefdde0434a01b70cd56bc51a41aa3aaccfc6b07f8 /sys/dev/isp/isp_freebsd.c
parentc499a83bba8f8470ae5c8ef7a572fe3892a87d8c (diff)
downloadFreeBSD-src-df42a0ca6b960167d6735a4fb358950b6d690ce6.zip
FreeBSD-src-df42a0ca6b960167d6735a4fb358950b6d690ce6.tar.gz
Redo how commands handles are created and managed and implement sequence
numbers and handle types in rational way. This will better protect from (unwittingly) dealing with stale handles/commands. Fix the watchdog timeout code to better protect itself from mistakes. If we run an abort on a putatively timed out command, the command may in fact get completed, so check to make sure the command we're timing it out is still around. If the abort succeeds, btw, the command should get returned via a different path.
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r--sys/dev/isp/isp_freebsd.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 2861d7b..cd6ec09 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -1653,7 +1653,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_timeout = 10;
}
- if (isp_save_xs_tgt(isp, ccb, &handle)) {
+ if (isp_allocate_xs_tgt(isp, ccb, &handle)) {
xpt_print(ccb->ccb_h.path, "No XFLIST pointers for %s\n", __func__);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
goto out;
@@ -3834,21 +3834,41 @@ isp_watchdog(void *arg)
isp = XS_ISP(xs);
handle = isp_find_handle(isp, xs);
- if (handle) {
+ if (handle != ISP_HANDLE_FREE) {
/*
- * Make sure the command is *really* dead before we
- * release the handle (and DMA resources) for reuse.
+ * Try and make sure the command is really dead before
+ * we release the handle (and DMA resources) for reuse.
+ *
+ * If we are successful in aborting the command then
+ * we're done here because we'll get the command returned
+ * back separately.
+ */
+ if (isp_control(isp, ISPCTL_ABORT_CMD, xs) == 0) {
+ return;
+ }
+
+ /*
+ * Note that after calling the above, the command may in
+ * fact have been completed.
*/
- (void) isp_control(isp, ISPCTL_ABORT_CMD, xs);
+ xs = isp_find_xs(isp, handle);
+
+ /*
+ * If the command no longer exists, then we won't
+ * be able to find the xs again with this handle.
+ */
+ if (xs == NULL) {
+ return;
+ }
/*
- * After this point, the comamnd is really dead.
+ * After this point, the command is really dead.
*/
if (XS_XFRLEN(xs)) {
ISP_DMAFREE(isp, xs, handle);
}
isp_destroy_handle(isp, handle);
- xpt_print(xs->ccb_h.path, "watchdog timeout for handle 0x%x\n", handle);
+ isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", __func__, handle);
XS_SETERR(xs, CAM_CMD_TIMEOUT);
isp_done(xs);
}
OpenPOWER on IntegriCloud