Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mps/mps_sas.c
Show First 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | mpssas_alloc_tm(struct mps_softc *sc) | ||||
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; | req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; | ||||
req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | req->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||||
return tm; | return tm; | ||||
} | } | ||||
void | void | ||||
mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm) | mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm) | ||||
{ | { | ||||
int target_id = 0xFFFFFFFF; | |||||
if (tm == NULL) | if (tm == NULL) | ||||
return; | return; | ||||
/* | /* | ||||
* For TM's the devq is frozen for the device. Unfreeze it here and | * 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 | * free the resources used for freezing the devq. Must clear the | ||||
* INRESET flag as well or scsi I/O will not work. | * INRESET flag as well or scsi I/O will not work. | ||||
*/ | */ | ||||
if (tm->cm_targ != NULL) { | |||||
tm->cm_targ->flags &= ~MPSSAS_TARGET_INRESET; | |||||
target_id = tm->cm_targ->tid; | |||||
} | |||||
if (tm->cm_ccb) { | if (tm->cm_ccb) { | ||||
mps_dprint(sc, MPS_INFO, "Unfreezing devq for target ID %d\n", | mps_dprint(sc, MPS_XINFO | MPS_RECOVERY, | ||||
target_id); | "Unfreezing devq for target ID %d\n", | ||||
tm->cm_targ->tid); | |||||
tm->cm_targ->flags &= ~MPSSAS_TARGET_INRESET; | |||||
xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); | xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); | ||||
xpt_free_path(tm->cm_ccb->ccb_h.path); | xpt_free_path(tm->cm_ccb->ccb_h.path); | ||||
xpt_free_ccb(tm->cm_ccb); | xpt_free_ccb(tm->cm_ccb); | ||||
} | } | ||||
mps_free_high_priority_command(sc, tm); | mps_free_high_priority_command(sc, tm); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,431 Lines • ▼ Show 20 Lines | mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb) | ||||
if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) { | if ((sc->mps_flags & MPS_FLAGS_SHUTDOWN) != 0) { | ||||
mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__); | mps_dprint(sc, MPS_INFO, "%s shutting down\n", __func__); | ||||
mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); | mpssas_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* If target has a reset in progress, freeze the devq and return. The | * If target has a reset in progress, the devq should be frozen. | ||||
* devq will be released when the TM reset is finished. | * Geting here we likely hit a race, so just requeue. | ||||
*/ | */ | ||||
if (targ->flags & MPSSAS_TARGET_INRESET) { | if (targ->flags & MPSSAS_TARGET_INRESET) { | ||||
ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN; | ccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_DEV_QFRZN; | ||||
mps_dprint(sc, MPS_INFO, "%s: Freezing devq for target ID %d\n", | mps_dprint(sc, MPS_INFO, "%s: Freezing devq for target ID %d\n", | ||||
__func__, targ->tid); | __func__, targ->tid); | ||||
xpt_freeze_devq(ccb->ccb_h.path, 1); | xpt_freeze_devq(ccb->ccb_h.path, 1); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
cm = mps_alloc_command(sc); | cm = mps_alloc_command(sc); | ||||
▲ Show 20 Lines • Show All 1,524 Lines • ▼ Show 20 Lines | mpssas_async(void *callback_arg, uint32_t code, struct cam_path *path, | ||||
} | } | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
mps_unlock(sc); | mps_unlock(sc); | ||||
} | } | ||||
/* | /* | ||||
* Set the INRESET flag for this target so that no I/O will be sent to | * Freeze the devq and set the INRESET flag so that no I/O will be sent to | ||||
* the target until the reset has completed. If an I/O request does | * the target until the reset has completed. The CCB holds the path which | ||||
* happen, the devq will be frozen. The CCB holds the path which is | * is used to release the devq. The devq is released and the CCB is freed | ||||
* used to release the devq. The devq is released and the CCB is freed | |||||
* when the TM completes. | * when the TM completes. | ||||
* We only need to do this when we're entering reset, not at each time we | |||||
* need to send an abort (which will happen if multiple commands timeout | |||||
* while we're sending the abort). We do not release the queue for each | |||||
* command we complete (just at the end when we free the tm), so freezing | |||||
* it each time doesn't make sense. | |||||
*/ | */ | ||||
void | void | ||||
mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm, | mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm, | ||||
struct mpssas_target *target, lun_id_t lun_id) | struct mpssas_target *target, lun_id_t lun_id) | ||||
{ | { | ||||
union ccb *ccb; | union ccb *ccb; | ||||
path_id_t path_id; | path_id_t path_id; | ||||
ccb = xpt_alloc_ccb_nowait(); | ccb = xpt_alloc_ccb_nowait(); | ||||
if (ccb) { | if (ccb) { | ||||
path_id = cam_sim_path(sc->sassc->sim); | path_id = cam_sim_path(sc->sassc->sim); | ||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, | if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id, | ||||
target->tid, lun_id) != CAM_REQ_CMP) { | target->tid, lun_id) != CAM_REQ_CMP) { | ||||
xpt_free_ccb(ccb); | xpt_free_ccb(ccb); | ||||
} else { | } else { | ||||
tm->cm_ccb = ccb; | tm->cm_ccb = ccb; | ||||
tm->cm_targ = target; | tm->cm_targ = target; | ||||
if ((target->flags & MPSSAS_TARGET_INRESET) == 0) { | |||||
mps_dprint(sc, MPS_XINFO | MPS_RECOVERY, | |||||
"%s: Freezing devq for target ID %d\n", | |||||
__func__, target->tid); | |||||
xpt_freeze_devq(ccb->ccb_h.path, 1); | |||||
target->flags |= MPSSAS_TARGET_INRESET; | target->flags |= MPSSAS_TARGET_INRESET; | ||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
int | int | ||||
mpssas_startup(struct mps_softc *sc) | mpssas_startup(struct mps_softc *sc) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 129 Lines • Show Last 20 Lines |