summaryrefslogtreecommitdiff
path: root/sys/dev/mpr/mpr_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mpr/mpr_sas.c')
-rw-r--r--sys/dev/mpr/mpr_sas.c476
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);
+ }
+}