diff options
| author | Warner Losh <imp@FreeBSD.org> | 2019-07-08 20:20:01 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2019-07-08 20:20:01 +0000 |
| commit | 8fe7bf064fe2bbde5d71e0e7d6711c6638147775 (patch) | |
| tree | a6472856453b249a9400a30ab1a75f4eb84ca908 /sys/dev/mps | |
| parent | 6529459a96afacc2c0ae8380c3c2268e47d55535 (diff) | |
Notes
Diffstat (limited to 'sys/dev/mps')
| -rw-r--r-- | sys/dev/mps/mps.c | 19 | ||||
| -rw-r--r-- | sys/dev/mps/mps_sas.c | 12 | ||||
| -rw-r--r-- | sys/dev/mps/mps_sas_lsi.c | 6 | ||||
| -rw-r--r-- | sys/dev/mps/mpsvar.h | 15 |
4 files changed, 35 insertions, 17 deletions
diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 32b834f52b67..046beda137fc 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -2479,13 +2479,24 @@ mps_intr_locked(void *data) (MPI2_EVENT_NOTIFICATION_REPLY *) reply); } else { + /* + * Ignore commands not in INQUEUE state + * since they've already been completed + * via another path. + */ cm = &sc->commands[ le16toh(desc->AddressReply.SMID)]; - if (cm->cm_state != MPS_CM_STATE_TIMEDOUT) + if (cm->cm_state == MPS_CM_STATE_INQUEUE) { cm->cm_state = MPS_CM_STATE_BUSY; - cm->cm_reply = reply; - cm->cm_reply_data = le32toh( - desc->AddressReply.ReplyFrameAddress); + cm->cm_reply = reply; + cm->cm_reply_data = le32toh( + desc->AddressReply.ReplyFrameAddress); + } else { + mps_dprint(sc, MPS_RECOVERY, + "Bad state for ADDRESS_REPLY status," + " ignoring state %d cm %p\n", + cm->cm_state, cm); + } } break; } diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index f35559ea9c52..8d8bac133cfa 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -1602,7 +1602,7 @@ mpssas_scsiio_timeout(void *data) * and been re-used, though this is unlikely. */ mps_intr_locked(sc); - if (cm->cm_state != MPS_CM_STATE_INQUEUE) { + if (cm->cm_flags & MPS_CM_FLAGS_ON_RECOVERY) { mpssas_log_command(cm, MPS_XINFO, "SCSI command %p almost timed out\n", cm); return; @@ -1626,7 +1626,7 @@ mpssas_scsiio_timeout(void *data) * operational. if not, do a diag reset. */ mpssas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); - cm->cm_state = MPS_CM_STATE_TIMEDOUT; + cm->cm_flags |= MPS_CM_FLAGS_ON_RECOVERY | MPS_CM_FLAGS_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); if (targ->tm != NULL) { @@ -2040,9 +2040,11 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) biotrack(ccb->csio.bio, __func__); #endif - if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) { + if (cm->cm_flags & MPS_CM_FLAGS_ON_RECOVERY) { TAILQ_REMOVE(&cm->cm_targ->timedout_commands, cm, cm_recovery); - cm->cm_state = MPS_CM_STATE_BUSY; + KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, + ("Not busy for CM_FLAGS_TIMEDOUT: %d\n", cm->cm_state)); + cm->cm_flags &= ~MPS_CM_FLAGS_ON_RECOVERY; if (cm->cm_reply != NULL) mpssas_log_command(cm, MPS_RECOVERY, "completed timedout cm %p ccb %p during recovery " @@ -2325,7 +2327,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) * retry counter), the only difference is what gets printed * on the console. */ - if (cm->cm_state == MPS_CM_STATE_TIMEDOUT) + if (cm->cm_flags & MPS_CM_FLAGS_TIMEDOUT) mpssas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); else mpssas_set_ccbstatus(ccb, CAM_REQ_ABORTED); diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 2f23b102e1cb..1362bd7cdd59 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -790,7 +790,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ cm = &sc->commands[i]; if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) { targ->timeouts++; - cm->cm_state = MPS_CM_STATE_TIMEDOUT; + cm->cm_flags |= MPS_CM_FLAGS_TIMEDOUT; if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) { mps_dprint(sc, MPS_INFO, "%s: sending Target " @@ -1017,9 +1017,11 @@ mpssas_ata_id_timeout(struct mps_softc *sc, struct mps_command *cm) /* * The Abort Task cannot be sent from here because the driver has not * completed setting up targets. Instead, the command is flagged so - * that special handling will be used to send the abort. + * that special handling will be used to send the abort. Now that + * this command has timed out, it's no longer in the queue. */ cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT; + cm->cm_state = MPS_CM_STATE_BUSY; } static int diff --git a/sys/dev/mps/mpsvar.h b/sys/dev/mps/mpsvar.h index 4a899bf31798..3193198c6cbd 100644 --- a/sys/dev/mps/mpsvar.h +++ b/sys/dev/mps/mpsvar.h @@ -242,11 +242,12 @@ struct mps_command { #define MPS_CM_FLAGS_ERROR_MASK MPS_CM_FLAGS_CHAIN_FAILED #define MPS_CM_FLAGS_USE_CCB (1 << 10) #define MPS_CM_FLAGS_SATA_ID_TIMEOUT (1 << 11) +#define MPS_CM_FLAGS_ON_RECOVERY (1 << 12) +#define MPS_CM_FLAGS_TIMEDOUT (1 << 13) u_int cm_state; #define MPS_CM_STATE_FREE 0 #define MPS_CM_STATE_BUSY 1 -#define MPS_CM_STATE_TIMEDOUT 2 -#define MPS_CM_STATE_INQUEUE 3 +#define MPS_CM_STATE_INQUEUE 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; TAILQ_HEAD(, mps_chain) cm_chain_list; @@ -545,7 +546,8 @@ mps_free_command(struct mps_softc *sc, struct mps_command *cm) { struct mps_chain *chain, *chain_temp; - KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, ("state not busy\n")); + KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, + ("state not busy: %d\n", cm->cm_state)); if (cm->cm_reply != NULL) mps_free_reply(sc, cm->cm_reply_data); @@ -581,7 +583,7 @@ mps_alloc_command(struct mps_softc *sc) return (NULL); KASSERT(cm->cm_state == MPS_CM_STATE_FREE, - ("mps: Allocating busy command\n")); + ("mps: Allocating busy command: %d\n", cm->cm_state)); TAILQ_REMOVE(&sc->req_list, cm, cm_link); cm->cm_state = MPS_CM_STATE_BUSY; @@ -594,7 +596,8 @@ mps_free_high_priority_command(struct mps_softc *sc, struct mps_command *cm) { struct mps_chain *chain, *chain_temp; - KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, ("state not busy\n")); + KASSERT(cm->cm_state == MPS_CM_STATE_BUSY, + ("state not busy: %d\n", cm->cm_state)); if (cm->cm_reply != NULL) mps_free_reply(sc, cm->cm_reply_data); @@ -623,7 +626,7 @@ mps_alloc_high_priority_command(struct mps_softc *sc) return (NULL); KASSERT(cm->cm_state == MPS_CM_STATE_FREE, - ("mps: Allocating busy command\n")); + ("mps: Allocating high priority busy command: %d\n", cm->cm_state)); TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link); cm->cm_state = MPS_CM_STATE_BUSY; |
