Index: sys/dev/mfi/mfi.c =================================================================== --- sys/dev/mfi/mfi.c (revision 251474) +++ sys/dev/mfi/mfi.c (working copy) @@ -503,7 +503,7 @@ return (ENOMEM); } if (bus_dmamem_alloc(sc->mfi_tb_dmat, (void **)&sc->request_message_pool, - BUS_DMA_NOWAIT, &sc->mfi_tb_dmamap)) { + BUS_DMA_NOWAIT, &sc->mfi_tb_dmamap)) { device_printf(sc->mfi_dev, "Cannot allocate comms memory\n"); return (ENOMEM); } @@ -1317,7 +1317,7 @@ /* * Dummy read to flush the bus; this ensures that the indexes are up - * to date. Restart processing if more commands have come it. + * to date. Restart processing if more commands have come in. */ (void)sc->mfi_read_fw_status(sc); if (pi != sc->mfi_comms->hw_pi) @@ -3776,14 +3776,39 @@ * Fail the command instead of leaving it on * the queue where it could remain stuck forever */ +/* mfi_remove_busy(cm); cm->cm_error = ETIMEDOUT; mfi_complete(sc, cm); +*/ timedout++; } } } + if (sc->mfi_tbolt) { + if (timedout != 0) { + int timedout2 = timedout2; + if (mfi_tbolt_complete_cmd(sc) != 0) { + timedout2 = 0; + TAILQ_FOREACH_SAFE(cm, &sc->mfi_busy, cm_link, tmp) { + if (sc->mfi_aen_cm == cm || + sc->mfi_map_sync_cm == cm) + continue; + if (cm->cm_timestamp <= deadline) + timedout2++; + } + } + device_printf(sc->mfi_dev, "DEBUG: %d commands timed out, " + "%d couldnt be instantly proccessed, %d seconds since " + "last interrupt\n", timedout, timedout2, + (int)(time_uptime - sc->last_intr)); + } else { + device_printf(sc->mfi_dev, "DEBUG: no timeouts @ %d\n", + (int)time_uptime); + } + } + #if 0 if (timedout) MFI_DUMP_CMDS(sc); Index: sys/dev/mfi/mfi_tbolt.c =================================================================== --- sys/dev/mfi/mfi_tbolt.c (revision 251474) +++ sys/dev/mfi/mfi_tbolt.c (working copy) @@ -58,7 +58,6 @@ struct mfi_cmd_tbolt *mfi_tbolt_get_cmd(struct mfi_softc *sc, struct mfi_command *); union mfi_mpi2_request_descriptor * mfi_tbolt_get_request_descriptor(struct mfi_softc *sc, uint16_t index); -void mfi_tbolt_complete_cmd(struct mfi_softc *sc); int mfi_tbolt_build_io(struct mfi_softc *sc, struct mfi_command *mfi_cmd, struct mfi_cmd_tbolt *cmd); union mfi_mpi2_request_descriptor *mfi_tbolt_build_mpt_cmd(struct mfi_softc @@ -94,7 +93,13 @@ void mfi_tbolt_enable_intr_ppc(struct mfi_softc *sc) { + /* For Thunderbolt/Invader also clear intr on enable */ + MFI_WRITE4(sc, MFI_OSTS, ~0); + /* Dummy read to force pci flush */ + MFI_READ4(sc, MFI_OSTS); + MFI_WRITE4(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK); + /* Dummy read to force pci flush */ MFI_READ4(sc, MFI_OMSK); } @@ -102,6 +107,7 @@ mfi_tbolt_disable_intr_ppc(struct mfi_softc *sc) { MFI_WRITE4(sc, MFI_OMSK, 0xFFFFFFFF); + /* Dummy read to force pci flush */ MFI_READ4(sc, MFI_OMSK); } @@ -114,23 +120,19 @@ int32_t mfi_tbolt_check_clear_intr_ppc(struct mfi_softc *sc) { - int32_t status, mfi_status = 0; + int32_t status; status = MFI_READ4(sc, MFI_OSTS); if (status & 1) { MFI_WRITE4(sc, MFI_OSTS, status); + /* Dummy read to force pci flush */ MFI_READ4(sc, MFI_OSTS); - if (status & MFI_STATE_CHANGE_INTERRUPT) { - mfi_status |= MFI_FIRMWARE_STATE_CHANGE; - } - - return mfi_status; + return 0; } if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) return 1; - MFI_READ4(sc, MFI_OSTS); return 0; } @@ -576,16 +578,36 @@ mfi_intr_tbolt(void *arg) { struct mfi_softc *sc = (struct mfi_softc *)arg; + int retries; if (sc->mfi_check_clear_intr(sc) == 1) { return; } - if (sc->mfi_detaching) + + sc->last_intr = time_uptime; + + if (sc->mfi_detaching || sc->adpreset) { + (void) sc->mfi_check_clear_intr(sc); return; + } + mtx_lock(&sc->mfi_io_lock); - mfi_tbolt_complete_cmd(sc); - sc->mfi_flags &= ~MFI_FLAGS_QFRZN; - mfi_startio(sc); + retries = 0; + while (mfi_tbolt_complete_cmd(sc) != 0) { + (void) sc->mfi_check_clear_intr(sc); + retries++; + } + if (retries == 0) { + (void) sc->mfi_check_clear_intr(sc); + /* If we didn't complete any commands, check for FW faults? */ + } else { + if (retries != 1) { + device_printf(sc->mfi_dev, + "DEBUG: intr took %d retries\n", retries); + } + sc->mfi_flags &= ~MFI_FLAGS_QFRZN; + mfi_startio(sc); + } mtx_unlock(&sc->mfi_io_lock); return; } @@ -654,7 +676,7 @@ TAILQ_INSERT_TAIL(&sc->mfi_cmd_tbolt_tqh, tbolt_cmd, next); } -void +int mfi_tbolt_complete_cmd(struct mfi_softc *sc) { struct mfi_mpi2_reply_header *desc, *reply_desc; @@ -675,13 +697,15 @@ if (reply_desc == NULL) { device_printf(sc->mfi_dev, "reply desc is NULL!!\n"); - return; + return (0); } reply_descript_type = reply_desc->ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) - return; + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { + device_printf(sc->mfi_dev, "DEBUG: complete unused\n"); + return (0); + } num_completed = 0; val.word = ((union mfi_mpi2_reply_descriptor *)desc)->words; @@ -726,10 +750,8 @@ next: sc->last_reply_idx++; - if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) { - MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx); + if (sc->last_reply_idx >= sc->mfi_max_fw_cmds) sc->last_reply_idx = 0; - } /* Set it back to all 0xfff */ ((union mfi_mpi2_reply_descriptor*)desc)->words = @@ -749,14 +771,15 @@ break; } - if (!num_completed) - return; + if (num_completed == 0) { + device_printf(sc->mfi_dev, "DEBUG: complete none\n"); + return (0); + } /* update replyIndex to FW */ - if (sc->last_reply_idx) - MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx); + MFI_WRITE4(sc, MFI_RPI, sc->last_reply_idx); - return; + return (1); } /* @@ -1142,12 +1165,12 @@ * Force check reply queue. * This ensures that dump works correctly */ - mfi_tbolt_complete_cmd(sc); + (void) mfi_tbolt_complete_cmd(sc); } } /* ensure the command cleanup has been processed before returning */ - mfi_tbolt_complete_cmd(sc); + (void) mfi_tbolt_complete_cmd(sc); if (hdr->cmd_status == MFI_STAT_INVALID_STATUS) { device_printf(sc->mfi_dev, "Frame %p timed out " Index: sys/dev/mfi/mfivar.h =================================================================== --- sys/dev/mfi/mfivar.h (revision 251474) +++ sys/dev/mfi/mfivar.h (working copy) @@ -365,6 +365,9 @@ uint8_t max_SGEs_in_main_message; uint8_t chain_offset_value_for_main_message; uint8_t chain_offset_value_for_mpt_ptmsg; + + /* Ddebugging */ + time_t last_intr; }; union desc_value { @@ -627,5 +630,6 @@ extern void mfi_release_command(struct mfi_command *); extern void mfi_tbolt_return_cmd(struct mfi_softc *, struct mfi_cmd_tbolt *, struct mfi_command *); +extern int mfi_tbolt_complete_cmd(struct mfi_softc *); #endif /* _MFIVAR_H */