# HG changeset patch # User Taylor R Campbell # Date 1597974123 0 # Fri Aug 21 01:42:03 2020 +0000 # Branch trunk # Node ID e548d28ec5c1704385ff7bab0b69c9acd6cc3bca # Parent 08ec9ad3f69b5448088ea57924148f0d4401c8c3 # EXP-Topic riastradh-mptfixes mpt(4): Formalize request state transitions and make assertions. While here, use the name we already had for a magic number, and omit a redundant assignment. diff -r 08ec9ad3f69b -r e548d28ec5c1 sys/dev/ic/mpt.c --- a/sys/dev/ic/mpt.c Sat Aug 29 10:12:06 2020 +0000 +++ b/sys/dev/ic/mpt.c Fri Aug 21 01:42:03 2020 +0000 @@ -286,17 +286,33 @@ mpt_reset(mpt_softc_t *mpt) return ret; } +void +mpt_transition_request(mpt_softc_t *mpt, request_t *req, + enum mpt_req_state ostate, enum mpt_req_state nstate) +{ + + KASSERT(req); + KASSERTMSG(req == &mpt->request_pool[req->index], + "request %u is %p, not %p", + req->index, &mpt->request_pool[req->index], req); + KASSERTMSG(req->debug == ostate, + "transition to %s -- request %p is in state %s, not %s", + mpt_req_state(nstate), + req, + mpt_req_state(req->debug), + mpt_req_state(ostate)); + + req->debug = nstate; +} + /* Return a command buffer to the free queue */ void mpt_free_request(mpt_softc_t *mpt, request_t *req) { - if (req == NULL || req != &mpt->request_pool[req->index]) { - panic("mpt_free_request bad req ptr\n"); - return; - } + + mpt_transition_request(mpt, req, REQ_DONE, REQ_FREE); req->sequence = 0; req->xfer = NULL; - req->debug = REQ_FREE; SLIST_INSERT_HEAD(&mpt->request_free_list, req, link); } @@ -305,17 +321,13 @@ request_t * mpt_get_request(mpt_softc_t *mpt) { request_t *req; + req = SLIST_FIRST(&mpt->request_free_list); - if (req != NULL) { - if (req != &mpt->request_pool[req->index]) { - panic("mpt_get_request: corrupted request free list\n"); - } - if (req->xfer != NULL) { - panic("mpt_get_request: corrupted request free list (xfer)\n"); - } - SLIST_REMOVE_HEAD(&mpt->request_free_list, link); - req->debug = REQ_IN_PROGRESS; - } + if (req == NULL) + return NULL; + + mpt_transition_request(mpt, req, REQ_FREE, REQ_IN_PROGRESS); + SLIST_REMOVE_HEAD(&mpt->request_free_list, link); return req; } @@ -323,6 +335,8 @@ mpt_get_request(mpt_softc_t *mpt) void mpt_send_cmd(mpt_softc_t *mpt, request_t *req) { + + mpt_transition_request(mpt, req, REQ_IN_PROGRESS, REQ_ON_CHIP); req->sequence = mpt->sequence++; if (mpt->verbose > 1) { u_int32_t *pReq; @@ -339,7 +353,6 @@ mpt_send_cmd(mpt_softc_t *mpt, request_t pReq[12], pReq[13], pReq[14], pReq[15]); } MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - req->debug = REQ_ON_CHIP; mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf); } @@ -1136,6 +1149,7 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who /* Put all request buffers (back) on the free list */ SLIST_INIT(&mpt->request_free_list); for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) { + mpt->request_pool[val].debug = REQ_DONE; mpt_free_request(mpt, &mpt->request_pool[val]); } diff -r 08ec9ad3f69b -r e548d28ec5c1 sys/dev/ic/mpt.h --- a/sys/dev/ic/mpt.h Sat Aug 29 10:12:06 2020 +0000 +++ b/sys/dev/ic/mpt.h Fri Aug 21 01:42:03 2020 +0000 @@ -168,6 +168,8 @@ int mpt_hw_init(mpt_softc_t *); int mpt_init(mpt_softc_t *, u_int32_t); int mpt_reset(mpt_softc_t *); int mpt_send_handshake_cmd(mpt_softc_t *, size_t, void *); +void mpt_transition_request(mpt_softc_t *, request_t *, enum mpt_req_state, + enum mpt_req_state); request_t * mpt_get_request(mpt_softc_t *); void mpt_free_request(mpt_softc_t *, request_t *); int mpt_intr(void *); diff -r 08ec9ad3f69b -r e548d28ec5c1 sys/dev/ic/mpt_debug.c --- a/sys/dev/ic/mpt_debug.c Sat Aug 29 10:12:06 2020 +0000 +++ b/sys/dev/ic/mpt_debug.c Fri Aug 21 01:42:03 2020 +0000 @@ -563,6 +563,7 @@ mpt_req_state(enum mpt_req_state state) case REQ_IN_PROGRESS: text = "In Progress"; break; case REQ_ON_CHIP: text = "On Chip"; break; case REQ_TIMEOUT: text = "Timeout"; break; + case REQ_DONE: text = "Done"; break; default: text = "Unknown"; break; } return text; diff -r 08ec9ad3f69b -r e548d28ec5c1 sys/dev/ic/mpt_netbsd.c --- a/sys/dev/ic/mpt_netbsd.c Sat Aug 29 10:12:06 2020 +0000 +++ b/sys/dev/ic/mpt_netbsd.c Fri Aug 21 01:42:03 2020 +0000 @@ -461,18 +461,15 @@ mpt_restart(mpt_softc_t *mpt, request_t if (xs != NULL) { if (xs->datalen != 0) bus_dmamap_unload(mpt->sc_dmat, req->dmap); - req->xfer = NULL; callout_stop(&xs->xs_callout); if (req != req0) { nreq++; xs->error = XS_REQUEUE; } + mpt_transition_request(mpt, req, REQ_ON_CHIP, + REQ_DONE); + mpt_free_request(mpt, req); scsipi_done(xs); - /* - * Don't need to mpt_free_request() since mpt_init() - * below will free all requests anyway. - */ - mpt_free_request(mpt, req); } } splx(s); @@ -579,6 +576,11 @@ mpt_done(mpt_softc_t *mpt, uint32_t repl index); return; } + KASSERTMSG(req->debug == REQ_ON_CHIP, + "%s: request %u (%p) is %s, expected %s", + __func__, req->index, req, + mpt_req_state(req->debug), + mpt_req_state(REQ_ON_CHIP)); MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); mpt_req = req->req_vbuf; @@ -659,6 +661,7 @@ mpt_done(mpt_softc_t *mpt, uint32_t repl xs->error = XS_NOERROR; xs->status = SCSI_OK; xs->resid = 0; + mpt_transition_request(mpt, req, REQ_ON_CHIP, REQ_DONE); mpt_free_request(mpt, req); scsipi_done(xs); return; @@ -805,8 +808,11 @@ mpt_done(mpt_softc_t *mpt, uint32_t repl } /* If IOC done with this request, free it up. */ - if (mpt_reply == NULL || (mpt_reply->MsgFlags & 0x80) == 0) + if (mpt_reply == NULL || + (mpt_reply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) == 0) { + mpt_transition_request(mpt, req, REQ_ON_CHIP, REQ_DONE); mpt_free_request(mpt, req); + } /* If address reply, give the buffer back to the IOC. */ if (mpt_reply != NULL) @@ -946,6 +952,8 @@ mpt_run_xfer(mpt_softc_t *mpt, struct sc mpt_prt(mpt, "error %d loading DMA map", error); out_bad: s = splbio(); + mpt_transition_request(mpt, req, REQ_IN_PROGRESS, + REQ_DONE); mpt_free_request(mpt, req); scsipi_done(xs); splx(s); @@ -1288,7 +1296,13 @@ mpt_ctlop(mpt_softc_t *mpt, void *vmsg, mpt_prt(mpt, "enable port reply index %d", index); if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) { request_t *req = &mpt->request_pool[index]; - req->debug = REQ_DONE; + if (req->debug != REQ_ON_CHIP) { + mpt_prt(mpt, "bogus port reply %d (%s)", + req->index, mpt_req_state(req->debug)); + } else { + mpt_transition_request(mpt, req, REQ_ON_CHIP, + REQ_DONE); + } } mpt_free_reply(mpt, (reply << 1)); break; @@ -1300,8 +1314,14 @@ mpt_ctlop(mpt_softc_t *mpt, void *vmsg, int index = le32toh(msg->MsgContext) & ~0x80000000; if (index >= 0 && index < MPT_MAX_REQUESTS(mpt)) { request_t *req = &mpt->request_pool[index]; - req->debug = REQ_DONE; - req->sequence = reply; + if (req->debug != REQ_ON_CHIP) { + mpt_prt(mpt, "bogus config reply %d (%s)", + req->index, mpt_req_state(req->debug)); + } else { + mpt_transition_request(mpt, req, REQ_ON_CHIP, + REQ_DONE); + req->sequence = reply; + } } else mpt_free_reply(mpt, (reply << 1)); break;