summaryrefslogtreecommitdiff
path: root/sys/dev/mps
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2019-07-08 20:20:01 +0000
committerWarner Losh <imp@FreeBSD.org>2019-07-08 20:20:01 +0000
commit8fe7bf064fe2bbde5d71e0e7d6711c6638147775 (patch)
treea6472856453b249a9400a30ab1a75f4eb84ca908 /sys/dev/mps
parent6529459a96afacc2c0ae8380c3c2268e47d55535 (diff)
Notes
Diffstat (limited to 'sys/dev/mps')
-rw-r--r--sys/dev/mps/mps.c19
-rw-r--r--sys/dev/mps/mps_sas.c12
-rw-r--r--sys/dev/mps/mps_sas_lsi.c6
-rw-r--r--sys/dev/mps/mpsvar.h15
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;