DF-3801 / fix.diff
diff --git a/sys/dev/raid/mpr/mpr_sas.c b/sys/dev/raid/mpr/mpr_sas.c index 1111111..2222222 100644 --- a/sys/dev/raid/mpr/mpr_sas.c +++ b/sys/dev/raid/mpr/mpr_sas.c @@ -3390,9 +3390,21 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) resp = (MPI2_SCSI_TASK_MANAGE_REPLY *)tm->cm_reply; ccb = tm->cm_complete_data; + /* + * DF-3801: a Diag Reset completes outstanding TMs with a NULL + * reply (mprsas_complete_all_commands); every other TM completion + * handler guards this. Without the guard we deref resp below and + * panic. + */ /* * Currently there should be no way we can hit this case. It only * happens when we have a failure to allocate chain frames, and * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { @@ -3407,6 +3419,15 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) goto bailout; } + if (resp == NULL) { + mpr_dprint(sc, MPR_RECOVERY, + "NULL reset reply for tm %p\n", tm); + if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) + mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); + else + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); + goto bailout; + } + mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); |