Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ocs_fc/ocs_cam.c
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
static int32_t ocs_target_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); | static int32_t ocs_target_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); | ||||
static int32_t ocs_io_abort_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); | static int32_t ocs_io_abort_cb(ocs_io_t *, ocs_scsi_io_status_e, uint32_t, void *); | ||||
static int32_t ocs_task_set_full_or_busy(ocs_io_t *io); | static int32_t ocs_task_set_full_or_busy(ocs_io_t *io); | ||||
static int32_t ocs_initiator_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, | static int32_t ocs_initiator_tmf_cb(ocs_io_t *, ocs_scsi_io_status_e, | ||||
ocs_scsi_cmd_resp_t *, uint32_t, void *); | ocs_scsi_cmd_resp_t *, uint32_t, void *); | ||||
static uint32_t | static uint32_t | ||||
ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role); | ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role); | ||||
static void ocs_ldt(void *arg); | |||||
static void ocs_ldt_task(void *arg, int pending); | |||||
static void ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt); | |||||
uint32_t ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp); | |||||
uint32_t ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id); | |||||
int32_t ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node); | |||||
static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag) | static inline ocs_io_t *ocs_scsi_find_io(struct ocs_softc *ocs, uint32_t tag) | ||||
{ | { | ||||
return ocs_io_get_instance(ocs, tag); | return ocs_io_get_instance(ocs, tag); | ||||
} | } | ||||
static inline void ocs_target_io_free(ocs_io_t *io) | static inline void ocs_target_io_free(ocs_io_t *io) | ||||
{ | { | ||||
Show All 34 Lines | ocs_attach_port(ocs_t *ocs, int chan) | ||||
if (CAM_REQ_CMP != xpt_create_path(&path, NULL, cam_sim_path(sim), | if (CAM_REQ_CMP != xpt_create_path(&path, NULL, cam_sim_path(sim), | ||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)) { | CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)) { | ||||
device_printf(ocs->dev, "Can't create path\n"); | device_printf(ocs->dev, "Can't create path\n"); | ||||
xpt_bus_deregister(cam_sim_path(sim)); | xpt_bus_deregister(cam_sim_path(sim)); | ||||
mtx_unlock(&ocs->sim_lock); | mtx_unlock(&ocs->sim_lock); | ||||
cam_sim_free(sim, FALSE); | cam_sim_free(sim, FALSE); | ||||
return 1; | return 1; | ||||
} | } | ||||
fcp->ocs = ocs; | |||||
fcp->sim = sim; | fcp->sim = sim; | ||||
fcp->path = path; | fcp->path = path; | ||||
return 0; | callout_init_mtx(&fcp->ldt, &ocs->sim_lock, 0); | ||||
TASK_INIT(&fcp->ltask, 1, ocs_ldt_task, fcp); | |||||
return 0; | |||||
} | } | ||||
static int32_t | static int32_t | ||||
ocs_detach_port(ocs_t *ocs, int32_t chan) | ocs_detach_port(ocs_t *ocs, int32_t chan) | ||||
{ | { | ||||
ocs_fcport *fcp = NULL; | ocs_fcport *fcp = NULL; | ||||
struct cam_sim *sim = NULL; | struct cam_sim *sim = NULL; | ||||
struct cam_path *path = NULL; | struct cam_path *path = NULL; | ||||
fcp = FCPORT(ocs, chan); | fcp = FCPORT(ocs, chan); | ||||
sim = fcp->sim; | sim = fcp->sim; | ||||
path = fcp->path; | path = fcp->path; | ||||
callout_drain(&fcp->ldt); | |||||
ocs_ldt_task(fcp, 0); | |||||
if (fcp->sim) { | if (fcp->sim) { | ||||
mtx_lock(&ocs->sim_lock); | mtx_lock(&ocs->sim_lock); | ||||
ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard); | ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard); | ||||
if (path) { | if (path) { | ||||
xpt_async(AC_LOST_DEVICE, path, NULL); | xpt_async(AC_LOST_DEVICE, path, NULL); | ||||
xpt_free_path(path); | xpt_free_path(path); | ||||
fcp->path = NULL; | fcp->path = NULL; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 513 Lines • ▼ Show 20 Lines | int32_t ocs_scsi_recv_tmf(ocs_io_t *tmfio, uint64_t lun, ocs_scsi_tmf_cmd_e cmd, | ||||
device_printf(tmfio->ocs->dev, "%s: io=%p cmd=%#x LU=%lx en=%s\n", | device_printf(tmfio->ocs->dev, "%s: io=%p cmd=%#x LU=%lx en=%s\n", | ||||
__func__, tmfio, cmd, (unsigned long)lun, | __func__, tmfio, cmd, (unsigned long)lun, | ||||
trsrc ? (trsrc->enabled ? "T" : "F") : "X"); | trsrc ? (trsrc->enabled ? "T" : "F") : "X"); | ||||
if (trsrc) { | if (trsrc) { | ||||
inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot); | inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot); | ||||
} | } | ||||
if (!inot) { | if (!inot) { | ||||
device_printf( | device_printf( | ||||
ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n", | ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n", | ||||
__func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X", | __func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X", | ||||
be16toh(tmfio->init_task_tag)); | be16toh(tmfio->init_task_tag)); | ||||
if (abortio) { | if (abortio) { | ||||
ocs_scsi_io_complete(abortio); | ocs_scsi_io_complete(abortio); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | if ((fcp->role != KNOB_ROLE_NONE)) { | ||||
} | } | ||||
ocs_sport_vport_alloc(ocs->domain, fcp->vport); | ocs_sport_vport_alloc(ocs->domain, fcp->vport); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
int32_t | |||||
ocs_tgt_find(ocs_fcport *fcp, ocs_node_t *node) | |||||
{ | |||||
ocs_fc_target_t *tgt = NULL; | |||||
uint32_t i; | |||||
for (i = 0; i < OCS_MAX_TARGETS; i++) { | |||||
tgt = &fcp->tgt[i]; | |||||
if (tgt->state == OCS_TGT_STATE_NONE) | |||||
continue; | |||||
if (ocs_node_get_wwpn(node) == tgt->wwpn) { | |||||
return i; | |||||
} | |||||
} | |||||
return -1; | |||||
} | |||||
/** | /** | ||||
* @ingroup scsi_api_initiator | * @ingroup scsi_api_initiator | ||||
* @brief receive notification of a new SCSI target node | * @brief receive notification of a new SCSI target node | ||||
* | * | ||||
* Sent by base driver to notify an initiator-client of the presense of a new | * Sent by base driver to notify an initiator-client of the presense of a new | ||||
* remote target. The initiator-server may use this call to prepare for | * remote target. The initiator-server may use this call to prepare for | ||||
* inbound IO from this node. | * inbound IO from this node. | ||||
* | * | ||||
* This function is only called if the base driver is enabled for | * This function is only called if the base driver is enabled for | ||||
* initiator capability. | * initiator capability. | ||||
* | * | ||||
* @param node pointer to new remote initiator node | * @param node pointer to new remote initiator node | ||||
* | * | ||||
* @return none | * @return none | ||||
* | * | ||||
* @note | * @note | ||||
*/ | */ | ||||
int32_t | |||||
ocs_scsi_new_target(ocs_node_t *node) | uint32_t | ||||
ocs_update_tgt(ocs_node_t *node, ocs_fcport *fcp, uint32_t tgt_id) | |||||
{ | { | ||||
struct ocs_softc *ocs = node->ocs; | ocs_fc_target_t *tgt = NULL; | ||||
union ccb *ccb = NULL; | |||||
ocs_fcport *fcp = NULL; | |||||
fcp = node->sport->tgt_data; | tgt = &fcp->tgt[tgt_id]; | ||||
if (fcp == NULL) { | |||||
printf("%s:FCP is NULL \n", __func__); | tgt->node_id = node->instance_index; | ||||
tgt->state = OCS_TGT_STATE_VALID; | |||||
tgt->port_id = node->rnode.fc_id; | |||||
tgt->wwpn = ocs_node_get_wwpn(node); | |||||
tgt->wwnn = ocs_node_get_wwnn(node); | |||||
return 0; | return 0; | ||||
} | } | ||||
uint32_t | |||||
ocs_add_new_tgt(ocs_node_t *node, ocs_fcport *fcp) | |||||
{ | |||||
uint32_t i; | |||||
struct ocs_softc *ocs = node->ocs; | |||||
union ccb *ccb = NULL; | |||||
for (i = 0; i < OCS_MAX_TARGETS; i++) { | |||||
if (fcp->tgt[i].state == OCS_TGT_STATE_NONE) | |||||
break; | |||||
} | |||||
if (NULL == (ccb = xpt_alloc_ccb_nowait())) { | if (NULL == (ccb = xpt_alloc_ccb_nowait())) { | ||||
device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__); | device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__); | ||||
return -1; | return -1; | ||||
} | } | ||||
if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph, | if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph, | ||||
cam_sim_path(fcp->sim), | cam_sim_path(fcp->sim), | ||||
node->instance_index, CAM_LUN_WILDCARD)) { | i, CAM_LUN_WILDCARD)) { | ||||
device_printf( | device_printf( | ||||
ocs->dev, "%s: target path creation failed\n", __func__); | ocs->dev, "%s: target path creation failed\n", __func__); | ||||
xpt_free_ccb(ccb); | xpt_free_ccb(ccb); | ||||
return -1; | return -1; | ||||
} | } | ||||
ocs_update_tgt(node, fcp, i); | |||||
xpt_rescan(ccb); | xpt_rescan(ccb); | ||||
return 0; | |||||
} | |||||
int32_t | |||||
ocs_scsi_new_target(ocs_node_t *node) | |||||
{ | |||||
ocs_fcport *fcp = NULL; | |||||
int32_t i; | |||||
fcp = node->sport->tgt_data; | |||||
if (fcp == NULL) { | |||||
printf("%s:FCP is NULL \n", __func__); | |||||
return 0; | return 0; | ||||
} | } | ||||
i = ocs_tgt_find(fcp, node); | |||||
if (i < 0) { | |||||
ocs_add_new_tgt(node, fcp); | |||||
return 0; | |||||
} | |||||
ocs_update_tgt(node, fcp, i); | |||||
return 0; | |||||
} | |||||
static void | |||||
ocs_delete_target(ocs_t *ocs, ocs_fcport *fcp, int tgt) | |||||
{ | |||||
struct cam_path *cpath = NULL; | |||||
if (!fcp->sim) { | |||||
device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__); | |||||
return; | |||||
} | |||||
if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim), | |||||
tgt, CAM_LUN_WILDCARD)) { | |||||
xpt_async(AC_LOST_DEVICE, cpath, NULL); | |||||
xpt_free_path(cpath); | |||||
} | |||||
} | |||||
/* | |||||
* Device Lost Timer Function- when we have decided that a device was lost, | |||||
* we wait a specific period of time prior to telling the OS about lost device. | |||||
* | |||||
* This timer function gets activated when the device was lost. | |||||
* This function fires once a second and then scans the port database | |||||
* for devices that are marked dead but still have a virtual target assigned. | |||||
* We decrement a counter for that port database entry, and when it hits zero, | |||||
ken: This comment makes it sound like the timer is active all the time. I had to look at the code… | |||||
* we tell the OS the device was lost. Timer will be stopped when the device | |||||
* comes back active or removed from the OS. | |||||
*/ | |||||
static void | |||||
ocs_ldt(void *arg) | |||||
{ | |||||
ocs_fcport *fcp = arg; | |||||
taskqueue_enqueue(taskqueue_thread, &fcp->ltask); | |||||
} | |||||
static void | |||||
ocs_ldt_task(void *arg, int pending) | |||||
{ | |||||
ocs_fcport *fcp = arg; | |||||
ocs_t *ocs = fcp->ocs; | |||||
int i, more_to_do = 0; | |||||
ocs_fc_target_t *tgt = NULL; | |||||
for (i = 0; i < OCS_MAX_TARGETS; i++) { | |||||
tgt = &fcp->tgt[i]; | |||||
if (tgt->state != OCS_TGT_STATE_LOST) { | |||||
continue; | |||||
} | |||||
if ((tgt->gone_timer != 0) && (ocs->attached)){ | |||||
tgt->gone_timer -= 1; | |||||
more_to_do++; | |||||
continue; | |||||
} | |||||
if (tgt->is_target) { | |||||
tgt->is_target = 0; | |||||
ocs_delete_target(ocs, fcp, i); | |||||
} | |||||
tgt->state = OCS_TGT_STATE_NONE; | |||||
} | |||||
if (more_to_do) { | |||||
callout_reset(&fcp->ldt, hz, ocs_ldt, fcp); | |||||
} else { | |||||
callout_deactivate(&fcp->ldt); | |||||
} | |||||
} | |||||
/** | /** | ||||
* @ingroup scsi_api_initiator | * @ingroup scsi_api_initiator | ||||
* @brief Delete a SCSI target node | * @brief Delete a SCSI target node | ||||
* | * | ||||
* Sent by base driver to notify a initiator-client that a remote target | * Sent by base driver to notify a initiator-client that a remote target | ||||
* is now gone. The base driver will have terminated all outstanding IOs | * is now gone. The base driver will have terminated all outstanding IOs | ||||
* and the initiator-client will receive appropriate completions. | * and the initiator-client will receive appropriate completions. | ||||
* | * | ||||
Show All 11 Lines | |||||
* completion and OCS_SCSI_CALL_COMPLETE if call completed or error. | * completion and OCS_SCSI_CALL_COMPLETE if call completed or error. | ||||
* | * | ||||
* @note | * @note | ||||
*/ | */ | ||||
int32_t | int32_t | ||||
ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason) | ocs_scsi_del_target(ocs_node_t *node, ocs_scsi_del_target_reason_e reason) | ||||
{ | { | ||||
struct ocs_softc *ocs = node->ocs; | struct ocs_softc *ocs = node->ocs; | ||||
struct cam_path *cpath = NULL; | |||||
ocs_fcport *fcp = NULL; | ocs_fcport *fcp = NULL; | ||||
ocs_fc_target_t *tgt = NULL; | |||||
uint32_t tgt_id; | |||||
fcp = node->sport->tgt_data; | fcp = node->sport->tgt_data; | ||||
if (fcp == NULL) { | if (fcp == NULL) { | ||||
ocs_log_err(ocs,"FCP is NULL \n"); | ocs_log_err(ocs,"FCP is NULL \n"); | ||||
return 0; | return 0; | ||||
} | } | ||||
if (!fcp->sim) { | tgt_id = ocs_tgt_find(fcp, node); | ||||
device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__); | |||||
return OCS_SCSI_CALL_COMPLETE; | |||||
} | |||||
if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim), | tgt = &fcp->tgt[tgt_id]; | ||||
node->instance_index, CAM_LUN_WILDCARD)) { | |||||
xpt_async(AC_LOST_DEVICE, cpath, NULL); | |||||
xpt_free_path(cpath); | // IF in shutdown delete target. | ||||
if(!ocs->attached) { | |||||
ocs_delete_target(ocs, fcp, tgt_id); | |||||
} else { | |||||
tgt->state = OCS_TGT_STATE_LOST; | |||||
tgt->gone_timer = 30; | |||||
if (!callout_active(&fcp->ldt)) { | |||||
callout_reset(&fcp->ldt, hz, ocs_ldt, fcp); | |||||
} | } | ||||
return OCS_SCSI_CALL_COMPLETE; | |||||
} | } | ||||
return 0; | |||||
} | |||||
/** | /** | ||||
* @brief Initialize SCSI IO | * @brief Initialize SCSI IO | ||||
* | * | ||||
* Initialize SCSI IO, this function is called once per IO during IO pool | * Initialize SCSI IO, this function is called once per IO during IO pool | ||||
* allocation so that the target server may initialize any of its own private | * allocation so that the target server may initialize any of its own private | ||||
* data. | * data. | ||||
* | * | ||||
* @param io pointer to SCSI IO object | * @param io pointer to SCSI IO object | ||||
▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | if ((rsp->sense_data_length) && | ||||
} else { | } else { | ||||
csio->sense_resid = 0; | csio->sense_resid = 0; | ||||
sense_len = csio->sense_len; | sense_len = csio->sense_len; | ||||
} | } | ||||
ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len); | ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len); | ||||
} | } | ||||
} else if (scsi_status != OCS_SCSI_STATUS_GOOD) { | } else if (scsi_status != OCS_SCSI_STATUS_GOOD) { | ||||
ccb_status = CAM_REQ_CMP_ERR; | ccb_status = CAM_REQ_CMP_ERR; | ||||
ocs_set_ccb_status(ccb, ccb_status); | |||||
csio->ccb_h.status |= CAM_DEV_QFRZN; | |||||
Done Inline ActionsLooks like you've got an extra space in there. ken: Looks like you've got an extra space in there. | |||||
xpt_freeze_devq(csio->ccb_h.path, 1); | |||||
} else { | } else { | ||||
ccb_status = CAM_REQ_CMP; | ccb_status = CAM_REQ_CMP; | ||||
} | } | ||||
ocs_set_ccb_status(ccb, ccb_status); | ocs_set_ccb_status(ccb, ccb_status); | ||||
ocs_scsi_io_free(io); | ocs_scsi_io_free(io); | ||||
▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | ocs_initiator_io(struct ocs_softc *ocs, union ccb *ccb) | ||||
int32_t rc; | int32_t rc; | ||||
struct ccb_scsiio *csio = &ccb->csio; | struct ccb_scsiio *csio = &ccb->csio; | ||||
struct ccb_hdr *ccb_h = &csio->ccb_h; | struct ccb_hdr *ccb_h = &csio->ccb_h; | ||||
ocs_node_t *node = NULL; | ocs_node_t *node = NULL; | ||||
ocs_io_t *io = NULL; | ocs_io_t *io = NULL; | ||||
ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL]; | ocs_scsi_sgl_t sgl[OCS_FC_MAX_SGL]; | ||||
int32_t sgl_count; | int32_t sgl_count; | ||||
node = ocs_node_get_instance(ocs, ccb_h->target_id); | ocs_fcport *fcp = NULL; | ||||
fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))); | |||||
if (fcp == NULL) { | |||||
device_printf(ocs->dev, "%s: fcp is NULL\n", __func__); | |||||
return -1; | |||||
} | |||||
if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_LOST) { | |||||
device_printf(ocs->dev, "%s: device LOST %d\n", __func__, | |||||
ccb_h->target_id); | |||||
return CAM_REQUEUE_REQ; | |||||
} | |||||
if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_NONE) { | |||||
device_printf(ocs->dev, "%s: device not ready %d\n", __func__, | |||||
ccb_h->target_id); | |||||
return CAM_DEV_NOT_THERE; | |||||
mavUnsubmitted Not Done Inline ActionsHere and below, when whole target is gone, proper error code would be CAM_SEL_TIMEOUT, since CAM_DEV_NOT_THERE will destroy only one LUN. mav: Here and below, when whole target is gone, proper error code would be CAM_SEL_TIMEOUT, since… | |||||
} | |||||
node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id); | |||||
if (node == NULL) { | if (node == NULL) { | ||||
device_printf(ocs->dev, "%s: no device %d\n", __func__, | device_printf(ocs->dev, "%s: no device %d\n", __func__, | ||||
ccb_h->target_id); | ccb_h->target_id); | ||||
return CAM_DEV_NOT_THERE; | return CAM_DEV_NOT_THERE; | ||||
} | } | ||||
if (!node->targ) { | if (!node->targ) { | ||||
device_printf(ocs->dev, "%s: not target device %d\n", __func__, | device_printf(ocs->dev, "%s: not target device %d\n", __func__, | ||||
ccb_h->target_id); | ccb_h->target_id); | ||||
return CAM_DEV_NOT_THERE; | return CAM_DEV_NOT_THERE; | ||||
} | } | ||||
io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR); | io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR); | ||||
if (io == NULL) { | if (io == NULL) { | ||||
device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__); | device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__); | ||||
return -1; | return -1; | ||||
} | } | ||||
/* eventhough this is INI, use target structure as ocs_build_scsi_sgl | /* eventhough this is INI, use target structure as ocs_build_scsi_sgl | ||||
Show All 20 Lines | ocs_initiator_io(struct ocs_softc *ocs, union ccb *ccb) | ||||
switch (ccb->ccb_h.flags & CAM_DIR_MASK) { | switch (ccb->ccb_h.flags & CAM_DIR_MASK) { | ||||
case CAM_DIR_NONE: | case CAM_DIR_NONE: | ||||
rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun, | rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun, | ||||
ccb->ccb_h.flags & CAM_CDB_POINTER ? | ccb->ccb_h.flags & CAM_CDB_POINTER ? | ||||
csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, | csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, | ||||
csio->cdb_len, | csio->cdb_len, | ||||
ocs_scsi_initiator_io_cb, ccb); | ocs_scsi_initiator_io_cb, ccb); | ||||
break; | break; | ||||
case CAM_DIR_IN: | case CAM_DIR_IN: | ||||
rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun, | rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun, | ||||
ccb->ccb_h.flags & CAM_CDB_POINTER ? | ccb->ccb_h.flags & CAM_CDB_POINTER ? | ||||
csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, | csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, | ||||
csio->cdb_len, | csio->cdb_len, | ||||
NULL, | NULL, | ||||
sgl, sgl_count, csio->dxfer_len, | sgl, sgl_count, csio->dxfer_len, | ||||
ocs_scsi_initiator_io_cb, ccb); | ocs_scsi_initiator_io_cb, ccb); | ||||
Show All 19 Lines | |||||
static uint32_t | static uint32_t | ||||
ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role) | ocs_fcp_change_role(struct ocs_softc *ocs, ocs_fcport *fcp, uint32_t new_role) | ||||
{ | { | ||||
uint32_t rc = 0, was = 0, i = 0; | uint32_t rc = 0, was = 0, i = 0; | ||||
ocs_vport_spec_t *vport = fcp->vport; | ocs_vport_spec_t *vport = fcp->vport; | ||||
for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) { | for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) { | ||||
if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE) | if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE) | ||||
was++; | was++; | ||||
} | } | ||||
// Physical port | // Physical port | ||||
if ((was == 0) || (vport == NULL)) { | if ((was == 0) || (vport == NULL)) { | ||||
fcp->role = new_role; | fcp->role = new_role; | ||||
if (vport == NULL) { | if (vport == NULL) { | ||||
ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; | ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; | ||||
ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; | ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; | ||||
} else { | } else { | ||||
Show All 22 Lines | if ((fcp->role != KNOB_ROLE_NONE)){ | ||||
return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn); | return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn); | ||||
} | } | ||||
fcp->role = new_role; | fcp->role = new_role; | ||||
vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; | vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; | ||||
vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; | vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; | ||||
if (fcp->role != KNOB_ROLE_NONE) { | if (fcp->role != KNOB_ROLE_NONE) { | ||||
return ocs_sport_vport_alloc(ocs->domain, vport); | return ocs_sport_vport_alloc(ocs->domain, vport); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/** | /** | ||||
* @ingroup cam_api | * @ingroup cam_api | ||||
Show All 14 Lines | ocs_action(struct cam_sim *sim, union ccb *ccb) | ||||
struct ocs_softc *ocs = (struct ocs_softc *)cam_sim_softc(sim); | struct ocs_softc *ocs = (struct ocs_softc *)cam_sim_softc(sim); | ||||
struct ccb_hdr *ccb_h = &ccb->ccb_h; | struct ccb_hdr *ccb_h = &ccb->ccb_h; | ||||
int32_t rc, bus; | int32_t rc, bus; | ||||
bus = cam_sim_bus(sim); | bus = cam_sim_bus(sim); | ||||
switch (ccb_h->func_code) { | switch (ccb_h->func_code) { | ||||
case XPT_SCSI_IO: | case XPT_SCSI_IO: | ||||
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { | if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { | ||||
if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { | if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { | ||||
ccb->ccb_h.status = CAM_REQ_INVALID; | ccb->ccb_h.status = CAM_REQ_INVALID; | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
rc = ocs_initiator_io(ocs, ccb); | rc = ocs_initiator_io(ocs, ccb); | ||||
if (0 == rc) { | if (0 == rc) { | ||||
ocs_set_ccb_status(ccb, CAM_REQ_INPROG | CAM_SIM_QUEUED); | ocs_set_ccb_status(ccb, CAM_REQ_INPROG | CAM_SIM_QUEUED); | ||||
break; | break; | ||||
} else { | } else { | ||||
if (rc == CAM_REQUEUE_REQ) { | |||||
cam_freeze_devq(ccb->ccb_h.path); | |||||
cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0); | |||||
ccb->ccb_h.status = CAM_REQUEUE_REQ; | |||||
xpt_done(ccb); | |||||
break; | |||||
} | |||||
ccb->ccb_h.status &= ~CAM_SIM_QUEUED; | ccb->ccb_h.status &= ~CAM_SIM_QUEUED; | ||||
if (rc > 0) { | if (rc > 0) { | ||||
ocs_set_ccb_status(ccb, rc); | ocs_set_ccb_status(ccb, rc); | ||||
} else { | } else { | ||||
ocs_set_ccb_status(ccb, CAM_SEL_TIMEOUT); | ocs_set_ccb_status(ccb, CAM_SEL_TIMEOUT); | ||||
} | } | ||||
} | } | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
Show All 34 Lines | case XPT_PATH_INQ: | ||||
} | } | ||||
if (ocs->config_tgt) { | if (ocs->config_tgt) { | ||||
cpi->target_sprt = | cpi->target_sprt = | ||||
PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; | PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; | ||||
} | } | ||||
cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; | cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; | ||||
cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN; | cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN; | ||||
cpi->hba_inquiry = PI_TAG_ABLE; | cpi->hba_inquiry = PI_TAG_ABLE; | ||||
cpi->max_target = OCS_MAX_TARGETS; | cpi->max_target = OCS_MAX_TARGETS; | ||||
cpi->initiator_id = ocs->max_remote_nodes + 1; | cpi->initiator_id = ocs->max_remote_nodes + 1; | ||||
if (!ocs->enable_ini) { | if (!ocs->enable_ini) { | ||||
cpi->hba_misc |= PIM_NOINITIATOR; | cpi->hba_misc |= PIM_NOINITIATOR; | ||||
} | } | ||||
Show All 20 Lines | case XPT_PATH_INQ: | ||||
break; | break; | ||||
} | } | ||||
case XPT_GET_TRAN_SETTINGS: | case XPT_GET_TRAN_SETTINGS: | ||||
{ | { | ||||
struct ccb_trans_settings *cts = &ccb->cts; | struct ccb_trans_settings *cts = &ccb->cts; | ||||
struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi; | struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi; | ||||
struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc; | struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc; | ||||
ocs_xport_stats_t value; | ocs_xport_stats_t value; | ||||
ocs_fcport *fcp = FCPORT(ocs, bus); | |||||
ocs_node_t *fnode = NULL; | ocs_node_t *fnode = NULL; | ||||
if (ocs->ocs_xport != OCS_XPORT_FC) { | if (ocs->ocs_xport != OCS_XPORT_FC) { | ||||
ocs_set_ccb_status(ccb, CAM_REQ_INVALID); | ocs_set_ccb_status(ccb, CAM_REQ_INVALID); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
} | } | ||||
fnode = ocs_node_get_instance(ocs, cts->ccb_h.target_id); | fnode = ocs_node_get_instance(ocs, fcp->tgt[cts->ccb_h.target_id].node_id); | ||||
if (fnode == NULL) { | if (fnode == NULL) { | ||||
ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE); | ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
} | } | ||||
cts->protocol = PROTO_SCSI; | cts->protocol = PROTO_SCSI; | ||||
cts->protocol_version = SCSI_REV_SPC2; | cts->protocol_version = SCSI_REV_SPC2; | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | case XPT_RESET_BUS: | ||||
} | } | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
case XPT_RESET_DEV: | case XPT_RESET_DEV: | ||||
{ | { | ||||
ocs_node_t *node = NULL; | ocs_node_t *node = NULL; | ||||
ocs_io_t *io = NULL; | ocs_io_t *io = NULL; | ||||
int32_t rc = 0; | int32_t rc = 0; | ||||
ocs_fcport *fcp = FCPORT(ocs, bus); | |||||
Done Inline ActionsThe declarations usually go in one contiguous section, so please take out this blank line. ken: The declarations usually go in one contiguous section, so please take out this blank line. | |||||
node = ocs_node_get_instance(ocs, ccb_h->target_id); | node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id); | ||||
if (node == NULL) { | if (node == NULL) { | ||||
device_printf(ocs->dev, "%s: no device %d\n", | device_printf(ocs->dev, "%s: no device %d\n", | ||||
__func__, ccb_h->target_id); | __func__, ccb_h->target_id); | ||||
ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE); | ocs_set_ccb_status(ccb, CAM_DEV_NOT_THERE); | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
} | } | ||||
Show All 12 Lines | rc = ocs_scsi_send_tmf(node, io, NULL, ccb_h->target_lun, | ||||
ocs_initiator_tmf_cb, NULL/*arg*/); | ocs_initiator_tmf_cb, NULL/*arg*/); | ||||
if (rc) { | if (rc) { | ||||
ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR); | ocs_set_ccb_status(ccb, CAM_REQ_CMP_ERR); | ||||
} else { | } else { | ||||
ocs_set_ccb_status(ccb, CAM_REQ_CMP); | ocs_set_ccb_status(ccb, CAM_REQ_CMP); | ||||
} | } | ||||
if (node->fcp2device) { | if (node->fcp2device) { | ||||
ocs_reset_crn(node, ccb_h->target_lun); | ocs_reset_crn(node, ccb_h->target_lun); | ||||
} | } | ||||
xpt_done(ccb); | xpt_done(ccb); | ||||
break; | break; | ||||
} | } | ||||
case XPT_EN_LUN: /* target support */ | case XPT_EN_LUN: /* target support */ | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | ocs_tgt_resource_abort(struct ocs_softc *ocs, ocs_tgt_resource_t *trsrc) | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb) | ocs_abort_atio(struct ocs_softc *ocs, union ccb *ccb) | ||||
{ | { | ||||
ocs_io_t *aio = NULL; | ocs_io_t *aio = NULL; | ||||
ocs_tgt_resource_t *trsrc = NULL; | ocs_tgt_resource_t *trsrc = NULL; | ||||
uint32_t status = CAM_REQ_INVALID; | uint32_t status = CAM_REQ_INVALID; | ||||
struct ccb_hdr *cur = NULL; | struct ccb_hdr *cur = NULL; | ||||
union ccb *accb = ccb->cab.abort_ccb; | union ccb *accb = ccb->cab.abort_ccb; | ||||
int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)); | int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)); | ||||
ocs_fcport *fcp = FCPORT(ocs, bus); | ocs_fcport *fcp = FCPORT(ocs, bus); | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | ocs_abort_inot(struct ocs_softc *ocs, union ccb *ccb) | ||||
ocs_set_ccb_status(ccb, CAM_UA_ABORT); | ocs_set_ccb_status(ccb, CAM_UA_ABORT); | ||||
return; | return; | ||||
} | } | ||||
static uint32_t | static uint32_t | ||||
ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb) | ocs_abort_initiator_io(struct ocs_softc *ocs, union ccb *accb) | ||||
{ | { | ||||
ocs_node_t *node = NULL; | ocs_node_t *node = NULL; | ||||
ocs_io_t *io = NULL; | ocs_io_t *io = NULL; | ||||
int32_t rc = 0; | int32_t rc = 0; | ||||
struct ccb_scsiio *csio = &accb->csio; | struct ccb_scsiio *csio = &accb->csio; | ||||
node = ocs_node_get_instance(ocs, accb->ccb_h.target_id); | ocs_fcport *fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((accb)->ccb_h.path))); | ||||
node = ocs_node_get_instance(ocs, fcp->tgt[accb->ccb_h.target_id].node_id); | |||||
if (node == NULL) { | if (node == NULL) { | ||||
device_printf(ocs->dev, "%s: no device %d\n", | device_printf(ocs->dev, "%s: no device %d\n", | ||||
__func__, accb->ccb_h.target_id); | __func__, accb->ccb_h.target_id); | ||||
ocs_set_ccb_status(accb, CAM_DEV_NOT_THERE); | ocs_set_ccb_status(accb, CAM_DEV_NOT_THERE); | ||||
xpt_done(accb); | xpt_done(accb); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 175 Lines • Show Last 20 Lines |
This comment makes it sound like the timer is active all the time. I had to look at the code to tell that it is only activated when a device goes away, and it only stays active if there is still work to do.
Please change the comment to explain that it's not polling once a second all the time.