diff options
Diffstat (limited to 'sys/dev/mpr/mpr_sas.c')
| -rw-r--r-- | sys/dev/mpr/mpr_sas.c | 476 |
1 files changed, 261 insertions, 215 deletions
diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 32c3a4633a1f..eac336068295 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. - * Copyright (c) 2011-2014 LSI Corp. + * Copyright (c) 2011-2015 LSI Corp. + * Copyright (c) 2013-2015 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,12 +24,15 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD + * */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT2 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include <sys/types.h> @@ -122,14 +126,10 @@ static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); -static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, +static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); -static int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, - uint8_t type); static void mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg); -static void mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd); #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, @@ -142,13 +142,12 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void -mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); +static void mprsas_smpio_complete(struct mpr_softc *sc, + struct mpr_command *cm); static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); -static void -mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); -#endif + union ccb *ccb, uint64_t sasaddr); +static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); +#endif //FreeBSD_version >= 900026 struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, @@ -230,7 +229,7 @@ mprsas_startup_decrement(struct mprsas_softc *sassc) } } -/* LSI's firmware requires us to stop sending commands when we're doing task +/* The firmware requires us to stop sending commands when we're doing task * management, so refcount the TMs and keep the simq frozen when any are in * use. */ @@ -241,35 +240,31 @@ mprsas_alloc_tm(struct mpr_softc *sc) MPR_FUNCTRACE(sc); tm = mpr_alloc_high_priority_command(sc); - if (tm != NULL) { - if (sc->sassc->tm_count++ == 0) { - mpr_dprint(sc, MPR_RECOVERY, - "%s freezing simq\n", __func__); - xpt_freeze_simq(sc->sassc->sim, 1); - } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); - } return tm; } void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { - mpr_dprint(sc, MPR_TRACE, "%s", __func__); + MPR_FUNCTRACE(sc); if (tm == NULL) return; - /* if there are no TMs in use, we can release the simq. We use our - * own refcount so that it's easier for a diag reset to cleanup and - * release the simq. + /* + * For TM's the devq is frozen for the device. Unfreeze it here and + * free the resources used for freezing the devq. Must clear the + * INRESET flag as well or scsi I/O will not work. */ - if (--sc->sassc->tm_count == 0) { - mpr_dprint(sc, MPR_RECOVERY, "%s releasing simq\n", __func__); - xpt_release_simq(sc->sassc->sim, 1); + if (tm->cm_targ != NULL) { + tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; + } + if (tm->cm_ccb) { + mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", + tm->cm_targ->tid); + xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); + xpt_free_path(tm->cm_ccb->ccb_h.path); + xpt_free_ccb(tm->cm_ccb); } - mpr_dprint(sc, MPR_RECOVERY, "%s tm_count %u\n", __func__, - sc->sassc->tm_count); mpr_free_high_priority_command(sc, tm); } @@ -298,8 +293,8 @@ mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ) return; } - if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, - targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; @@ -473,11 +468,16 @@ mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_volume; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } /* - * The MPT2 firmware performs debounce on the link to avoid transient link + * The MPT3 firmware performs debounce on the link to avoid transient link * errors and false removals. When it does decide that link has been lost * and a device needs to go away, it expects that the host will perform a * target reset and then an op remove. The reset has the side-effect of @@ -532,6 +532,11 @@ mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; cm->cm_complete = mprsas_remove_device; cm->cm_complete_data = (void *)(uintptr_t)handle; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD); + mpr_map_command(sc, cm); } @@ -596,10 +601,10 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_map_command(sc, tm); - mpr_dprint(sc, MPR_XINFO, "clearing target %u handle 0x%04x\n", + mpr_dprint(sc, MPR_INFO, "clearing target %u handle 0x%04x\n", targ->tid, handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -608,7 +613,7 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_XINFO, "Completing missed command %p\n", tm); ccb = tm->cm_complete_data; - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); mprsas_scsiio_complete(sc, tm); } } @@ -726,7 +731,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * XXX MaxTargets could change during a reinit. since we don't + * XXX MaxTargets could change during a reinit. Since we don't * resize the targets[] array during such an event, cache the value * of MaxTargets here so that we don't get into trouble later. This * should move into the reinit logic. @@ -782,7 +787,7 @@ mpr_attach_sas(struct mpr_softc *sc) } /* - * Assume that discovery events will start right away. Freezing + * Assume that discovery events will start right away. * * Hold off boot until discovery is complete. */ @@ -790,9 +795,7 @@ mpr_attach_sas(struct mpr_softc *sc) sc->sassc->startup_refcount = 0; mprsas_startup_increment(sassc); - callout_init(&sassc->discovery_callout, 1 /*mprafe*/); - - sassc->tm_count = 0; + callout_init(&sassc->discovery_callout, 1 /*mpsafe*/); /* * Register for async events so we can determine the EEDP @@ -962,7 +965,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) sassc = cam_sim_softc(sim); MPR_FUNCTRACE(sassc->sc); - mpr_dprint(sassc->sc, MPR_TRACE, "%s func 0x%x\n", __func__, + mpr_dprint(sassc->sc, MPR_TRACE, "ccb func_code 0x%x\n", ccb->ccb_h.func_code); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); @@ -985,7 +988,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cpi->max_lun = 255; cpi->initiator_id = sassc->maxtargets - 1; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN); + strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); @@ -1005,7 +1008,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) */ cpi->maxio = 256 * 1024; #endif - cpi->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_GET_TRAN_SETTINGS: @@ -1024,7 +1027,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id)); targ = &sassc->targets[cts->ccb_h.target_id]; if (targ->handle == 0x0) { - cts->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } @@ -1054,12 +1057,12 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - cts->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: mpr_dprint(sassc->sc, MPR_XINFO, @@ -1071,7 +1074,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) case XPT_TERM_IO: mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success for abort or reset\n"); - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: mprsas_action_scsiio(sassc, ccb); @@ -1082,7 +1085,7 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) return; #endif default: - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + mprsas_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); break; } xpt_done(ccb); @@ -1102,7 +1105,7 @@ mprsas_announce_reset(struct mpr_softc *sc, uint32_t ac_code, if (xpt_create_path(&path, NULL, path_id, target_id, lun_id) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "unable to create path for reset " - "notification\n"); + "notification\n"); return; } @@ -1131,8 +1134,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag reset\n", - cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag " + "reset\n", cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1145,6 +1148,14 @@ mprsas_complete_all_commands(struct mpr_softc *sc) completed = 1; } + if (cm->cm_sc->io_cmds_active != 0) { + cm->cm_sc->io_cmds_active--; + } else { + mpr_dprint(cm->cm_sc, MPR_INFO, "Warning: " + "io_cmds_active is out of sync - resynching to " + "0\n"); + } + if ((completed == 0) && (cm->cm_state != MPR_CM_STATE_FREE)) { /* this should never happen, but if it does, log */ mprsas_log_command(cm, MPR_RECOVERY, @@ -1180,9 +1191,8 @@ mprsas_handle_reinit(struct mpr_softc *sc) /* complete and cleanup after all outstanding commands */ mprsas_complete_all_commands(sc); - mpr_dprint(sc, MPR_INIT, "%s startup %u tm %u after command " - "completion\n", __func__, sc->sassc->startup_refcount, - sc->sassc->tm_count); + mpr_dprint(sc, MPR_INIT, "%s startup %u after command completion\n", + __func__, sc->sassc->startup_refcount); /* zero all the target handles, since they may change after the * reset, and we have to rediscover all the targets and use the new @@ -1244,7 +1254,6 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1322,8 +1331,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) * task management commands don't have S/G lists. */ if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x for target reset! " - "This should not happen!\n", __func__, tm->cm_flags); + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " + "reset! This should not happen!\n", __func__, tm->cm_flags); mprsas_free_tm(sc, tm); return; } @@ -1333,7 +1342,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) "NULL reset reply for tm %p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ - targ->flags &= ~MPRSAS_TARGET_INRESET; targ->tm = NULL; mprsas_free_tm(sc, tm); } @@ -1349,8 +1357,6 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(reply->IOCStatus), le32toh(reply->ResponseCode), le32toh(reply->TerminationCount)); - targ->flags &= ~MPRSAS_TARGET_INRESET; - if (targ->outstanding == 0) { /* we've finished recovery for this target and all * of its logical units. @@ -1378,7 +1384,7 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) #define MPR_RESET_TIMEOUT 30 -static int +int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) { MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1387,8 +1393,8 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) target = tm->cm_targ; if (target->handle == 0) { - mpr_dprint(sc, MPR_ERROR,"%s null devhandle for target_id %d\n", - __func__, target->tid); + mpr_dprint(sc, MPR_ERROR, "%s null devhandle for target_id " + "%d\n", __func__, target->tid); return -1; } @@ -1404,6 +1410,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending logical unit reset\n"); tm->cm_complete = mprsas_logical_unit_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, tm->cm_lun); } else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { /* @@ -1412,20 +1419,20 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) */ req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET; tm->cm_targ->target_resets++; - tm->cm_targ->flags |= MPRSAS_TARGET_INRESET; mprsas_log_command(tm, MPR_RECOVERY|MPR_INFO, "sending target reset\n"); tm->cm_complete = mprsas_target_reset_complete; + mprsas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD); } else { mpr_dprint(sc, MPR_ERROR, "unexpected reset type 0x%x\n", type); return -1; } - mpr_dprint(sc, MPR_XINFO, "to target %u handle 0x%04x\n", target->tid, + mpr_dprint(sc, MPR_INFO, "to target %u handle 0x%04x\n", target->tid, target->handle); if (target->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_INFO, "At enclosure level %d, slot %d, " "connector name (%4s)\n", target->encl_level, target->encl_slot, target->connector_name); } @@ -1441,8 +1448,7 @@ mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type) err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, - "error %d sending reset type %u\n", - err, type); + "error %d sending reset type %u\n", err, type); return err; } @@ -1573,6 +1579,10 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, targ->aborts++; + mpr_dprint(sc, MPR_INFO, "Sending reset from %s for target ID %d\n", + __func__, targ->tid); + mprsas_prepare_for_tm(sc, tm, targ, tm->cm_lun); + err = mpr_map_command(sc, tm); if (err) mprsas_log_command(tm, MPR_RECOVERY, @@ -1581,7 +1591,6 @@ mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, return err; } - static void mprsas_scsiio_timeout(void *data) { @@ -1617,11 +1626,11 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_XINFO, "command timeout cm %p ccb %p " + mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { - mpr_dprint(sc, MPR_XINFO, "At enclosure level %d, slot %d, " + mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, targ->connector_name); } @@ -1629,8 +1638,7 @@ mprsas_scsiio_timeout(void *data) /* XXX first, check the firmware state, to see if it's still * operational. if not, do a diag reset. */ - - cm->cm_ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(cm->cm_ccb, CAM_CMD_TIMEOUT); cm->cm_state = MPR_CM_STATE_TIMEDOUT; TAILQ_INSERT_TAIL(&targ->timedout_commands, cm, cm_recovery); @@ -1681,19 +1689,22 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) mtx_assert(&sc->mpr_mtx, MA_OWNED); csio = &ccb->csio; + KASSERT(csio->ccb_h.target_id < sassc->maxtargets, + ("Target %d out of bounds in XPT_SCSI_IO\n", + csio->ccb_h.target_id)); targ = &sassc->targets[csio->ccb_h.target_id]; mpr_dprint(sc, MPR_TRACE, "ccb %p target flag %x\n", ccb, targ->flags); if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s NULL handle for target %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->flags & MPR_TARGET_FLAGS_RAID_COMPONENT) { - mpr_dprint(sc, MPR_TRACE, "%s Raid component no SCSI IO " + mpr_dprint(sc, MPR_ERROR, "%s Raid component no SCSI IO " "supported %u\n", __func__, csio->ccb_h.target_id); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } @@ -1702,7 +1713,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ - if (ccb->ccb_h.status != CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_INPROG) { mpr_dprint(sc, MPR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); @@ -1715,16 +1726,29 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) */ if (targ->flags & MPRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) - csio->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - csio->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } if ((sc->mpr_flags & MPR_FLAGS_SHUTDOWN) != 0) { - mpr_dprint(sc, MPR_TRACE, "%s shutting down\n", __func__); - csio->ccb_h.status = CAM_DEV_NOT_THERE; + mpr_dprint(sc, MPR_INFO, "%s shutting down\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); + xpt_done(ccb); + return; + } + + /* + * If target has a reset in progress, freeze the devq and return. The + * devq will be released when the TM reset is finished. + */ + if (targ->flags & MPRSAS_TARGET_INRESET) { + ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; + mpr_dprint(sc, MPR_INFO, "%s: Freezing devq for target ID %d\n", + __func__, targ->tid); + xpt_freeze_devq(ccb->ccb_h.path, 1); xpt_done(ccb); return; } @@ -1807,7 +1831,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) if (MPR_SET_LUN(req->LUN, csio->ccb_h.target_lun) != 0) { mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_LUN_INVALID; + mprsas_set_ccbstatus(ccb, CAM_LUN_INVALID); xpt_done(ccb); return; } @@ -1904,7 +1928,7 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) } callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, - mprsas_scsiio_timeout, cm, 0); + mprsas_scsiio_timeout, cm, 0); targ->issued++; targ->outstanding++; @@ -2102,7 +2126,7 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, desc_scsi_state, scsi_state); if (sc->mpr_debug & MPR_XINFO && - scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { + scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : Start :\n"); scsi_sense_print(csio); mpr_dprint(sc, MPR_XINFO, "-> Sense Buffer Data : End :\n"); @@ -2126,6 +2150,8 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) u8 *TLR_bits, TLR_on; int dir = 0, i; u16 alloc_len; + struct mprsas_target *target; + target_id_t target_id; MPR_FUNCTRACE(sc); mpr_dprint(sc, MPR_TRACE, @@ -2139,6 +2165,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) sassc = sc->sassc; ccb = cm->cm_complete_data; csio = &ccb->csio; + target_id = csio->ccb_h.target_id; rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply; /* * XXX KDM if the chain allocation fails, does it matter if we do @@ -2197,7 +2224,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * because there can be no reply when we haven't actually * gone out to the hardware. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); /* * Currently the only error included in the mask is @@ -2214,7 +2241,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) xpt_freeze_simq(sassc->sim, 1); sassc->flags |= MPRSAS_QUEUE_FROZEN; mpr_dprint(sc, MPR_INFO, "Error sending command, " - "freezing SIM queue\n"); + "freezing SIM queue\n"); } } @@ -2224,7 +2251,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * commands that were sent. All SSU commands should be completed before * shutdown completes, meaning SSU_refcount will be 0 after SSU_started * is TRUE. - */ + */ if (sc->SSU_started && (csio->cdb_io.cdb_bytes[0] == START_STOP_UNIT)) { mpr_dprint(sc, MPR_INFO, "Decrementing SSU count.\n"); sc->SSU_refcount--; @@ -2232,12 +2259,12 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Take the fast path to completion */ if (cm->cm_reply == NULL) { - if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) - ccb->ccb_h.status = CAM_SCSI_BUS_RESET; + mprsas_set_ccbstatus(ccb, CAM_SCSI_BUS_RESET); else { - ccb->ccb_h.status = CAM_REQ_CMP; - ccb->csio.scsi_status = SCSI_STATUS_OK; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); + csio->scsi_status = SCSI_STATUS_OK; } if (sassc->flags & MPRSAS_QUEUE_FROZEN) { ccb->ccb_h.status |= CAM_RELEASE_SIMQ; @@ -2252,10 +2279,10 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * CAM_REQ_CMP. The first is if MPR_CM_FLAGS_ERROR_MASK is * set, the second is in the MPR_FLAGS_DIAGRESET above. */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { /* * Freeze the dev queue so that commands are - * executed in the correct order with after error + * executed in the correct order after error * recovery. */ ccb->ccb_h.status |= CAM_DEV_QFRZN; @@ -2285,7 +2312,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) /* Completion failed at the transport level. */ if (rep->SCSIState & (MPI2_SCSI_STATE_NO_SCSI_STATUS | MPI2_SCSI_STATE_TERMINATED)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2294,7 +2321,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * recover the command. */ if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_FAILED) { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; + mprsas_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); break; } @@ -2306,7 +2333,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) && ((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) == MPR_SCSI_RI_INVALID_FRAME)) { - sc->mapping_table[csio->ccb_h.target_id].TLR_bits = + sc->mapping_table[target_id].TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; } @@ -2318,16 +2345,16 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) */ if ((rep->SCSIStatus == MPI2_SCSI_STATUS_COMMAND_TERMINATED) || (rep->SCSIStatus == MPI2_SCSI_STATUS_TASK_ABORTED)) { - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; } /* Handle normal status and sense */ csio->scsi_status = rep->SCSIStatus; if (rep->SCSIStatus == MPI2_SCSI_STATUS_GOOD) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); if (rep->SCSIState & MPI2_SCSI_STATE_AUTOSENSE_VALID) { int sense_len, returned_sense_len; @@ -2362,12 +2389,11 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) (csio->data_ptr != NULL) && ((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) && (sc->control_TLR) && - (sc->mapping_table[csio->ccb_h.target_id].device_info & + (sc->mapping_table[target_id].device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)) { vpd_list = (struct scsi_vpd_supported_page_list *) csio->data_ptr; - TLR_bits = &sc->mapping_table[csio->ccb_h.target_id]. - TLR_bits; + TLR_bits = &sc->mapping_table[target_id].TLR_bits; *TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR; TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON; alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) + @@ -2380,6 +2406,24 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) } } } + + /* + * If this is a SATA direct-access end device, mark it so that + * a SCSI StartStopUnit command will be sent to it when the + * driver is being shutdown. + */ + if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) && + ((csio->data_ptr[0] & 0x1f) == T_DIRECT) && + (sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && + ((sc->mapping_table[target_id].device_info & + MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == + MPI2_SAS_DEVICE_INFO_END_DEVICE)) { + target = &sassc->targets[target_id]; + target->supports_SSU = TRUE; + mpr_dprint(sc, MPR_XINFO, "Target %d supports SSU\n", + target_id); + } break; case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: @@ -2390,13 +2434,13 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * failed. */ if (cm->cm_targ->devinfo == 0) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; case MPI2_IOCSTATUS_INVALID_SGL: mpr_print_scsiio_cmd(sc, cm); - ccb->ccb_h.status = CAM_UNREC_HBA_ERROR; + mprsas_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); break; case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: /* @@ -2409,14 +2453,14 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * on the console. */ if (cm->cm_state == MPR_CM_STATE_TIMEDOUT) - ccb->ccb_h.status = CAM_CMD_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_CMD_TIMEOUT); else - ccb->ccb_h.status = CAM_REQ_ABORTED; + mprsas_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; - ccb->ccb_h.status = CAM_DATA_RUN_ERR; + mprsas_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); break; case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: @@ -2425,7 +2469,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) * transient transport-related) errors, retry these without * decrementing the retry count. */ - ccb->ccb_h.status = CAM_REQUEUE_REQ; + mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, @@ -2447,7 +2491,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, le32toh(rep->TransferCount)); csio->resid = cm->cm_length; - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } @@ -2460,7 +2504,7 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) "queue\n"); } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + if (mprsas_get_ccbstatus(ccb) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } @@ -2487,16 +2531,16 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) * in the standard request size. */ if ((cm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { - mpr_dprint(sc, MPR_ERROR,"%s: cm_flags = %#x on SMP request!\n", - __func__, cm->cm_flags); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x on SMP " + "request!\n", __func__, cm->cm_flags); + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } rpl = (MPI2_SMP_PASSTHROUGH_REPLY *)cm->cm_reply; if (rpl == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: NULL cm_reply!\n", __func__); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2509,17 +2553,17 @@ mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm) rpl->SASStatus != MPI2_SASSTATUS_SUCCESS) { mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus %04x SASStatus %02x\n", __func__, le16toh(rpl->IOCStatus), rpl->SASStatus); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } - mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address " - "%#jx completed successfully\n", __func__, (uintmax_t)sasaddr); + mpr_dprint(sc, MPR_XINFO, "%s: SMP request to SAS address %#jx " + "completed successfully\n", __func__, (uintmax_t)sasaddr); if (ccb->smpio.smp_response[2] == SMP_FR_ACCEPTED) - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); else - ccb->ccb_h.status = CAM_SMP_STATUS_ERROR; + mprsas_set_ccbstatus(ccb, CAM_SMP_STATUS_ERROR); bailout: /* @@ -2558,7 +2602,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " "supported\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; case CAM_DATA_SG: @@ -2571,7 +2615,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or response buffer segments " "not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2605,7 +2649,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, response = ccb->smpio.smp_response; break; default: - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2614,9 +2658,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, * XXX We don't yet support physical addresses here. */ if (ccb->ccb_h.flags & (CAM_DATA_PHYS|CAM_SG_LIST_PHYS)) { - mpr_printf(sc, "%s: physical addresses not supported\n", - __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mpr_dprint(sc, MPR_ERROR, "%s: physical addresses not " + "supported\n", __func__); + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2635,7 +2679,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " "response buffer segments not supported for SMP\n", __func__); - ccb->ccb_h.status = CAM_REQ_INVALID; + mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; } @@ -2673,7 +2717,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, if (cm == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", __func__); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2760,7 +2804,7 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, bailout_error: mpr_free_command(sc, cm); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2783,7 +2827,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: target %d does not exist!\n", __func__, ccb->ccb_h.target_id); - ccb->ccb_h.status = CAM_SEL_TIMEOUT; + mprsas_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } @@ -2831,7 +2875,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (targ->parent_handle == 0x0) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent handle!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } #ifdef OLD_MPR_PROBE @@ -2841,7 +2885,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (parent_target == NULL) { mpr_dprint(sc, MPR_ERROR, "%s: handle %d does not have " "a valid parent target!\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2850,9 +2894,8 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, parent_target->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; - } sasaddr = parent_target->sasaddr; @@ -2862,7 +2905,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent %d " "does not have an SMP target!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2870,7 +2913,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) mpr_dprint(sc, MPR_ERROR, "%s: handle %d parent handle " "%d does not have a valid SAS address!\n", __func__, targ->handle, targ->parent_handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } @@ -2882,7 +2925,7 @@ mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb) if (sasaddr == 0) { mpr_dprint(sc, MPR_INFO, "%s: unable to find SAS address for " "handle %d\n", __func__, targ->handle); - ccb->ccb_h.status = CAM_DEV_NOT_THERE; + mprsas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); goto bailout; } mprsas_send_smpcmd(sassc, ccb, sasaddr); @@ -2914,7 +2957,7 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) if (tm == NULL) { mpr_dprint(sc, MPR_ERROR, "command alloc failure in mprsas_action_resetdev\n"); - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; } @@ -2933,7 +2976,12 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; tm->cm_complete = mprsas_resetdev_complete; tm->cm_complete_data = ccb; + + mpr_dprint(sc, MPR_INFO, "%s: Sending reset for target ID %d\n", + __func__, targ->tid); tm->cm_targ = targ; + targ->flags |= MPRSAS_TARGET_INRESET; + mpr_map_command(sc, tm); } @@ -2962,7 +3010,7 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, req->DevHandle); - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); goto bailout; } @@ -2971,12 +3019,12 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { - ccb->ccb_h.status = CAM_REQ_CMP; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, CAM_LUN_WILDCARD); } else - ccb->ccb_h.status = CAM_REQ_CMP_ERR; + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); bailout: @@ -2995,7 +3043,8 @@ mprsas_poll(struct cam_sim *sim) /* frequent debug messages during a panic just slow * everything down too much. */ - mpr_printf(sassc->sc, "%s clearing MPR_TRACE\n", __func__); + mpr_dprint(sassc->sc, MPR_XINFO, "%s clearing MPR_TRACE\n", + __func__); sassc->sc->mpr_debug &= ~MPR_TRACE; } @@ -3094,7 +3143,7 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); - if (((cdai.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) + if ((mprsas_get_ccbstatus((union ccb *)&cdai) == CAM_REQ_CMP) && (rcap_buf.prot & SRC16_PROT_EN)) { lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf.length); @@ -3121,8 +3170,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, #endif cgd = arg; - mprsas_prepare_ssu(sc, path, cgd); - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) mprsas_check_eedp(sc, path, cgd); @@ -3134,64 +3181,6 @@ mprsas_async(void *callback_arg, uint32_t code, struct cam_path *path, } } -static void -mprsas_prepare_ssu(struct mpr_softc *sc, struct cam_path *path, - struct ccb_getdev *cgd) -{ - struct mprsas_softc *sassc = sc->sassc; - path_id_t pathid; - target_id_t targetid; - lun_id_t lunid; - struct mprsas_target *target; - struct mprsas_lun *lun; - uint8_t found_lun; - - sassc = sc->sassc; - pathid = cam_sim_path(sassc->sim); - targetid = xpt_path_target_id(path); - lunid = xpt_path_lun_id(path); - - KASSERT(targetid < sassc->maxtargets, - ("Target %d out of bounds in mprsas_prepare_ssu\n", targetid)); - target = &sassc->targets[targetid]; - if (target->handle == 0x0) - return; - - /* - * If LUN is already in list, don't create a new one. - */ - found_lun = FALSE; - SLIST_FOREACH(lun, &target->luns, lun_link) { - if (lun->lun_id == lunid) { - found_lun = TRUE; - break; - } - } - if (!found_lun) { - lun = malloc(sizeof(struct mprsas_lun), M_MPR, - M_NOWAIT | M_ZERO); - if (lun == NULL) { - mpr_dprint(sc, MPR_ERROR, "Unable to alloc LUN for " - "preparing SSU.\n"); - return; - } - lun->lun_id = lunid; - SLIST_INSERT_HEAD(&target->luns, lun, lun_link); - } - - /* - * If this is a SATA direct-access end device, mark it so that a SCSI - * StartStopUnit command will be sent to it when the driver is being - * shutdown. - */ - if (((cgd->inq_data.device & 0x1F) == T_DIRECT) && - (target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) && - ((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) == - MPI2_SAS_DEVICE_INFO_END_DEVICE)) { - lun->stop_at_shutdown = TRUE; - } -} - #if (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) static void @@ -3212,7 +3201,6 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, uint8_t found_lun; char path_str[64]; - sassc = sc->sassc; pathid = cam_sim_path(sassc->sim); targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); @@ -3288,7 +3276,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, rcap_buf = malloc(sizeof(struct scsi_read_capacity_eedp), M_MPR, M_NOWAIT | M_ZERO); if (rcap_buf == NULL) { - mpr_dprint(sc, MPR_FAULT, "Unable to alloc read capacity " + mpr_dprint(sc, MPR_ERROR, "Unable to alloc read capacity " "buffer for EEDP support.\n"); xpt_free_path(ccb->ccb_h.path); xpt_free_ccb(ccb); @@ -3341,7 +3329,7 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) xpt_release_devq(done_ccb->ccb_h.path, /*count*/ 1, /*run_queue*/TRUE); } - + rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; /* @@ -3359,21 +3347,21 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) /* * Got the LUN in the target's LUN list. Fill it in with EEDP - * info. If the READ CAP 16 command had some SCSI error (common + * info. If the READ CAP 16 command had some SCSI error (common * if command is not supported), mark the lun as not supporting * EEDP and set the block size to 0. */ - if (((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) - || (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { + if ((mprsas_get_ccbstatus(done_ccb) != CAM_REQ_CMP) || + (done_ccb->csio.scsi_status != SCSI_STATUS_OK)) { lun->eedp_formatted = FALSE; lun->eedp_block_size = 0; break; } if (rcap_buf->protect & 0x01) { - mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for " - "target ID %d is formatted for EEDP " - "support.\n", done_ccb->ccb_h.target_lun, + mpr_dprint(sassc->sc, MPR_INFO, "LUN %d for target ID " + "%d is formatted for EEDP support.\n", + done_ccb->ccb_h.target_lun, done_ccb->ccb_h.target_id); lun->eedp_formatted = TRUE; lun->eedp_block_size = scsi_4btoul(rcap_buf->length); @@ -3389,6 +3377,34 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) #endif /* (__FreeBSD_version < 901503) || \ ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */ +void +mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm, + struct mprsas_target *target, lun_id_t lun_id) +{ + union ccb *ccb; + path_id_t path_id; + + /* + * Set the INRESET flag for this target so that no I/O will be sent to + * the target until the reset has completed. If an I/O request does + * happen, the devq will be frozen. The CCB holds the path which is + * used to release the devq. The devq is released and the CCB is freed + * when the TM completes. + */ + ccb = xpt_alloc_ccb_nowait(); + if (ccb) { + path_id = cam_sim_path(sc->sassc->sim); + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, + target->tid, lun_id) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + } else { + tm->cm_ccb = ccb; + tm->cm_targ = target; + target->flags |= MPRSAS_TARGET_INRESET; + } + } +} + int mprsas_startup(struct mpr_softc *sc) { @@ -3489,3 +3505,33 @@ mprsas_check_id(struct mprsas_softc *sassc, int id) return (0); } + +void +mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) +{ + struct mprsas_softc *sassc; + struct mprsas_lun *lun, *lun_tmp; + struct mprsas_target *targ; + int i; + + sassc = sc->sassc; + /* + * The number of targets is based on IOC Facts, so free all of + * the allocated LUNs for each target and then the target buffer + * itself. + */ + for (i=0; i< maxtargets; i++) { + targ = &sassc->targets[i]; + SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link, lun_tmp) { + free(lun, M_MPR); + } + } + free(sassc->targets, M_MPR); + + sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, + M_MPR, M_WAITOK|M_ZERO); + if (!sassc->targets) { + panic("%s failed to alloc targets with error %d\n", + __func__, ENOMEM); + } +} |
