Changeset View
Changeset View
Standalone View
Standalone View
mpr_sas.c
/*- | /*- | ||||
* Copyright (c) 2009 Yahoo! Inc. | * Copyright (c) 2009 Yahoo! Inc. | ||||
* Copyright (c) 2011-2015 LSI Corp. | * Copyright (c) 2011-2015 LSI Corp. | ||||
* Copyright (c) 2013-2015 Avago Technologies | * Copyright (c) 2013-2016 Avago Technologies | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | |||||
MALLOC_DEFINE(M_MPRSAS, "MPRSAS", "MPR SAS memory"); | MALLOC_DEFINE(M_MPRSAS, "MPRSAS", "MPR SAS memory"); | ||||
static void mprsas_remove_device(struct mpr_softc *, struct mpr_command *); | static void mprsas_remove_device(struct mpr_softc *, struct mpr_command *); | ||||
static void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *); | static void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *); | ||||
static void mprsas_action(struct cam_sim *sim, union ccb *ccb); | static void mprsas_action(struct cam_sim *sim, union ccb *ccb); | ||||
static void mprsas_poll(struct cam_sim *sim); | static void mprsas_poll(struct cam_sim *sim); | ||||
static void mprsas_scsiio_timeout(void *data); | static void mprsas_scsiio_timeout(void *data); | ||||
static void mprsas_abort_complete(struct mpr_softc *sc, | static void mprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *cm); | ||||
struct mpr_command *cm); | |||||
static void mprsas_action_scsiio(struct mprsas_softc *, union ccb *); | static void mprsas_action_scsiio(struct mprsas_softc *, union ccb *); | ||||
static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); | static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); | ||||
static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); | static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); | ||||
static void mprsas_resetdev_complete(struct mpr_softc *, | static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); | ||||
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); | struct mpr_command *cm); | ||||
static void mprsas_async(void *callback_arg, uint32_t code, | static void mprsas_async(void *callback_arg, uint32_t code, | ||||
struct cam_path *path, void *arg); | struct cam_path *path, void *arg); | ||||
#if (__FreeBSD_version < 901503) || \ | #if (__FreeBSD_version < 901503) || \ | ||||
((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) | ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) | ||||
static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, | static void mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, | ||||
struct ccb_getdev *cgd); | struct ccb_getdev *cgd); | ||||
static void mprsas_read_cap_done(struct cam_periph *periph, | static void mprsas_read_cap_done(struct cam_periph *periph, | ||||
union ccb *done_ccb); | union ccb *done_ccb); | ||||
#endif | #endif | ||||
static int mprsas_send_portenable(struct mpr_softc *sc); | static int mprsas_send_portenable(struct mpr_softc *sc); | ||||
static void mprsas_portenable_complete(struct mpr_softc *sc, | static void mprsas_portenable_complete(struct mpr_softc *sc, | ||||
struct mpr_command *cm); | struct mpr_command *cm); | ||||
#if __FreeBSD_version >= 900026 | #if __FreeBSD_version >= 900026 | ||||
static void mprsas_smpio_complete(struct mpr_softc *sc, | static void mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); | ||||
struct mpr_command *cm); | static void mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, | ||||
static void mprsas_send_smpcmd(struct mprsas_softc *sassc, | uint64_t sasaddr); | ||||
union ccb *ccb, uint64_t sasaddr); | |||||
static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); | static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); | ||||
#endif //FreeBSD_version >= 900026 | #endif //FreeBSD_version >= 900026 | ||||
struct mprsas_target * | struct mprsas_target * | ||||
mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, | mprsas_find_target_by_handle(struct mprsas_softc *sassc, int start, | ||||
uint16_t handle) | uint16_t handle) | ||||
{ | { | ||||
struct mprsas_target *target; | struct mprsas_target *target; | ||||
▲ Show 20 Lines • Show All 903 Lines • ▼ Show 20 Lines | case XPT_GET_TRAN_SETTINGS: | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | ||||
break; | break; | ||||
} | } | ||||
case XPT_CALC_GEOMETRY: | case XPT_CALC_GEOMETRY: | ||||
cam_calc_geometry(&ccb->ccg, /*extended*/1); | cam_calc_geometry(&ccb->ccg, /*extended*/1); | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | ||||
break; | break; | ||||
case XPT_RESET_DEV: | case XPT_RESET_DEV: | ||||
mpr_dprint(sassc->sc, MPR_XINFO, | mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action " | ||||
"mprsas_action XPT_RESET_DEV\n"); | "XPT_RESET_DEV\n"); | ||||
mprsas_action_resetdev(sassc, ccb); | mprsas_action_resetdev(sassc, ccb); | ||||
return; | return; | ||||
case XPT_RESET_BUS: | case XPT_RESET_BUS: | ||||
case XPT_ABORT: | case XPT_ABORT: | ||||
case XPT_TERM_IO: | case XPT_TERM_IO: | ||||
mpr_dprint(sassc->sc, MPR_XINFO, | mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success " | ||||
"mprsas_action faking success for abort or reset\n"); | "for abort or reset\n"); | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | ||||
break; | break; | ||||
case XPT_SCSI_IO: | case XPT_SCSI_IO: | ||||
mprsas_action_scsiio(sassc, ccb); | mprsas_action_scsiio(sassc, ccb); | ||||
return; | return; | ||||
#if __FreeBSD_version >= 900026 | #if __FreeBSD_version >= 900026 | ||||
case XPT_SMP_IO: | case XPT_SMP_IO: | ||||
mprsas_action_smpio(sassc, ccb); | mprsas_action_smpio(sassc, ccb); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | for (i = 1; i < sc->num_reqs; i++) { | ||||
cm->cm_reply = NULL; | cm->cm_reply = NULL; | ||||
completed = 0; | completed = 0; | ||||
if (cm->cm_flags & MPR_CM_FLAGS_POLLED) | if (cm->cm_flags & MPR_CM_FLAGS_POLLED) | ||||
cm->cm_flags |= MPR_CM_FLAGS_COMPLETE; | cm->cm_flags |= MPR_CM_FLAGS_COMPLETE; | ||||
if (cm->cm_complete != NULL) { | if (cm->cm_complete != NULL) { | ||||
mprsas_log_command(cm, MPR_RECOVERY, | mprsas_log_command(cm, MPR_RECOVERY, | ||||
"completing cm %p state %x ccb %p for diag " | "completing cm %p state %x ccb %p for diag reset\n", | ||||
"reset\n", cm, cm->cm_state, cm->cm_ccb); | cm, cm->cm_state, cm->cm_ccb); | ||||
cm->cm_complete(sc, cm); | cm->cm_complete(sc, cm); | ||||
completed = 1; | completed = 1; | ||||
} | } | ||||
if (cm->cm_flags & MPR_CM_FLAGS_WAKEUP) { | if (cm->cm_flags & MPR_CM_FLAGS_WAKEUP) { | ||||
mprsas_log_command(cm, MPR_RECOVERY, | mprsas_log_command(cm, MPR_RECOVERY, | ||||
"waking up cm %p state %x ccb %p for diag reset\n", | "waking up cm %p state %x ccb %p for diag reset\n", | ||||
cm, cm->cm_state, cm->cm_ccb); | cm, cm->cm_state, cm->cm_ccb); | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
mprsas_tm_timeout(void *data) | mprsas_tm_timeout(void *data) | ||||
{ | { | ||||
struct mpr_command *tm = data; | struct mpr_command *tm = data; | ||||
struct mpr_softc *sc = tm->cm_sc; | struct mpr_softc *sc = tm->cm_sc; | ||||
mtx_assert(&sc->mpr_mtx, MA_OWNED); | mtx_assert(&sc->mpr_mtx, MA_OWNED); | ||||
mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, | mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, "task mgmt %p timed " | ||||
"task mgmt %p timed out\n", tm); | "out\n", tm); | ||||
mpr_reinit(sc); | mpr_reinit(sc); | ||||
} | } | ||||
static void | static void | ||||
mprsas_logical_unit_reset_complete(struct mpr_softc *sc, | mprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) | ||||
struct mpr_command *tm) | |||||
{ | { | ||||
MPI2_SCSI_TASK_MANAGE_REPLY *reply; | MPI2_SCSI_TASK_MANAGE_REPLY *reply; | ||||
MPI2_SCSI_TASK_MANAGE_REQUEST *req; | MPI2_SCSI_TASK_MANAGE_REQUEST *req; | ||||
unsigned int cm_count = 0; | unsigned int cm_count = 0; | ||||
struct mpr_command *cm; | struct mpr_command *cm; | ||||
struct mprsas_target *targ; | struct mprsas_target *targ; | ||||
callout_stop(&tm->cm_callout); | callout_stop(&tm->cm_callout); | ||||
Show All 10 Lines | mprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) | ||||
if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { | if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { | ||||
mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for LUN reset! " | mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for LUN reset! " | ||||
"This should not happen!\n", __func__, tm->cm_flags); | "This should not happen!\n", __func__, tm->cm_flags); | ||||
mprsas_free_tm(sc, tm); | mprsas_free_tm(sc, tm); | ||||
return; | return; | ||||
} | } | ||||
if (reply == NULL) { | if (reply == NULL) { | ||||
mprsas_log_command(tm, MPR_RECOVERY, | mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " | ||||
"NULL reset reply for tm %p\n", tm); | "%p\n", tm); | ||||
if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { | if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { | ||||
/* this completion was due to a reset, just cleanup */ | /* this completion was due to a reset, just cleanup */ | ||||
targ->tm = NULL; | targ->tm = NULL; | ||||
mprsas_free_tm(sc, tm); | mprsas_free_tm(sc, tm); | ||||
} | } | ||||
else { | else { | ||||
/* we should have gotten a reply. */ | /* we should have gotten a reply. */ | ||||
mpr_reinit(sc); | mpr_reinit(sc); | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) | ||||
if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { | if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { | ||||
mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " | mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for target " | ||||
"reset! This should not happen!\n", __func__, tm->cm_flags); | "reset! This should not happen!\n", __func__, tm->cm_flags); | ||||
mprsas_free_tm(sc, tm); | mprsas_free_tm(sc, tm); | ||||
return; | return; | ||||
} | } | ||||
if (reply == NULL) { | if (reply == NULL) { | ||||
mprsas_log_command(tm, MPR_RECOVERY, | mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " | ||||
"NULL reset reply for tm %p\n", tm); | "%p\n", tm); | ||||
if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { | if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { | ||||
/* this completion was due to a reset, just cleanup */ | /* this completion was due to a reset, just cleanup */ | ||||
targ->tm = NULL; | targ->tm = NULL; | ||||
mprsas_free_tm(sc, tm); | mprsas_free_tm(sc, tm); | ||||
} | } | ||||
else { | else { | ||||
/* we should have gotten a reply. */ | /* we should have gotten a reply. */ | ||||
mpr_reinit(sc); | mpr_reinit(sc); | ||||
▲ Show 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | mprsas_scsiio_timeout(void *data) | ||||
if (cm->cm_ccb == NULL) { | if (cm->cm_ccb == NULL) { | ||||
mpr_dprint(sc, MPR_ERROR, "command timeout with NULL ccb\n"); | mpr_dprint(sc, MPR_ERROR, "command timeout with NULL ccb\n"); | ||||
return; | return; | ||||
} | } | ||||
targ = cm->cm_targ; | targ = cm->cm_targ; | ||||
targ->timeouts++; | targ->timeouts++; | ||||
mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " | mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p target " | ||||
"target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, | "%u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); | ||||
targ->handle); | |||||
if (targ->encl_level_valid) { | if (targ->encl_level_valid) { | ||||
mpr_dprint(sc, MPR_ERROR, "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, | "connector name (%4s)\n", targ->encl_level, targ->encl_slot, | ||||
targ->connector_name); | targ->connector_name); | ||||
} | } | ||||
/* XXX first, check the firmware state, to see if it's still | /* XXX first, check the firmware state, to see if it's still | ||||
* operational. if not, do a diag reset. | * operational. if not, do a diag reset. | ||||
Show All 21 Lines | else { | ||||
* available. The firmware only has a limited number of | * available. The firmware only has a limited number of | ||||
* HighPriority credits for the high priority requests used | * HighPriority credits for the high priority requests used | ||||
* for task management, and we ran out. | * for task management, and we ran out. | ||||
* | * | ||||
* Isilon: don't worry about this for now, since we have | * Isilon: don't worry about this for now, since we have | ||||
* more credits than disks in an enclosure, and limit | * more credits than disks in an enclosure, and limit | ||||
* ourselves to one TM per target for recovery. | * ourselves to one TM per target for recovery. | ||||
*/ | */ | ||||
mpr_dprint(sc, MPR_RECOVERY, | mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p failed to " | ||||
"timedout cm %p failed to allocate a tm\n", cm); | "allocate a tm\n", cm); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) | mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) | ||||
{ | { | ||||
MPI2_SCSI_IO_REQUEST *req; | MPI2_SCSI_IO_REQUEST *req; | ||||
struct ccb_scsiio *csio; | struct ccb_scsiio *csio; | ||||
▲ Show 20 Lines • Show All 894 Lines • ▼ Show 20 Lines | bailout: | ||||
bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, | bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, | ||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | ||||
bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); | bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap); | ||||
mpr_free_command(sc, cm); | mpr_free_command(sc, cm); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
} | } | ||||
static void | static void | ||||
mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, | mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, uint64_t sasaddr) | ||||
uint64_t sasaddr) | |||||
{ | { | ||||
struct mpr_command *cm; | struct mpr_command *cm; | ||||
uint8_t *request, *response; | uint8_t *request, *response; | ||||
MPI2_SMP_PASSTHROUGH_REQUEST *req; | MPI2_SMP_PASSTHROUGH_REQUEST *req; | ||||
struct mpr_softc *sc; | struct mpr_softc *sc; | ||||
struct sglist *sg; | struct sglist *sg; | ||||
int error; | int error; | ||||
Show All 16 Lines | case CAM_DATA_SG_PADDR: | ||||
return; | return; | ||||
case CAM_DATA_SG: | case CAM_DATA_SG: | ||||
/* | /* | ||||
* The chip does not support more than one buffer for the | * The chip does not support more than one buffer for the | ||||
* request or response. | * request or response. | ||||
*/ | */ | ||||
if ((ccb->smpio.smp_request_sglist_cnt > 1) | if ((ccb->smpio.smp_request_sglist_cnt > 1) | ||||
|| (ccb->smpio.smp_response_sglist_cnt > 1)) { | || (ccb->smpio.smp_response_sglist_cnt > 1)) { | ||||
mpr_dprint(sc, MPR_ERROR, | mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " | ||||
"%s: multiple request or response buffer segments " | "response buffer segments not supported for SMP\n", | ||||
"not supported for SMP\n", __func__); | __func__); | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); | mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* The CAM_SCATTER_VALID flag was originally implemented | * The CAM_SCATTER_VALID flag was originally implemented | ||||
* for the XPT_SCSI_IO CCB, which only has one data pointer. | * for the XPT_SCSI_IO CCB, which only has one data pointer. | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | #else /* __FreeBSD_version < 1000028 */ | ||||
} else { | } else { | ||||
request = ccb->smpio.smp_request; | request = ccb->smpio.smp_request; | ||||
response = ccb->smpio.smp_response; | response = ccb->smpio.smp_response; | ||||
} | } | ||||
#endif /* __FreeBSD_version < 1000028 */ | #endif /* __FreeBSD_version < 1000028 */ | ||||
cm = mpr_alloc_command(sc); | cm = mpr_alloc_command(sc); | ||||
if (cm == NULL) { | if (cm == NULL) { | ||||
mpr_dprint(sc, MPR_ERROR, | mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", | ||||
"%s: cannot allocate command\n", __func__); | __func__); | ||||
mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); | mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; | req = (MPI2_SMP_PASSTHROUGH_REQUEST *)cm->cm_req; | ||||
bzero(req, sizeof(*req)); | bzero(req, sizeof(*req)); | ||||
req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | req->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | ||||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) | ||||
MPI2_SCSI_TASK_MANAGE_REQUEST *req; | MPI2_SCSI_TASK_MANAGE_REQUEST *req; | ||||
struct mpr_softc *sc; | struct mpr_softc *sc; | ||||
struct mpr_command *tm; | struct mpr_command *tm; | ||||
struct mprsas_target *targ; | struct mprsas_target *targ; | ||||
MPR_FUNCTRACE(sassc->sc); | MPR_FUNCTRACE(sassc->sc); | ||||
mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); | mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); | ||||
KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, | KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out of " | ||||
("Target %d out of bounds in XPT_RESET_DEV\n", | "bounds in XPT_RESET_DEV\n", ccb->ccb_h.target_id)); | ||||
ccb->ccb_h.target_id)); | |||||
sc = sassc->sc; | sc = sassc->sc; | ||||
tm = mpr_alloc_command(sc); | tm = mpr_alloc_command(sc); | ||||
if (tm == NULL) { | if (tm == NULL) { | ||||
mpr_dprint(sc, MPR_ERROR, | mpr_dprint(sc, MPR_ERROR, "command alloc failure in " | ||||
"command alloc failure in mprsas_action_resetdev\n"); | "mprsas_action_resetdev\n"); | ||||
mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); | mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
return; | return; | ||||
} | } | ||||
targ = &sassc->targets[ccb->ccb_h.target_id]; | targ = &sassc->targets[ccb->ccb_h.target_id]; | ||||
req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; | req = (MPI2_SCSI_TASK_MANAGE_REQUEST *)tm->cm_req; | ||||
req->DevHandle = htole16(targ->handle); | req->DevHandle = htole16(targ->handle); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | if ((tm->cm_flags & MPR_CM_FLAGS_ERROR_MASK) != 0) { | ||||
mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " | mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for reset of " | ||||
"handle %#04x! This should not happen!\n", __func__, | "handle %#04x! This should not happen!\n", __func__, | ||||
tm->cm_flags, req->DevHandle); | tm->cm_flags, req->DevHandle); | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); | ||||
goto bailout; | goto bailout; | ||||
} | } | ||||
mpr_dprint(sc, MPR_XINFO, | mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", | ||||
"%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, | __func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); | ||||
le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); | |||||
if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { | if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); | ||||
mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, | mprsas_announce_reset(sc, AC_SENT_BDR, tm->cm_targ->tid, | ||||
CAM_LUN_WILDCARD); | CAM_LUN_WILDCARD); | ||||
} | } | ||||
else | else | ||||
mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); | mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, | ||||
struct mprsas_lun *lun; | struct mprsas_lun *lun; | ||||
uint8_t found_lun; | uint8_t found_lun; | ||||
char path_str[64]; | char path_str[64]; | ||||
pathid = cam_sim_path(sassc->sim); | pathid = cam_sim_path(sassc->sim); | ||||
targetid = xpt_path_target_id(path); | targetid = xpt_path_target_id(path); | ||||
lunid = xpt_path_lun_id(path); | lunid = xpt_path_lun_id(path); | ||||
KASSERT(targetid < sassc->maxtargets, | KASSERT(targetid < sassc->maxtargets, ("Target %d out of bounds in " | ||||
("Target %d out of bounds in mprsas_check_eedp\n", targetid)); | "mprsas_check_eedp\n", targetid)); | ||||
target = &sassc->targets[targetid]; | target = &sassc->targets[targetid]; | ||||
if (target->handle == 0x0) | if (target->handle == 0x0) | ||||
return; | return; | ||||
/* | /* | ||||
* Determine if the device is EEDP capable. | * Determine if the device is EEDP capable. | ||||
* | * | ||||
* If this flag is set in the inquiry data, the device supports | * If this flag is set in the inquiry data, the device supports | ||||
* protection information, and must support the 16 byte read capacity | * protection information, and must support the 16 byte read capacity | ||||
* command, otherwise continue without sending read cap 16 | * command, otherwise continue without sending read cap 16. | ||||
*/ | */ | ||||
if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) | if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) | ||||
return; | return; | ||||
/* | /* | ||||
* Issue a READ CAPACITY 16 command. This info is used to determine if | * Issue a READ CAPACITY 16 command. This info is used to determine if | ||||
* the LUN is formatted for EEDP support. | * the LUN is formatted for EEDP support. | ||||
*/ | */ | ||||
ccb = xpt_alloc_ccb_nowait(); | ccb = xpt_alloc_ccb_nowait(); | ||||
if (ccb == NULL) { | if (ccb == NULL) { | ||||
mpr_dprint(sc, MPR_ERROR, "Unable to alloc CCB for EEDP " | mpr_dprint(sc, MPR_ERROR, "Unable to alloc CCB for EEDP " | ||||
"support.\n"); | "support.\n"); | ||||
return; | return; | ||||
} | } | ||||
if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) | if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) != | ||||
!= CAM_REQ_CMP) { | CAM_REQ_CMP) { | ||||
mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP " | mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP " | ||||
"support\n"); | "support.\n"); | ||||
xpt_free_ccb(ccb); | xpt_free_ccb(ccb); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* If LUN is already in list, don't create a new one. | * If LUN is already in list, don't create a new one. | ||||
*/ | */ | ||||
found_lun = FALSE; | found_lun = FALSE; | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) | ||||
rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; | rcap_buf = (struct scsi_read_capacity_eedp *)done_ccb->csio.data_ptr; | ||||
/* | /* | ||||
* Get the LUN ID for the path and look it up in the LUN list for the | * Get the LUN ID for the path and look it up in the LUN list for the | ||||
* target. | * target. | ||||
*/ | */ | ||||
sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; | sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; | ||||
KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, | KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out " | ||||
("Target %d out of bounds in mprsas_read_cap_done\n", | "of bounds in mprsas_read_cap_done\n", done_ccb->ccb_h.target_id)); | ||||
done_ccb->ccb_h.target_id)); | |||||
target = &sassc->targets[done_ccb->ccb_h.target_id]; | target = &sassc->targets[done_ccb->ccb_h.target_id]; | ||||
SLIST_FOREACH(lun, &target->luns, lun_link) { | SLIST_FOREACH(lun, &target->luns, lun_link) { | ||||
if (lun->lun_id != done_ccb->ccb_h.target_lun) | if (lun->lun_id != done_ccb->ccb_h.target_lun) | ||||
continue; | continue; | ||||
/* | /* | ||||
* Got the LUN in the target's LUN list. Fill it in with EEDP | * 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 | ||||
▲ Show 20 Lines • Show All 187 Lines • Show Last 20 Lines |