aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/mpr/mpr.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2019-09-26 01:54:24 +0000
committerWarner Losh <imp@FreeBSD.org>2019-09-26 01:54:24 +0000
commit40d21e921a551c61306276dfee10a5529ffe6dbf (patch)
tree99f36866c68853a4f8ba529ef29f98a6792b2049 /sys/dev/mpr/mpr.c
parent863302c12433e368bd0c68a9b0f406bd392fdcd3 (diff)
Notes
Diffstat (limited to 'sys/dev/mpr/mpr.c')
-rw-r--r--sys/dev/mpr/mpr.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c
index d35a5e8b9b58..f8d19bb2943b 100644
--- a/sys/dev/mpr/mpr.c
+++ b/sys/dev/mpr/mpr.c
@@ -2,6 +2,7 @@
* Copyright (c) 2009 Yahoo! Inc.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2016 Avago Technologies
+ * Copyright 2000-2020 Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
+ * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
*
*/
@@ -624,8 +625,9 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
sc->eedp_enabled = TRUE;
if (sc->facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)
sc->control_TLR = TRUE;
- if (sc->facts->IOCCapabilities &
- MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ)
+ if ((sc->facts->IOCCapabilities &
+ MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ) &&
+ (sc->mpr_flags & MPR_FLAGS_SEA_IOC))
sc->atomic_desc_capable = TRUE;
mpr_resize_queues(sc);
@@ -2365,6 +2367,7 @@ mpr_complete_command(struct mpr_softc *sc, struct mpr_command *cm)
return;
}
+ cm->cm_state = MPR_CM_STATE_BUSY;
if (cm->cm_flags & MPR_CM_FLAGS_POLLED)
cm->cm_flags |= MPR_CM_FLAGS_COMPLETE;
@@ -2493,12 +2496,13 @@ void
mpr_intr_locked(void *data)
{
MPI2_REPLY_DESCRIPTORS_UNION *desc;
+ MPI2_DIAG_RELEASE_REPLY *rel_rep;
+ mpr_fw_diagnostic_buffer_t *pBuffer;
struct mpr_softc *sc;
+ uint64_t tdesc;
struct mpr_command *cm = NULL;
uint8_t flags;
u_int pq;
- MPI2_DIAG_RELEASE_REPLY *rel_rep;
- mpr_fw_diagnostic_buffer_t *pBuffer;
sc = (struct mpr_softc *)data;
@@ -2510,6 +2514,17 @@ mpr_intr_locked(void *data)
for ( ;; ) {
cm = NULL;
desc = &sc->post_queue[sc->replypostindex];
+
+ /*
+ * Copy and clear out the descriptor so that any reentry will
+ * immediately know that this descriptor has already been
+ * looked at. There is unfortunate casting magic because the
+ * MPI API doesn't have a cardinal 64bit type.
+ */
+ tdesc = 0xffffffffffffffff;
+ tdesc = atomic_swap_64((uint64_t *)desc, tdesc);
+ desc = (MPI2_REPLY_DESCRIPTORS_UNION *)&tdesc;
+
flags = desc->Default.ReplyFlags &
MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) ||
@@ -2603,13 +2618,17 @@ mpr_intr_locked(void *data)
} else {
cm = &sc->commands[
le16toh(desc->AddressReply.SMID)];
- KASSERT(cm->cm_state == MPR_CM_STATE_INQUEUE,
- ("command not inqueue\n"));
- cm->cm_state = MPR_CM_STATE_BUSY;
- cm->cm_reply = reply;
- cm->cm_reply_data =
- le32toh(desc->AddressReply.
- ReplyFrameAddress);
+ if (cm->cm_state == MPR_CM_STATE_INQUEUE) {
+ cm->cm_reply = reply;
+ cm->cm_reply_data =
+ le32toh(desc->AddressReply.
+ ReplyFrameAddress);
+ } else {
+ mpr_dprint(sc, MPR_RECOVERY,
+ "Bad state for ADDRESS_REPLY status,"
+ " ignoring state %d cm %p\n",
+ cm->cm_state, cm);
+ }
}
break;
}
@@ -2630,9 +2649,6 @@ mpr_intr_locked(void *data)
mpr_display_reply_info(sc,cm->cm_reply);
mpr_complete_command(sc, cm);
}
-
- desc->Words.Low = 0xffffffff;
- desc->Words.High = 0xffffffff;
}
if (pq != sc->replypostindex) {
@@ -3805,12 +3821,15 @@ mpr_wait_command(struct mpr_softc *sc, struct mpr_command **cmp, int timeout,
}
if (error == EWOULDBLOCK) {
- mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s, timeout=%d,"
- " elapsed=%jd\n", __func__, timeout,
- (intmax_t)cur_time.tv_sec);
- rc = mpr_reinit(sc);
- mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
- "failed");
+ if (cm->cm_timeout_handler == NULL) {
+ mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s, timeout=%d,"
+ " elapsed=%jd\n", __func__, timeout,
+ (intmax_t)cur_time.tv_sec);
+ rc = mpr_reinit(sc);
+ mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" :
+ "failed");
+ } else
+ cm->cm_timeout_handler(sc, cm);
if (sc->mpr_flags & MPR_FLAGS_REALLOCATED) {
/*
* Tell the caller that we freed the command in a
@@ -3861,7 +3880,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command **cmp)
break;
}
}
-
+ cm->cm_state = MPR_CM_STATE_BUSY;
if (error) {
mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__);
rc = mpr_reinit(sc);