summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2006-07-16 03:34:55 +0000
committermjacob <mjacob@FreeBSD.org>2006-07-16 03:34:55 +0000
commitcada3266ec712ab3cbcbace9df32a3924b21c31f (patch)
tree297269a27f6b1d72f5be3394b1257609487d5db0 /sys/dev
parentd2141d93f8b1a698f0555ee5fad7fc13b75e9c1a (diff)
downloadFreeBSD-src-cada3266ec712ab3cbcbace9df32a3924b21c31f.zip
FreeBSD-src-cada3266ec712ab3cbcbace9df32a3924b21c31f.tar.gz
If we're in mpt_wait_req and the command times out,
mark it as timed out. Don't try and free the config request for read_cfg_header that times out because it's still active. Put in code for the config reply handler that will then free up timed out requests. Fix the FC_PRIMITIVE_SEND completion to not try and free a command twice. Dunno how this possibly could have been working for awhile. MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mpt/mpt.c13
-rw-r--r--sys/dev/mpt/mpt_cam.c9
2 files changed, 18 insertions, 4 deletions
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index 24ef254..2b8028a 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -483,6 +483,11 @@ mpt_config_reply_handler(struct mpt_softc *mpt, request_t *req,
TAILQ_REMOVE(&mpt->request_pending_list, req, links);
if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
wakeup(req);
+ } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) {
+ /*
+ * Whew- we can free this request (late completion)
+ */
+ mpt_free_request(mpt, req);
}
}
@@ -1282,6 +1287,7 @@ mpt_wait_req(struct mpt_softc *mpt, request_t *req,
}
if (time_ms && timeout <= 0) {
MSG_REQUEST_HEADER *msg_hdr = req->req_vbuf;
+ req->state |= REQ_STATE_TIMEDOUT;
mpt_prt(mpt, "mpt_wait_req(%x) timed out\n", msg_hdr->Function);
return (ETIMEDOUT);
}
@@ -1560,7 +1566,12 @@ mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber,
PageType, PageAddress, /*addr*/0, /*len*/0,
sleep_ok, timeout_ms);
if (error != 0) {
- mpt_free_request(mpt, req);
+ /*
+ * Leave the request. Without resetting the chip, it's
+ * still owned by it and we'll just get into trouble
+ * freeing it now. Mark it as abandoned so that if it
+ * shows up later it can be freed.
+ */
mpt_prt(mpt, "read_cfg_header timed out\n");
return (ETIMEDOUT);
}
diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c
index c7803c7..f7f6c8d 100644
--- a/sys/dev/mpt/mpt_cam.c
+++ b/sys/dev/mpt/mpt_cam.c
@@ -2393,14 +2393,17 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req,
TAILQ_REMOVE(&mpt->request_pending_list, req, links);
req->state &= ~REQ_STATE_QUEUED;
req->state |= REQ_STATE_DONE;
- if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) {
+ if (req->state & REQ_STATE_TIMEDOUT) {
+ mpt_lprt(mpt, MPT_PRT_DEBUG,
+ "Sync Primitive Send Completed After Timeout\n");
+ mpt_free_request(mpt, req);
+ } else if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) {
mpt_lprt(mpt, MPT_PRT_DEBUG,
"Async Primitive Send Complete\n");
- TAILQ_REMOVE(&mpt->request_pending_list, req, links);
mpt_free_request(mpt, req);
} else {
mpt_lprt(mpt, MPT_PRT_DEBUG,
- "Sync Primitive Send Complete\n");
+ "Sync Primitive Send Complete- Waking Waiter\n");
wakeup(req);
}
return (TRUE);
OpenPOWER on IntegriCloud