Index: sys/cam/cam_xpt.h =================================================================== --- sys/cam/cam_xpt.h +++ sys/cam/cam_xpt.h @@ -148,6 +148,7 @@ const char * xpt_action_name(uint32_t action); void xpt_pollwait(union ccb *start_ccb, uint32_t timeout); uint32_t xpt_poll_setup(union ccb *start_ccb); +void xpt_sim_poll(struct cam_sim *sim); /* * Perform a path inquiry at the request priority. The bzero may be Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -3198,6 +3198,25 @@ start_ccb->ccb_h.status)); } +/* + * Call the sim poll routine to allow the sim to complete + * any inflight requests, then call camisr_runqueue to + * complete any CCB that the polling completed. + */ +void +xpt_sim_poll(struct cam_sim *sim) +{ + struct mtx *mtx; + + mtx = sim->mtx; + if (mtx) + mtx_lock(mtx); + (*(sim->sim_poll))(sim); + if (mtx) + mtx_unlock(mtx); + camisr_runqueue(); +} + uint32_t xpt_poll_setup(union ccb *start_ccb) { @@ -3205,12 +3224,10 @@ struct cam_sim *sim; struct cam_devq *devq; struct cam_ed *dev; - struct mtx *mtx; timeout = start_ccb->ccb_h.timeout * 10; sim = start_ccb->ccb_h.path->bus->sim; devq = sim->devq; - mtx = sim->mtx; dev = start_ccb->ccb_h.path->device; /* @@ -3223,12 +3240,7 @@ (--timeout > 0)) { mtx_unlock(&devq->send_mtx); DELAY(100); - if (mtx) - mtx_lock(mtx); - (*(sim->sim_poll))(sim); - if (mtx) - mtx_unlock(mtx); - camisr_runqueue(); + xpt_sim_poll(sim); mtx_lock(&devq->send_mtx); } dev->ccbq.dev_openings++; @@ -3240,19 +3252,9 @@ void xpt_pollwait(union ccb *start_ccb, uint32_t timeout) { - struct cam_sim *sim; - struct mtx *mtx; - - sim = start_ccb->ccb_h.path->bus->sim; - mtx = sim->mtx; while (--timeout > 0) { - if (mtx) - mtx_lock(mtx); - (*(sim->sim_poll))(sim); - if (mtx) - mtx_unlock(mtx); - camisr_runqueue(); + xpt_sim_poll(start_ccb->ccb_h.path->bus->sim); if ((start_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) break; Index: sys/dev/mpr/mpr_sas_lsi.c =================================================================== --- sys/dev/mpr/mpr_sas_lsi.c +++ sys/dev/mpr/mpr_sas_lsi.c @@ -46,10 +46,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -127,7 +129,7 @@ u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); -static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); +static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc, int howto); static void mprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb); @@ -1469,7 +1471,7 @@ * Return nothing. */ static void -mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) +mprsas_SSU_to_SATA_devices(struct mpr_softc *sc, int howto) { struct mprsas_softc *sassc = sc->sassc; union ccb *ccb; @@ -1477,7 +1479,7 @@ target_id_t targetid; struct mprsas_target *target; char path_str[64]; - struct timeval cur_time, start_time; + int timeout; mpr_lock(sc); @@ -1544,17 +1546,25 @@ mpr_unlock(sc); /* - * Wait until all of the SSU commands have completed or time has - * expired (60 seconds). Pause for 100ms each time through. If any - * command times out, the target will be reset in the SCSI command - * timeout routine. + * Timeout after 60 seconds by default or 10 seconds if howto has + * RB_NOSYNC set which indicates we're likely handling a panic. */ - getmicrotime(&start_time); - while (sc->SSU_refcount) { + timeout = 600; + if (howto & RB_NOSYNC) + timeout = 100; + + /* + * Wait until all of the SSU commands have completed or time + * has expired. Pause for 100ms each time through. If any + * command times out, the target will be reset in the SCSI + * command timeout routine. + */ + while (sc->SSU_refcount > 0) { pause("mprwait", hz/10); + if (SCHEDULER_STOPPED()) + xpt_sim_poll(sassc->sim); - getmicrotime(&cur_time); - if ((cur_time.tv_sec - start_time.tv_sec) > 60) { + if (--timeout == 0) { mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " "for SSU commands to complete.\n"); break; @@ -1596,7 +1606,7 @@ * Return nothing. */ void -mprsas_ir_shutdown(struct mpr_softc *sc) +mprsas_ir_shutdown(struct mpr_softc *sc, int howto) { u16 volume_mapping_flags; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); @@ -1701,5 +1711,5 @@ } } } - mprsas_SSU_to_SATA_devices(sc); + mprsas_SSU_to_SATA_devices(sc, howto); } Index: sys/dev/mpr/mprvar.h =================================================================== --- sys/dev/mpr/mprvar.h +++ sys/dev/mpr/mprvar.h @@ -807,7 +807,7 @@ int mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address); -void mprsas_ir_shutdown(struct mpr_softc *sc); +void mprsas_ir_shutdown(struct mpr_softc *sc, int howto); int mpr_reinit(struct mpr_softc *sc); void mprsas_handle_reinit(struct mpr_softc *sc); Index: sys/dev/mps/mps_sas_lsi.c =================================================================== --- sys/dev/mps/mps_sas_lsi.c +++ sys/dev/mps/mps_sas_lsi.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1209,7 +1210,9 @@ */ while (sc->SSU_refcount > 0) { pause("mpswait", hz/10); - + if (SCHEDULER_STOPPED()) + xpt_sim_poll(sassc->sim); + if (--timeout == 0) { mps_dprint(sc, MPS_FAULT, "Time has expired waiting " "for SSU commands to complete.\n");