Index: sys/dev/mpr/mpr.c =================================================================== --- sys/dev/mpr/mpr.c +++ sys/dev/mpr/mpr.c @@ -2492,7 +2492,7 @@ void mpr_intr_locked(void *data) { - MPI2_REPLY_DESCRIPTORS_UNION *desc; + MPI2_REPLY_DESCRIPTORS_UNION *desc, tdesc; struct mpr_softc *sc; struct mpr_command *cm = NULL; uint8_t flags; @@ -2510,12 +2510,26 @@ for ( ;; ) { cm = NULL; desc = &sc->post_queue[sc->replypostindex]; - flags = desc->Default.ReplyFlags & + + /* Copy over the descriptor */ + tdesc.Words.High = desc->Words.High; + tdesc.Words.Low = desc->Words.Low; + + flags = tdesc.Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) || - (le32toh(desc->Words.High) == 0xffffffff)) + (le32toh(tdesc.Words.High) == 0xffffffff)) break; + /* + * Clear out the descriptor so that any reentry will + * immediately know that this descriptor has already been + * looked at. + */ + desc->Words.Low = 0xffffffff; + desc->Words.High = 0xffffffff; + desc = NULL; + /* increment the replypostindex now, so that event handlers * and cm completion handlers which decide to do a diag * reset can zero it without it getting incremented again @@ -2530,7 +2544,7 @@ case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS: case MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS: case MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS: - cm = &sc->commands[le16toh(desc->SCSIIOSuccess.SMID)]; + cm = &sc->commands[le16toh(tdesc.SCSIIOSuccess.SMID)]; KASSERT(cm->cm_state == MPR_CM_STATE_INQUEUE, ("command not inqueue\n")); cm->cm_state = MPR_CM_STATE_BUSY; @@ -2550,7 +2564,7 @@ * offset against the virtual address base * (sc->reply_frames). */ - baddr = le32toh(desc->AddressReply.ReplyFrameAddress); + baddr = le32toh(tdesc.AddressReply.ReplyFrameAddress); reply = sc->reply_frames + (baddr - ((uint32_t)sc->reply_busaddr)); /* @@ -2572,7 +2586,7 @@ /* LSI-TODO. See Linux Code for Graceful exit */ panic("Reply address out of range"); } - if (le16toh(desc->AddressReply.SMID) == 0) { + if (le16toh(tdesc.AddressReply.SMID) == 0) { if (((MPI2_DEFAULT_REPLY *)reply)->Function == MPI2_FUNCTION_DIAG_BUFFER_POST) { /* @@ -2602,13 +2616,13 @@ reply); } else { cm = &sc->commands[ - le16toh(desc->AddressReply.SMID)]; + le16toh(tdesc.AddressReply.SMID)]; KASSERT(cm->cm_state == MPR_CM_STATE_INQUEUE, - ("command not inqueue\n")); + ("command SMID %d not inqueue\n", tdesc.AddressReply.SMID)); cm->cm_state = MPR_CM_STATE_BUSY; cm->cm_reply = reply; cm->cm_reply_data = - le32toh(desc->AddressReply. + le32toh(tdesc.AddressReply. ReplyFrameAddress); } break; @@ -2619,7 +2633,7 @@ default: /* Unhandled */ mpr_dprint(sc, MPR_ERROR, "Unhandled reply 0x%x\n", - desc->Default.ReplyFlags); + tdesc.Default.ReplyFlags); cm = NULL; break; } @@ -2630,9 +2644,6 @@ 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) {