Lines Matching +full:io +full:- +full:backends
1 /*-
36 * @defgroup cam_io CAM IO
49 /* Default IO timeout value for initiators is 30 seconds */
71 { OCS_SCSI_STATUS_NO_IO, "No IO" },
91 static int32_t ocs_task_set_full_or_busy(ocs_io_t *io);
111 static inline void ocs_target_io_free(ocs_io_t *io) in ocs_target_io_free() argument
113 io->tgt_io.state = OCS_CAM_IO_FREE; in ocs_target_io_free()
114 io->tgt_io.flags = 0; in ocs_target_io_free()
115 io->tgt_io.app = NULL; in ocs_target_io_free()
116 ocs_scsi_io_complete(io); in ocs_target_io_free()
117 if(io->ocs->io_in_use != 0) in ocs_target_io_free()
118 atomic_subtract_acq_32(&io->ocs->io_in_use, 1); in ocs_target_io_free()
131 device_get_name(ocs->dev), ocs, in ocs_attach_port()
132 device_get_unit(ocs->dev), &ocs->sim_lock, in ocs_attach_port()
133 max_io, max_io, ocs->devq))) { in ocs_attach_port()
134 device_printf(ocs->dev, "Can't allocate SIM\n"); in ocs_attach_port()
138 mtx_lock(&ocs->sim_lock); in ocs_attach_port()
139 if (CAM_SUCCESS != xpt_bus_register(sim, ocs->dev, chan)) { in ocs_attach_port()
140 device_printf(ocs->dev, "Can't register bus %d\n", 0); in ocs_attach_port()
141 mtx_unlock(&ocs->sim_lock); in ocs_attach_port()
145 mtx_unlock(&ocs->sim_lock); in ocs_attach_port()
149 device_printf(ocs->dev, "Can't create path\n"); in ocs_attach_port()
151 mtx_unlock(&ocs->sim_lock); in ocs_attach_port()
156 fcp->ocs = ocs; in ocs_attach_port()
157 fcp->sim = sim; in ocs_attach_port()
158 fcp->path = path; in ocs_attach_port()
160 callout_init_mtx(&fcp->ldt, &ocs->sim_lock, 0); in ocs_attach_port()
161 TASK_INIT(&fcp->ltask, 1, ocs_ldt_task, fcp); in ocs_attach_port()
174 sim = fcp->sim; in ocs_detach_port()
175 path = fcp->path; in ocs_detach_port()
177 callout_drain(&fcp->ldt); in ocs_detach_port()
180 if (fcp->sim) { in ocs_detach_port()
181 mtx_lock(&ocs->sim_lock); in ocs_detach_port()
182 ocs_tgt_resource_abort(ocs, &fcp->targ_rsrc_wildcard); in ocs_detach_port()
186 fcp->path = NULL; in ocs_detach_port()
191 fcp->sim = NULL; in ocs_detach_port()
192 mtx_unlock(&ocs->sim_lock); in ocs_detach_port()
206 device_printf(ocs->dev, "Can't allocate SIMQ\n"); in ocs_cam_attach()
207 return -1; in ocs_cam_attach()
210 ocs->devq = devq; in ocs_cam_attach()
212 if (mtx_initialized(&ocs->sim_lock) == 0) { in ocs_cam_attach()
213 mtx_init(&ocs->sim_lock, "ocs_sim_lock", NULL, MTX_DEF); in ocs_cam_attach()
216 for (i = 0; i < (ocs->num_vports + 1); i++) { in ocs_cam_attach()
223 ocs->io_high_watermark = max_io; in ocs_cam_attach()
224 ocs->io_in_use = 0; in ocs_cam_attach()
228 while (--i >= 0) { in ocs_cam_attach()
232 cam_simq_free(ocs->devq); in ocs_cam_attach()
234 if (mtx_initialized(&ocs->sim_lock)) in ocs_cam_attach()
235 mtx_destroy(&ocs->sim_lock); in ocs_cam_attach()
245 for (i = (ocs->num_vports); i >= 0; i--) { in ocs_cam_detach()
249 cam_simq_free(ocs->devq); in ocs_cam_detach()
251 if (mtx_initialized(&ocs->sim_lock)) in ocs_cam_detach()
252 mtx_destroy(&ocs->sim_lock); in ocs_cam_detach()
269 * @return 0 on success, non-zero otherwise
274 ocs->enable_task_set_full = ocs_scsi_get_property(ocs, in ocs_scsi_tgt_new_device()
277 ocs->enable_task_set_full ? "enabled" : "disabled"); in ocs_scsi_tgt_new_device()
303 * Called by base drive when new domain is discovered. A target-server
308 * which is declared by the target-server code and is used for target-server
311 * This function will only be called if the base-driver has been enabled for
314 * Note that this call is made to target-server backends,
315 * the ocs_scsi_ini_new_domain() function is called to initiator-client backends.
331 * Called by base-driver when a domain goes away. A target-server will
334 * Note that this call is made to target-server backends,
335 * the ocs_scsi_ini_del_domain() function is called to initiator-client backends.
350 * Called by base drive when new sport is discovered. A target-server
355 * which is declared by the target-server code and is used for
356 * target-server private data.
358 * This function will only be called if the base-driver has been enabled for
361 * Note that this call is made to target-server backends,
362 * the ocs_scsi_tgt_new_domain() is called to initiator-client backends.
371 ocs_t *ocs = sport->ocs; in ocs_scsi_tgt_new_sport()
373 if(!sport->is_vport) { in ocs_scsi_tgt_new_sport()
374 sport->tgt_data = FCPORT(ocs, 0); in ocs_scsi_tgt_new_sport()
384 * Called by base-driver when a sport goes away. A target-server will
387 * Note that this call is made to target-server backends,
388 * the ocs_scsi_ini_del_sport() is called to initiator-client backends.
404 * Sent by base driver to notify a target-server of the presense of a new
405 * remote initiator. The target-server may use this call to prepare for
406 * inbound IO from this node.
409 * tgt_node that is declared and used by a target-server for private
423 ocs_t *ocs = node->ocs; in ocs_scsi_new_initiator()
429 fcp = node->sport->tgt_data; in ocs_scsi_new_initiator()
436 * Update the IO watermark by decrementing it by the in ocs_scsi_new_initiator()
439 atomic_subtract_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO); in ocs_scsi_new_initiator()
443 adc->wwpn = ocs_node_get_wwpn(node); in ocs_scsi_new_initiator()
444 adc->port = node->rnode.fc_id; in ocs_scsi_new_initiator()
445 adc->target = node->instance_index; in ocs_scsi_new_initiator()
446 adc->arrived = 1; in ocs_scsi_new_initiator()
447 xpt_async(AC_CONTRACT, fcp->path, &ac); in ocs_scsi_new_initiator()
456 * Sent by base driver to validate a remote initiatiator. The target-server
478 * Sent by base driver to notify a target-server that a remote initiator
480 * and the target-server will receive appropriate completions.
495 ocs_t *ocs = node->ocs; in ocs_scsi_del_initiator()
501 fcp = node->sport->tgt_data; in ocs_scsi_del_initiator()
509 adc->wwpn = ocs_node_get_wwpn(node); in ocs_scsi_del_initiator()
510 adc->port = node->rnode.fc_id; in ocs_scsi_del_initiator()
511 adc->target = node->instance_index; in ocs_scsi_del_initiator()
512 adc->arrived = 0; in ocs_scsi_del_initiator()
513 xpt_async(AC_CONTRACT, fcp->path, &ac); in ocs_scsi_del_initiator()
520 * Update the IO watermark by incrementing it by the in ocs_scsi_del_initiator()
523 atomic_add_acq_32(&ocs->io_high_watermark, OCS_RSVD_INI_IO); in ocs_scsi_del_initiator()
533 * target-server will process the command, and issue data and/or response phase
536 * The IO context (ocs_io_t) structure has and element of type
538 * a target-server for private information.
540 * @param io pointer to IO context
541 * @param lun LUN for this IO
548 int32_t ocs_scsi_recv_cmd(ocs_io_t *io, uint64_t lun, uint8_t *cdb, in ocs_scsi_recv_cmd() argument
551 ocs_t *ocs = io->ocs; in ocs_scsi_recv_cmd()
553 ocs_node_t *node = io->node; in ocs_scsi_recv_cmd()
555 int32_t rc = -1; in ocs_scsi_recv_cmd()
558 fcp = node->sport->tgt_data; in ocs_scsi_recv_cmd()
564 atomic_add_acq_32(&ocs->io_in_use, 1); in ocs_scsi_recv_cmd()
566 /* set target io timeout */ in ocs_scsi_recv_cmd()
567 io->timeout = ocs->target_io_timer_sec; in ocs_scsi_recv_cmd()
569 if (ocs->enable_task_set_full && in ocs_scsi_recv_cmd()
570 (ocs->io_in_use >= ocs->io_high_watermark)) { in ocs_scsi_recv_cmd()
571 return ocs_task_set_full_or_busy(io); in ocs_scsi_recv_cmd()
573 atomic_store_rel_32(&io->node->tgt_node.busy_sent, FALSE); in ocs_scsi_recv_cmd()
576 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) { in ocs_scsi_recv_cmd()
577 trsrc = &fcp->targ_rsrc[lun]; in ocs_scsi_recv_cmd()
578 } else if (fcp->targ_rsrc_wildcard.enabled) { in ocs_scsi_recv_cmd()
579 trsrc = &fcp->targ_rsrc_wildcard; in ocs_scsi_recv_cmd()
583 atio = (struct ccb_accept_tio *)STAILQ_FIRST(&trsrc->atio); in ocs_scsi_recv_cmd()
587 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe); in ocs_scsi_recv_cmd()
589 atio->ccb_h.status = CAM_CDB_RECVD; in ocs_scsi_recv_cmd()
590 atio->ccb_h.target_lun = lun; in ocs_scsi_recv_cmd()
591 atio->sense_len = 0; in ocs_scsi_recv_cmd()
593 atio->init_id = node->instance_index; in ocs_scsi_recv_cmd()
594 atio->tag_id = io->tag; in ocs_scsi_recv_cmd()
595 atio->ccb_h.ccb_io_ptr = io; in ocs_scsi_recv_cmd()
598 atio->tag_action = MSG_SIMPLE_Q_TAG; in ocs_scsi_recv_cmd()
600 atio->tag_action = MSG_HEAD_OF_Q_TAG; in ocs_scsi_recv_cmd()
602 atio->tag_action = MSG_ORDERED_Q_TAG; in ocs_scsi_recv_cmd()
604 atio->tag_action = MSG_ACA_TASK; in ocs_scsi_recv_cmd()
606 atio->tag_action = CAM_TAG_ACTION_NONE; in ocs_scsi_recv_cmd()
607 atio->priority = (flags & OCS_SCSI_PRIORITY_MASK) >> in ocs_scsi_recv_cmd()
610 atio->cdb_len = cdb_len; in ocs_scsi_recv_cmd()
611 ocs_memcpy(atio->cdb_io.cdb_bytes, cdb, cdb_len); in ocs_scsi_recv_cmd()
613 io->tgt_io.flags = 0; in ocs_scsi_recv_cmd()
614 io->tgt_io.state = OCS_CAM_IO_COMMAND; in ocs_scsi_recv_cmd()
615 io->tgt_io.lun = lun; in ocs_scsi_recv_cmd()
622 ocs->dev, "%s: no ATIO for LUN %lx (en=%s) OX_ID %#x\n", in ocs_scsi_recv_cmd()
624 trsrc ? (trsrc->enabled ? "T" : "F") : "X", in ocs_scsi_recv_cmd()
625 be16toh(io->init_task_tag)); in ocs_scsi_recv_cmd()
627 io->tgt_io.state = OCS_CAM_IO_MAX; in ocs_scsi_recv_cmd()
628 ocs_target_io_free(io); in ocs_scsi_recv_cmd()
640 * @param io pointer to IO context
641 * @param lun LUN for this IO
650 int32_t ocs_scsi_recv_cmd_first_burst(ocs_io_t *io, uint64_t lun, uint8_t *cdb, in ocs_scsi_recv_cmd_first_burst() argument
655 return -1; in ocs_scsi_recv_cmd_first_burst()
660 * @brief receive a TMF command IO
663 * target-server will process the command, aborting commands as needed, and post
666 * The IO context (ocs_io_t) structure has and element of type ocs_scsi_tgt_io_t named
667 * tgt_io that is declared and used by a target-server for private information.
669 * If the target-server walks the nodes active_ios linked list, and starts IO
670 * abort processing, the code <b>must</b> be sure not to abort the IO passed into the
673 * @param tmfio pointer to IO context
676 * @param abortio pointer to IO object to abort for TASK_ABORT (NULL for all other TMF)
684 ocs_t *ocs = tmfio->ocs; in ocs_scsi_recv_tmf()
685 ocs_node_t *node = tmfio->node; in ocs_scsi_recv_tmf()
688 int32_t rc = -1; in ocs_scsi_recv_tmf()
691 fcp = node->sport->tgt_data; in ocs_scsi_recv_tmf()
697 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) { in ocs_scsi_recv_tmf()
698 trsrc = &fcp->targ_rsrc[lun]; in ocs_scsi_recv_tmf()
699 } else if (fcp->targ_rsrc_wildcard.enabled) { in ocs_scsi_recv_tmf()
700 trsrc = &fcp->targ_rsrc_wildcard; in ocs_scsi_recv_tmf()
703 device_printf(tmfio->ocs->dev, "%s: io=%u(index) cmd=%#x LU=%lx en=%s\n", in ocs_scsi_recv_tmf()
704 __func__, tmfio->instance_index, cmd, (unsigned long)lun, in ocs_scsi_recv_tmf()
705 trsrc ? (trsrc->enabled ? "T" : "F") : "X"); in ocs_scsi_recv_tmf()
707 inot = (struct ccb_immediate_notify *)STAILQ_FIRST(&trsrc->inot); in ocs_scsi_recv_tmf()
712 ocs->dev, "%s: no INOT for LUN %llx (en=%s) OX_ID %#x\n", in ocs_scsi_recv_tmf()
713 __func__, (unsigned long long)lun, trsrc ? (trsrc->enabled ? "T" : "F") : "X", in ocs_scsi_recv_tmf()
714 be16toh(tmfio->init_task_tag)); in ocs_scsi_recv_tmf()
723 tmfio->tgt_io.app = abortio; in ocs_scsi_recv_tmf()
725 STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe); in ocs_scsi_recv_tmf()
727 inot->tag_id = tmfio->tag; in ocs_scsi_recv_tmf()
728 inot->seq_id = tmfio->tag; in ocs_scsi_recv_tmf()
730 if ((lun < OCS_MAX_LUN) && fcp->targ_rsrc[lun].enabled) { in ocs_scsi_recv_tmf()
731 inot->initiator_id = node->instance_index; in ocs_scsi_recv_tmf()
733 inot->initiator_id = CAM_TARGET_WILDCARD; in ocs_scsi_recv_tmf()
736 inot->ccb_h.status = CAM_MESSAGE_RECV; in ocs_scsi_recv_tmf()
737 inot->ccb_h.target_lun = lun; in ocs_scsi_recv_tmf()
741 inot->arg = MSG_ABORT_TASK; in ocs_scsi_recv_tmf()
742 inot->seq_id = abortio->tag; in ocs_scsi_recv_tmf()
743 device_printf(ocs->dev, "%s: ABTS IO.%#x st=%#x\n", in ocs_scsi_recv_tmf()
744 __func__, abortio->tag, abortio->tgt_io.state); in ocs_scsi_recv_tmf()
745 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_RECV; in ocs_scsi_recv_tmf()
746 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_NOTIFY; in ocs_scsi_recv_tmf()
749 device_printf(ocs->dev, in ocs_scsi_recv_tmf()
752 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe); in ocs_scsi_recv_tmf()
757 inot->arg = MSG_ABORT_TASK_SET; in ocs_scsi_recv_tmf()
760 inot->arg = MSG_CLEAR_TASK_SET; in ocs_scsi_recv_tmf()
763 inot->arg = MSG_QUERY_ASYNC_EVENT; in ocs_scsi_recv_tmf()
766 inot->arg = MSG_LOGICAL_UNIT_RESET; in ocs_scsi_recv_tmf()
769 inot->arg = MSG_CLEAR_ACA; in ocs_scsi_recv_tmf()
772 inot->arg = MSG_TARGET_RESET; in ocs_scsi_recv_tmf()
775 device_printf(ocs->dev, "%s: unsupported TMF %#x\n", in ocs_scsi_recv_tmf()
777 STAILQ_INSERT_TAIL(&trsrc->inot, &inot->ccb_h, sim_links.stqe); in ocs_scsi_recv_tmf()
783 xpt_print(inot->ccb_h.path, "%s: func=%#x stat=%#x id=%#x lun=%#x" in ocs_scsi_recv_tmf()
785 __func__, inot->ccb_h.func_code, inot->ccb_h.status, in ocs_scsi_recv_tmf()
786 inot->ccb_h.target_id, in ocs_scsi_recv_tmf()
787 (unsigned int)inot->ccb_h.target_lun, inot->ccb_h.flags, in ocs_scsi_recv_tmf()
788 inot->tag_id, inot->seq_id, inot->initiator_id, in ocs_scsi_recv_tmf()
789 inot->arg); in ocs_scsi_recv_tmf()
793 abortio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_DEV; in ocs_scsi_recv_tmf()
840 * Called by base drive when new domain is discovered. An initiator-client
845 * which is declared by the initiator-client code and is used for
846 * initiator-client private data.
848 * This function will only be called if the base-driver has been enabled for
851 * Note that this call is made to initiator-client backends,
852 * the ocs_scsi_tgt_new_domain() function is called to target-server backends.
868 * Called by base-driver when a domain goes away. An initiator-client will
871 * This function will only be called if the base-driver has been enabled for
874 * Note that this call is made to initiator-client backends,
875 * the ocs_scsi_tgt_del_domain() function is called to target-server backends.
891 * A target-server will use this call to prepare for new remote node
894 * This function will only be called if the base-driver has been enabled for
897 * Note that this call is made to target-server backends,
898 * the ocs_scsi_ini_new_sport() function is called to initiator-client backends.
907 ocs_t *ocs = sport->ocs; in ocs_scsi_ini_new_sport()
910 if (!sport->is_vport) { in ocs_scsi_ini_new_sport()
911 sport->tgt_data = fcp; in ocs_scsi_ini_new_sport()
912 fcp->fc_id = sport->fc_id; in ocs_scsi_ini_new_sport()
922 * Called by base-driver when a sport goes away. A target-server will
925 * Note that this call is made to target-server backends,
926 * the ocs_scsi_ini_del_sport() function is called to initiator-client backends.
935 ocs_t *ocs = sport->ocs; in ocs_scsi_ini_del_sport()
938 if (!sport->is_vport) { in ocs_scsi_ini_del_sport()
939 fcp->fc_id = 0; in ocs_scsi_ini_del_sport()
946 ocs_t *ocs = sport->ocs; in ocs_scsi_sport_deleted()
951 if (!sport->is_vport) { in ocs_scsi_sport_deleted()
955 fcp = sport->tgt_data; in ocs_scsi_sport_deleted()
957 ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value); in ocs_scsi_sport_deleted()
964 if ((fcp->role != KNOB_ROLE_NONE)) { in ocs_scsi_sport_deleted()
965 if(fcp->vport->sport != NULL) { in ocs_scsi_sport_deleted()
970 ocs_sport_vport_alloc(ocs->domain, fcp->vport); in ocs_scsi_sport_deleted()
983 tgt = &fcp->tgt[i]; in ocs_tgt_find()
985 if (tgt->state == OCS_TGT_STATE_NONE) in ocs_tgt_find()
988 if (ocs_node_get_wwpn(node) == tgt->wwpn) { in ocs_tgt_find()
993 return -1; in ocs_tgt_find()
1000 * Sent by base driver to notify an initiator-client of the presense of a new
1001 * remote target. The initiator-server may use this call to prepare for
1002 * inbound IO from this node.
1019 tgt = &fcp->tgt[tgt_id]; in ocs_update_tgt()
1021 tgt->node_id = node->instance_index; in ocs_update_tgt()
1022 tgt->state = OCS_TGT_STATE_VALID; in ocs_update_tgt()
1024 tgt->port_id = node->rnode.fc_id; in ocs_update_tgt()
1025 tgt->wwpn = ocs_node_get_wwpn(node); in ocs_update_tgt()
1026 tgt->wwnn = ocs_node_get_wwnn(node); in ocs_update_tgt()
1035 struct ocs_softc *ocs = node->ocs; in ocs_add_new_tgt()
1038 if (fcp->tgt[i].state == OCS_TGT_STATE_NONE) in ocs_add_new_tgt()
1043 device_printf(ocs->dev, "%s: ccb allocation failed\n", __func__); in ocs_add_new_tgt()
1044 return -1; in ocs_add_new_tgt()
1047 if (CAM_REQ_CMP != xpt_create_path(&ccb->ccb_h.path, xpt_periph, in ocs_add_new_tgt()
1048 cam_sim_path(fcp->sim), in ocs_add_new_tgt()
1051 ocs->dev, "%s: target path creation failed\n", __func__); in ocs_add_new_tgt()
1053 return -1; in ocs_add_new_tgt()
1067 fcp = node->sport->tgt_data; in ocs_scsi_new_target()
1089 if (!fcp->sim) { in ocs_delete_target()
1090 device_printf(ocs->dev, "%s: calling with NULL sim\n", __func__); in ocs_delete_target()
1094 if (CAM_REQ_CMP == xpt_create_path(&cpath, NULL, cam_sim_path(fcp->sim), in ocs_delete_target()
1103 * Device Lost Timer Function- when we have decided that a device was lost,
1117 taskqueue_enqueue(taskqueue_thread, &fcp->ltask); in ocs_ldt()
1124 ocs_t *ocs = fcp->ocs; in ocs_ldt_task()
1129 tgt = &fcp->tgt[i]; in ocs_ldt_task()
1131 if (tgt->state != OCS_TGT_STATE_LOST) { in ocs_ldt_task()
1135 if ((tgt->gone_timer != 0) && (ocs->attached)){ in ocs_ldt_task()
1136 tgt->gone_timer -= 1; in ocs_ldt_task()
1143 tgt->state = OCS_TGT_STATE_NONE; in ocs_ldt_task()
1147 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp); in ocs_ldt_task()
1149 callout_deactivate(&fcp->ldt); in ocs_ldt_task()
1158 * Sent by base driver to notify a initiator-client that a remote target
1160 * and the initiator-client will receive appropriate completions.
1163 * ini_node that is declared and used by a target-server for private
1180 struct ocs_softc *ocs = node->ocs; in ocs_scsi_del_target()
1187 return -1; in ocs_scsi_del_target()
1190 fcp = node->sport->tgt_data; in ocs_scsi_del_target()
1193 return -1; in ocs_scsi_del_target()
1197 if (tgt_id == -1) { in ocs_scsi_del_target()
1199 return -1; in ocs_scsi_del_target()
1202 tgt = &fcp->tgt[tgt_id]; in ocs_scsi_del_target()
1205 if(!ocs->attached) { in ocs_scsi_del_target()
1208 tgt->state = OCS_TGT_STATE_LOST; in ocs_scsi_del_target()
1209 tgt->gone_timer = 30; in ocs_scsi_del_target()
1210 if (!callout_active(&fcp->ldt)) { in ocs_scsi_del_target()
1211 callout_reset(&fcp->ldt, hz, ocs_ldt, fcp); in ocs_scsi_del_target()
1219 * @brief Initialize SCSI IO
1221 * Initialize SCSI IO, this function is called once per IO during IO pool
1225 * @param io pointer to SCSI IO object
1230 ocs_scsi_tgt_io_init(ocs_io_t *io) in ocs_scsi_tgt_io_init() argument
1236 * @brief Uninitialize SCSI IO
1238 * Uninitialize target server private data in a SCSI io object
1240 * @param io pointer to SCSI IO object
1245 ocs_scsi_tgt_io_exit(ocs_io_t *io) in ocs_scsi_tgt_io_exit() argument
1251 * @brief Initialize SCSI IO
1253 * Initialize SCSI IO, this function is called once per IO during IO pool
1257 * @param io pointer to SCSI IO object
1262 ocs_scsi_ini_io_init(ocs_io_t *io) in ocs_scsi_ini_io_init() argument
1268 * @brief Uninitialize SCSI IO
1270 * Uninitialize initiator client private data in a SCSI io object
1272 * @param io pointer to SCSI IO object
1277 ocs_scsi_ini_io_exit(ocs_io_t *io) in ocs_scsi_ini_io_exit() argument
1288 ccb->ccb_h.status &= ~CAM_STATUS_MASK; in ocs_set_ccb_status()
1289 ccb->ccb_h.status |= status; in ocs_set_ccb_status()
1293 ocs_task_set_full_or_busy_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, in ocs_task_set_full_or_busy_cb() argument
1297 ocs_target_io_free(io); in ocs_task_set_full_or_busy_cb()
1306 * another IO is already active on the LUN.
1308 * @param io pointer to IO context
1314 ocs_task_set_full_or_busy(ocs_io_t *io) in ocs_task_set_full_or_busy() argument
1317 ocs_t *ocs = io->ocs; in ocs_task_set_full_or_busy()
1326 if (atomic_cmpset_acq_32(&io->node->tgt_node.busy_sent, FALSE, TRUE)) { in ocs_task_set_full_or_busy()
1329 io->node->display_name, io->tag, in ocs_task_set_full_or_busy()
1330 io->ocs->io_in_use, io->ocs->io_high_watermark); in ocs_task_set_full_or_busy()
1333 printf("%s: full tag=%x iiu=%d\n", __func__, io->tag, in ocs_task_set_full_or_busy()
1334 io->ocs->io_in_use); in ocs_task_set_full_or_busy()
1343 ocs->io_high_watermark); in ocs_task_set_full_or_busy()
1353 ocs_scsi_send_resp(io, 0, &rsp, ocs_task_set_full_or_busy_cb, NULL); in ocs_task_set_full_or_busy()
1358 * @brief Process target IO completions
1360 * @param io
1361 * @param scsi_status did the IO complete successfully
1367 static int32_t ocs_scsi_target_io_cb(ocs_io_t *io, in ocs_scsi_target_io_cb() argument
1372 struct ccb_scsiio *csio = &ccb->csio; in ocs_scsi_target_io_cb()
1373 struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr; in ocs_scsi_target_io_cb()
1374 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK; in ocs_scsi_target_io_cb()
1376 (ccb->ccb_h.flags & CAM_SEND_STATUS) == CAM_SEND_STATUS; in ocs_scsi_target_io_cb()
1378 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; in ocs_scsi_target_io_cb()
1389 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op); in ocs_scsi_target_io_cb()
1390 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) { in ocs_scsi_target_io_cb()
1391 bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap); in ocs_scsi_target_io_cb()
1395 if (io->tgt_io.sendresp) { in ocs_scsi_target_io_cb()
1396 io->tgt_io.sendresp = 0; in ocs_scsi_target_io_cb()
1398 io->tgt_io.state = OCS_CAM_IO_RESP; in ocs_scsi_target_io_cb()
1400 if (ccb->ccb_h.flags & CAM_SEND_SENSE) { in ocs_scsi_target_io_cb()
1401 resp.sense_data = (uint8_t *)&csio->sense_data; in ocs_scsi_target_io_cb()
1402 resp.sense_data_length = csio->sense_len; in ocs_scsi_target_io_cb()
1404 resp.residual = io->exp_xfer_len - io->transferred; in ocs_scsi_target_io_cb()
1406 return ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb); in ocs_scsi_target_io_cb()
1421 if ((io->tgt_io.flags & OCS_CAM_IO_F_ABORT_NOTIFY) == 0) { in ocs_scsi_target_io_cb()
1422 ocs_target_io_free(io); in ocs_scsi_target_io_cb()
1425 io->tgt_io.state = OCS_CAM_IO_DATA_DONE; in ocs_scsi_target_io_cb()
1426 /*device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n", in ocs_scsi_target_io_cb()
1427 __func__, io->tgt_io.state, io->tag);*/ in ocs_scsi_target_io_cb()
1438 * a CTIO, the IO's CCB will be NULL.
1441 ocs_io_abort_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, void *arg) in ocs_io_abort_cb() argument
1448 ocs = io->ocs; in ocs_io_abort_cb()
1450 io->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_DEV; in ocs_io_abort_cb()
1452 /* A good status indicates the IO was aborted and will be completed in in ocs_io_abort_cb()
1453 * the IO's completion handler. Handle the other cases here. */ in ocs_io_abort_cb()
1460 device_printf(ocs->dev, "%s: unhandled status %d\n", in ocs_io_abort_cb()
1463 rc = -1; in ocs_io_abort_cb()
1473 * @brief Process initiator IO completions
1475 * @param io
1476 * @param scsi_status did the IO complete successfully
1483 static int32_t ocs_scsi_initiator_io_cb(ocs_io_t *io, in ocs_scsi_initiator_io_cb() argument
1489 struct ccb_scsiio *csio = &ccb->csio; in ocs_scsi_initiator_io_cb()
1490 struct ocs_softc *ocs = csio->ccb_h.ccb_ocs_ptr; in ocs_scsi_initiator_io_cb()
1491 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK; in ocs_scsi_initiator_io_cb()
1503 bus_dmamap_sync(ocs->buf_dmat, io->tgt_io.dmap, op); in ocs_scsi_initiator_io_cb()
1504 if (io->tgt_io.flags & OCS_CAM_IO_F_DMAPPED) { in ocs_scsi_initiator_io_cb()
1505 bus_dmamap_unload(ocs->buf_dmat, io->tgt_io.dmap); in ocs_scsi_initiator_io_cb()
1510 csio->scsi_status = rsp->scsi_status; in ocs_scsi_initiator_io_cb()
1511 if (SCSI_STATUS_OK != rsp->scsi_status) in ocs_scsi_initiator_io_cb()
1516 csio->resid = rsp->residual; in ocs_scsi_initiator_io_cb()
1522 if ((rsp->residual < 0) && (ccb_status == CAM_REQ_CMP)) { in ocs_scsi_initiator_io_cb()
1526 if ((rsp->sense_data_length) && in ocs_scsi_initiator_io_cb()
1527 !(ccb->ccb_h.flags & (CAM_SENSE_PHYS | CAM_SENSE_PTR))) { in ocs_scsi_initiator_io_cb()
1530 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; in ocs_scsi_initiator_io_cb()
1531 if (rsp->sense_data_length < csio->sense_len) { in ocs_scsi_initiator_io_cb()
1532 csio->sense_resid = in ocs_scsi_initiator_io_cb()
1533 csio->sense_len - rsp->sense_data_length; in ocs_scsi_initiator_io_cb()
1534 sense_len = rsp->sense_data_length; in ocs_scsi_initiator_io_cb()
1536 csio->sense_resid = 0; in ocs_scsi_initiator_io_cb()
1537 sense_len = csio->sense_len; in ocs_scsi_initiator_io_cb()
1539 ocs_memcpy(&csio->sense_data, rsp->sense_data, sense_len); in ocs_scsi_initiator_io_cb()
1549 xpt_path_sbuf(ccb->ccb_h.path, &sb); in ocs_scsi_initiator_io_cb()
1558 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { in ocs_scsi_initiator_io_cb()
1559 scsi_command_string(&ccb->csio, &sb); in ocs_scsi_initiator_io_cb()
1560 sbuf_printf(&sb, "length %d ", ccb->csio.dxfer_len); in ocs_scsi_initiator_io_cb()
1602 ocs_scsi_io_free(io); in ocs_scsi_initiator_io_cb()
1604 csio->ccb_h.ccb_io_ptr = NULL; in ocs_scsi_initiator_io_cb()
1605 csio->ccb_h.ccb_ocs_ptr = NULL; in ocs_scsi_initiator_io_cb()
1607 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; in ocs_scsi_initiator_io_cb()
1610 ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0)) { in ocs_scsi_initiator_io_cb()
1611 ccb->ccb_h.status |= CAM_DEV_QFRZN; in ocs_scsi_initiator_io_cb()
1612 xpt_freeze_devq(ccb->ccb_h.path, 1); in ocs_scsi_initiator_io_cb()
1621 * @brief Load scatter-gather list entries into an IO
1624 * the IO object pointer having been already assigned to hooks in the CCB.
1628 * @param arg pointer to the CAM ccb for this IO
1631 * @param error any errors while mapping the IO
1641 sglarg->rc = -1; in ocs_scsi_dmamap_load()
1646 if ((sglarg->sgl_count + nseg) > sglarg->sgl_max) { in ocs_scsi_dmamap_load()
1648 sglarg->sgl_count, nseg, sglarg->sgl_max); in ocs_scsi_dmamap_load()
1649 sglarg->rc = -2; in ocs_scsi_dmamap_load()
1653 for (i = 0, c = sglarg->sgl_count; i < nseg; i++, c++) { in ocs_scsi_dmamap_load()
1654 sglarg->sgl[c].addr = seg[i].ds_addr; in ocs_scsi_dmamap_load()
1655 sglarg->sgl[c].len = seg[i].ds_len; in ocs_scsi_dmamap_load()
1658 sglarg->sgl_count = c; in ocs_scsi_dmamap_load()
1660 sglarg->rc = 0; in ocs_scsi_dmamap_load()
1665 * @brief Build a scatter-gather list from a CAM CCB
1669 * @param io pointer to the previously allocated IO object
1673 * @return 0 on success, non-zero otherwise
1676 ocs_build_scsi_sgl(struct ocs_softc *ocs, union ccb *ccb, ocs_io_t *io, in ocs_build_scsi_sgl() argument
1682 if (!ocs || !ccb || !io || !sgl) { in ocs_build_scsi_sgl()
1684 ocs, ccb, io, sgl); in ocs_build_scsi_sgl()
1685 return -1; in ocs_build_scsi_sgl()
1688 io->tgt_io.flags &= ~OCS_CAM_IO_F_DMAPPED; in ocs_build_scsi_sgl()
1695 err = bus_dmamap_load_ccb(ocs->buf_dmat, io->tgt_io.dmap, ccb, in ocs_build_scsi_sgl()
1700 ocs->dev, "%s: bus_dmamap_load_ccb error (%d %d)\n", in ocs_build_scsi_sgl()
1702 return -1; in ocs_build_scsi_sgl()
1705 io->tgt_io.flags |= OCS_CAM_IO_F_DMAPPED; in ocs_build_scsi_sgl()
1711 * @brief Send a target IO
1716 * @return 0 on success, non-zero otherwise
1721 struct ccb_scsiio *csio = &ccb->csio; in ocs_target_io()
1722 ocs_io_t *io = NULL; in ocs_target_io() local
1723 uint32_t cam_dir = ccb->ccb_h.flags & CAM_DIR_MASK; in ocs_target_io()
1724 bool sendstatus = ccb->ccb_h.flags & CAM_SEND_STATUS; in ocs_target_io()
1725 uint32_t xferlen = csio->dxfer_len; in ocs_target_io()
1728 io = ocs_scsi_find_io(ocs, csio->tag_id); in ocs_target_io()
1729 if (io == NULL) { in ocs_target_io()
1735 /* Received an ABORT TASK for this IO */ in ocs_target_io()
1736 if (io->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) { in ocs_target_io()
1737 /*device_printf(ocs->dev, in ocs_target_io()
1739 __func__, io->tgt_io.state, io->tag, io->init_task_tag, in ocs_target_io()
1740 io->tgt_io.flags);*/ in ocs_target_io()
1741 io->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM; in ocs_target_io()
1743 if (ccb->ccb_h.flags & CAM_SEND_STATUS) { in ocs_target_io()
1745 ocs_target_io_free(io); in ocs_target_io()
1754 io->tgt_io.app = ccb; in ocs_target_io()
1757 ccb->ccb_h.status |= CAM_SIM_QUEUED; in ocs_target_io()
1759 csio->ccb_h.ccb_ocs_ptr = ocs; in ocs_target_io()
1760 csio->ccb_h.ccb_io_ptr = io; in ocs_target_io()
1765 ocs_assert(ccb->ccb_h.flags & CAM_SEND_STATUS, -1); in ocs_target_io()
1767 io->tgt_io.state = OCS_CAM_IO_RESP; in ocs_target_io()
1769 resp.scsi_status = csio->scsi_status; in ocs_target_io()
1771 if (ccb->ccb_h.flags & CAM_SEND_SENSE) { in ocs_target_io()
1772 resp.sense_data = (uint8_t *)&csio->sense_data; in ocs_target_io()
1773 resp.sense_data_length = csio->sense_len; in ocs_target_io()
1776 resp.residual = io->exp_xfer_len - io->transferred; in ocs_target_io()
1777 rc = ocs_scsi_send_resp(io, 0, &resp, ocs_scsi_target_io_cb, ccb); in ocs_target_io()
1783 io->tgt_io.state = OCS_CAM_IO_DATA; in ocs_target_io()
1786 io->tgt_io.sendresp = 1; in ocs_target_io()
1788 sgl = io->sgl; in ocs_target_io()
1790 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, io->sgl_allocated); in ocs_target_io()
1793 rc = ocs_scsi_send_rd_data(io, 0, NULL, sgl, in ocs_target_io()
1794 sgl_count, csio->dxfer_len, in ocs_target_io()
1797 rc = ocs_scsi_recv_wr_data(io, 0, NULL, sgl, in ocs_target_io()
1798 sgl_count, csio->dxfer_len, in ocs_target_io()
1801 device_printf(ocs->dev, "%s:" in ocs_target_io()
1808 device_printf(ocs->dev, "%s: building SGL failed\n", in ocs_target_io()
1814 device_printf(ocs->dev, "%s: Wrong value xfer and sendstatus" in ocs_target_io()
1822 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; in ocs_target_io()
1823 io->tgt_io.state = OCS_CAM_IO_DATA_DONE; in ocs_target_io()
1824 device_printf(ocs->dev, "%s: CTIO state=%d tag=%#x\n", in ocs_target_io()
1825 __func__, io->tgt_io.state, io->tag); in ocs_target_io()
1827 ocs_target_io_free(io); in ocs_target_io()
1835 ocs_target_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, uint32_t flags, in ocs_target_tmf_cb() argument
1839 /*device_printf(io->ocs->dev, "%s: tag=%x io=%p s=%#x\n", in ocs_target_tmf_cb()
1840 __func__, io->tag, io, scsi_status);*/ in ocs_target_tmf_cb()
1841 ocs_scsi_io_complete(io); in ocs_target_tmf_cb()
1848 * @brief Send an initiator IO
1853 * @return 0 on success, non-zero otherwise
1859 struct ccb_scsiio *csio = &ccb->csio; in ocs_initiator_io()
1860 struct ccb_hdr *ccb_h = &csio->ccb_h; in ocs_initiator_io()
1862 ocs_io_t *io = NULL; in ocs_initiator_io() local
1867 fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))); in ocs_initiator_io()
1869 if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_LOST) { in ocs_initiator_io()
1870 device_printf(ocs->dev, "%s: device LOST %d\n", __func__, in ocs_initiator_io()
1871 ccb_h->target_id); in ocs_initiator_io()
1875 if (fcp->tgt[ccb_h->target_id].state == OCS_TGT_STATE_NONE) { in ocs_initiator_io()
1876 device_printf(ocs->dev, "%s: device not ready %d\n", __func__, in ocs_initiator_io()
1877 ccb_h->target_id); in ocs_initiator_io()
1881 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id); in ocs_initiator_io()
1883 device_printf(ocs->dev, "%s: no device %d\n", __func__, in ocs_initiator_io()
1884 ccb_h->target_id); in ocs_initiator_io()
1888 if (!node->targ) { in ocs_initiator_io()
1889 device_printf(ocs->dev, "%s: not target device %d\n", __func__, in ocs_initiator_io()
1890 ccb_h->target_id); in ocs_initiator_io()
1894 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR); in ocs_initiator_io()
1895 if (io == NULL) { in ocs_initiator_io()
1896 device_printf(ocs->dev, "%s: unable to alloc IO\n", __func__); in ocs_initiator_io()
1897 return -1; in ocs_initiator_io()
1902 io->tgt_io.app = ccb; in ocs_initiator_io()
1904 csio->ccb_h.ccb_ocs_ptr = ocs; in ocs_initiator_io()
1905 csio->ccb_h.ccb_io_ptr = io; in ocs_initiator_io()
1906 sgl = io->sgl; in ocs_initiator_io()
1908 sgl_count = ocs_build_scsi_sgl(ocs, ccb, io, sgl, io->sgl_allocated); in ocs_initiator_io()
1910 ocs_scsi_io_free(io); in ocs_initiator_io()
1911 device_printf(ocs->dev, "%s: building SGL failed\n", __func__); in ocs_initiator_io()
1912 return -1; in ocs_initiator_io()
1915 if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) { in ocs_initiator_io()
1916 io->timeout = 0; in ocs_initiator_io()
1917 } else if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT) { in ocs_initiator_io()
1918 io->timeout = OCS_CAM_IO_TIMEOUT; in ocs_initiator_io()
1920 if (ccb->ccb_h.timeout < 1000) in ocs_initiator_io()
1921 io->timeout = 1; in ocs_initiator_io()
1923 io->timeout = ccb->ccb_h.timeout / 1000; in ocs_initiator_io()
1927 switch (csio->tag_action) { in ocs_initiator_io()
1943 flags |= (csio->priority << OCS_SCSI_PRIORITY_SHIFT) & in ocs_initiator_io()
1946 switch (ccb->ccb_h.flags & CAM_DIR_MASK) { in ocs_initiator_io()
1948 rc = ocs_scsi_send_nodata_io(node, io, ccb_h->target_lun, in ocs_initiator_io()
1949 ccb->ccb_h.flags & CAM_CDB_POINTER ? in ocs_initiator_io()
1950 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, in ocs_initiator_io()
1951 csio->cdb_len, in ocs_initiator_io()
1955 rc = ocs_scsi_send_rd_io(node, io, ccb_h->target_lun, in ocs_initiator_io()
1956 ccb->ccb_h.flags & CAM_CDB_POINTER ? in ocs_initiator_io()
1957 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, in ocs_initiator_io()
1958 csio->cdb_len, in ocs_initiator_io()
1960 sgl, sgl_count, csio->dxfer_len, in ocs_initiator_io()
1964 rc = ocs_scsi_send_wr_io(node, io, ccb_h->target_lun, in ocs_initiator_io()
1965 ccb->ccb_h.flags & CAM_CDB_POINTER ? in ocs_initiator_io()
1966 csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, in ocs_initiator_io()
1967 csio->cdb_len, in ocs_initiator_io()
1969 sgl, sgl_count, csio->dxfer_len, in ocs_initiator_io()
1974 ccb->ccb_h.flags); in ocs_initiator_io()
1986 ocs_vport_spec_t *vport = fcp->vport; in ocs_fcp_change_role()
1988 for (was = 0, i = 0; i < (ocs->num_vports + 1); i++) { in ocs_fcp_change_role()
1989 if (FCPORT(ocs, i)->role != KNOB_ROLE_NONE) in ocs_fcp_change_role()
1995 fcp->role = new_role; in ocs_fcp_change_role()
1997 ocs->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; in ocs_fcp_change_role()
1998 ocs->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; in ocs_fcp_change_role()
2000 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; in ocs_fcp_change_role()
2001 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; in ocs_fcp_change_role()
2004 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); in ocs_fcp_change_role()
2009 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); in ocs_fcp_change_role()
2017 if ((fcp->role != KNOB_ROLE_NONE)){ in ocs_fcp_change_role()
2018 fcp->role = new_role; in ocs_fcp_change_role()
2019 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; in ocs_fcp_change_role()
2020 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; in ocs_fcp_change_role()
2022 return ocs_sport_vport_del(ocs, ocs->domain, vport->wwpn, vport->wwnn); in ocs_fcp_change_role()
2025 fcp->role = new_role; in ocs_fcp_change_role()
2027 vport->enable_ini = (new_role & KNOB_ROLE_INITIATOR)? 1:0; in ocs_fcp_change_role()
2028 vport->enable_tgt = (new_role & KNOB_ROLE_TARGET)? 1:0; in ocs_fcp_change_role()
2030 if (fcp->role != KNOB_ROLE_NONE) { in ocs_fcp_change_role()
2031 return ocs_sport_vport_alloc(ocs->domain, vport); in ocs_fcp_change_role()
2048 * - populate path inquiry data via info retrieved from SLI port
2054 struct ccb_hdr *ccb_h = &ccb->ccb_h; in ocs_action()
2059 switch (ccb_h->func_code) { in ocs_action()
2062 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { in ocs_action()
2063 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) { in ocs_action()
2064 ccb->ccb_h.status = CAM_REQ_INVALID; in ocs_action()
2076 cam_freeze_devq(ccb->ccb_h.path); in ocs_action()
2077 cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 100, 0); in ocs_action()
2078 ccb->ccb_h.status = CAM_REQUEUE_REQ; in ocs_action()
2083 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; in ocs_action()
2094 struct ccb_pathinq *cpi = &ccb->cpi; in ocs_action()
2095 struct ccb_pathinq_settings_fc *fc = &cpi->xport_specific.fc; in ocs_action()
2101 cpi->version_num = 1; in ocs_action()
2103 cpi->protocol = PROTO_SCSI; in ocs_action()
2104 cpi->protocol_version = SCSI_REV_SPC; in ocs_action()
2106 if (ocs->ocs_xport == OCS_XPORT_FC) { in ocs_action()
2107 cpi->transport = XPORT_FC; in ocs_action()
2109 cpi->transport = XPORT_UNKNOWN; in ocs_action()
2112 cpi->transport_version = 0; in ocs_action()
2115 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value); in ocs_action()
2116 fc->bitrate = value.value * 1000; /* speed in Mbps */ in ocs_action()
2119 fc->wwpn = be64toh(wwn); in ocs_action()
2122 fc->wwnn = be64toh(wwn); in ocs_action()
2124 fc->port = fcp->fc_id; in ocs_action()
2126 if (ocs->config_tgt) { in ocs_action()
2127 cpi->target_sprt = in ocs_action()
2131 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; in ocs_action()
2132 cpi->hba_misc |= PIM_EXTLUNS | PIM_NOSCAN; in ocs_action()
2134 cpi->hba_inquiry = PI_TAG_ABLE; in ocs_action()
2135 cpi->max_target = OCS_MAX_TARGETS; in ocs_action()
2136 cpi->initiator_id = ocs->max_remote_nodes + 1; in ocs_action()
2138 if (!ocs->enable_ini) { in ocs_action()
2139 cpi->hba_misc |= PIM_NOINITIATOR; in ocs_action()
2142 cpi->max_lun = OCS_MAX_LUN; in ocs_action()
2143 cpi->bus_id = cam_sim_bus(sim); in ocs_action()
2147 cpi->base_transfer_speed = 1 * 1000 * 1000; in ocs_action()
2149 /* Calculate the max IO supported in ocs_action()
2152 cpi->maxio = PAGE_SIZE * in ocs_action()
2153 (ocs_scsi_get_property(ocs, OCS_SCSI_MAX_SGL) - 1); in ocs_action()
2155 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); in ocs_action()
2156 strncpy(cpi->hba_vid, "Emulex", HBA_IDLEN); in ocs_action()
2157 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); in ocs_action()
2158 cpi->unit_number = cam_sim_unit(sim); in ocs_action()
2160 cpi->ccb_h.status = CAM_REQ_CMP; in ocs_action()
2166 struct ccb_trans_settings *cts = &ccb->cts; in ocs_action()
2167 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi; in ocs_action()
2168 struct ccb_trans_settings_fc *fc = &cts->xport_specific.fc; in ocs_action()
2173 if (ocs->ocs_xport != OCS_XPORT_FC) { in ocs_action()
2179 if (cts->ccb_h.target_id > OCS_MAX_TARGETS) { in ocs_action()
2185 tgt = &fcp->tgt[cts->ccb_h.target_id]; in ocs_action()
2186 if (tgt->state == OCS_TGT_STATE_NONE) { in ocs_action()
2192 cts->protocol = PROTO_SCSI; in ocs_action()
2193 cts->protocol_version = SCSI_REV_SPC2; in ocs_action()
2194 cts->transport = XPORT_FC; in ocs_action()
2195 cts->transport_version = 2; in ocs_action()
2197 scsi->valid = CTS_SCSI_VALID_TQ; in ocs_action()
2198 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; in ocs_action()
2201 ocs_xport_status(ocs->xport, OCS_XPORT_LINK_SPEED, &value); in ocs_action()
2202 fc->bitrate = value.value * 100; in ocs_action()
2204 fc->wwpn = tgt->wwpn; in ocs_action()
2206 fc->wwnn = tgt->wwnn; in ocs_action()
2208 fc->port = tgt->port_id; in ocs_action()
2210 fc->valid = CTS_FC_VALID_SPEED | in ocs_action()
2225 cam_calc_geometry(&ccb->ccg, TRUE); in ocs_action()
2231 struct ccb_sim_knob *knob = &ccb->knob; in ocs_action()
2235 if (ocs->ocs_xport != OCS_XPORT_FC) { in ocs_action()
2244 knob->xport_specific.fc.wwnn = be64toh(wwn); in ocs_action()
2248 knob->xport_specific.fc.wwpn = be64toh(wwn); in ocs_action()
2250 knob->xport_specific.fc.wwnn = fcp->vport->wwnn; in ocs_action()
2251 knob->xport_specific.fc.wwpn = fcp->vport->wwpn; in ocs_action()
2254 knob->xport_specific.fc.role = fcp->role; in ocs_action()
2255 knob->xport_specific.fc.valid = KNOB_VALID_ADDRESS | in ocs_action()
2264 struct ccb_sim_knob *knob = &ccb->knob; in ocs_action()
2268 if (ocs->ocs_xport != OCS_XPORT_FC) { in ocs_action()
2274 if (knob->xport_specific.fc.valid & KNOB_VALID_ADDRESS) { in ocs_action()
2275 device_printf(ocs->dev, in ocs_action()
2278 (unsigned long long)knob->xport_specific.fc.wwnn, in ocs_action()
2279 (unsigned long long)knob->xport_specific.fc.wwpn); in ocs_action()
2282 if (knob->xport_specific.fc.valid & KNOB_VALID_ROLE) { in ocs_action()
2283 switch (knob->xport_specific.fc.role) { in ocs_action()
2285 if (fcp->role != KNOB_ROLE_NONE) { in ocs_action()
2290 if (fcp->role != KNOB_ROLE_TARGET) { in ocs_action()
2295 if (fcp->role != KNOB_ROLE_INITIATOR) { in ocs_action()
2300 if (fcp->role != KNOB_ROLE_BOTH) { in ocs_action()
2305 device_printf(ocs->dev, in ocs_action()
2307 __func__, knob->xport_specific.fc.role); in ocs_action()
2311 device_printf(ocs->dev, in ocs_action()
2313 bus, fcp->role, knob->xport_specific.fc.role); in ocs_action()
2315 ocs_fcp_change_role(ocs, fcp, knob->xport_specific.fc.role); in ocs_action()
2327 union ccb *accb = ccb->cab.abort_ccb; in ocs_action()
2329 switch (accb->ccb_h.func_code) { in ocs_action()
2339 ccb->ccb_h.status = CAM_UA_ABORT; in ocs_action()
2341 ccb->ccb_h.status = CAM_REQ_CMP; in ocs_action()
2347 accb->ccb_h.func_code); in ocs_action()
2348 ccb->ccb_h.status = CAM_REQ_INVALID; in ocs_action()
2354 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE) == 0) { in ocs_action()
2355 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); in ocs_action()
2369 ocs_io_t *io = NULL; in ocs_action() local
2373 node = ocs_node_get_instance(ocs, fcp->tgt[ccb_h->target_id].node_id); in ocs_action()
2375 device_printf(ocs->dev, "%s: no device %d\n", in ocs_action()
2376 __func__, ccb_h->target_id); in ocs_action()
2382 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR); in ocs_action()
2383 if (io == NULL) { in ocs_action()
2384 device_printf(ocs->dev, "%s: unable to alloc IO\n", in ocs_action()
2391 rc = ocs_scsi_send_tmf(node, io, NULL, ccb_h->target_lun, in ocs_action()
2402 if (node->fcp2device) { in ocs_action()
2403 ocs_reset_crn(node, ccb_h->target_lun); in ocs_action()
2415 device_printf(ocs->dev, "XPT_EN_LUN %sable %d:%d\n", in ocs_action()
2416 ccb->cel.enable ? "en" : "dis", in ocs_action()
2417 ccb->ccb_h.target_id, in ocs_action()
2418 (unsigned int)ccb->ccb_h.target_lun); in ocs_action()
2420 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status); in ocs_action()
2422 trsrc->enabled = ccb->cel.enable; in ocs_action()
2425 if (trsrc->enabled == FALSE) { in ocs_action()
2428 STAILQ_INIT(&trsrc->atio); in ocs_action()
2429 STAILQ_INIT(&trsrc->inot); in ocs_action()
2440 * - CAM supplies a number of CCBs to the driver used for received in ocs_action()
2442 * - when the driver receives a command, it copies the relevant in ocs_action()
2444 * - after the target server processes the request, it creates in ocs_action()
2445 * a new CCB containing information on how to continue the IO and in ocs_action()
2447 * - the driver processes the "continue IO" (a.k.a CTIO) CCB in ocs_action()
2448 * - once the IO completes, the driver returns the CTIO to the CAM in ocs_action()
2460 /*printf("XPT_%s %p\n", ccb_h->func_code == XPT_ACCEPT_TARGET_IO ? in ocs_action()
2462 trsrc = ocs_tgt_resource_get(fcp, &ccb->ccb_h, &status); in ocs_action()
2469 if (XPT_ACCEPT_TARGET_IO == ccb->ccb_h.func_code) { in ocs_action()
2473 atio->init_id = 0x0badbeef; in ocs_action()
2474 atio->tag_id = 0xdeadc0de; in ocs_action()
2476 STAILQ_INSERT_TAIL(&trsrc->atio, &ccb->ccb_h, in ocs_action()
2479 STAILQ_INSERT_TAIL(&trsrc->inot, &ccb->ccb_h, in ocs_action()
2482 ccb->ccb_h.ccb_io_ptr = NULL; in ocs_action()
2483 ccb->ccb_h.ccb_ocs_ptr = ocs; in ocs_action()
2489 * IO or other event had arrived. in ocs_action()
2495 ocs_io_t *io = NULL; in ocs_action() local
2498 /* Get the IO reference for this tag */ in ocs_action()
2499 io = ocs_scsi_find_io(ocs, ccb->cna2.tag_id); in ocs_action()
2500 if (io == NULL) { in ocs_action()
2501 device_printf(ocs->dev, in ocs_action()
2502 "%s: XPT_NOTIFY_ACKNOWLEDGE no IO with tag %#x\n", in ocs_action()
2503 __func__, ccb->cna2.tag_id); in ocs_action()
2509 abortio = io->tgt_io.app; in ocs_action()
2511 abortio->tgt_io.flags &= ~OCS_CAM_IO_F_ABORT_NOTIFY; in ocs_action()
2512 device_printf(ocs->dev, in ocs_action()
2514 " flags=%#x\n", __func__, abortio->tgt_io.state, in ocs_action()
2515 abortio->tag, abortio->init_task_tag, in ocs_action()
2516 abortio->tgt_io.flags); in ocs_action()
2519 ocs_scsi_send_tmf_resp(io, in ocs_action()
2528 case XPT_CONT_TARGET_IO: /* continue target IO, sending data/response (a.k.a. CTIO) */ in ocs_action()
2530 device_printf(ocs->dev, in ocs_action()
2532 ccb->ccb_h.flags, ccb->csio.tag_id); in ocs_action()
2537 device_printf(ocs->dev, "unhandled func_code = %#x\n", in ocs_action()
2538 ccb_h->func_code); in ocs_action()
2539 ccb_h->status = CAM_REQ_INVALID; in ocs_action()
2559 ocs_initiator_tmf_cb(ocs_io_t *io, ocs_scsi_io_status_e scsi_status, in ocs_initiator_tmf_cb() argument
2569 if (rsp->response_data_length == 0) { in ocs_initiator_tmf_cb()
2570 ocs_log_test(io->ocs, "check response without data?!?\n"); in ocs_initiator_tmf_cb()
2571 rc = -1; in ocs_initiator_tmf_cb()
2575 if (rsp->response_data[3] != 0) { in ocs_initiator_tmf_cb()
2576 ocs_log_test(io->ocs, "TMF status %08x\n", in ocs_initiator_tmf_cb()
2577 be32toh(*((uint32_t *)rsp->response_data))); in ocs_initiator_tmf_cb()
2578 rc = -1; in ocs_initiator_tmf_cb()
2583 ocs_log_test(io->ocs, "status=%#x\n", scsi_status); in ocs_initiator_tmf_cb()
2584 rc = -1; in ocs_initiator_tmf_cb()
2587 ocs_scsi_io_free(io); in ocs_initiator_tmf_cb()
2596 * - wildcard target ID + LU
2597 * - 0 target ID + non-wildcard LU
2609 target_id_t tid = ccb_h->target_id; in ocs_tgt_resource_get()
2610 lun_id_t lun = ccb_h->target_lun; in ocs_tgt_resource_get()
2617 return &fcp->targ_rsrc_wildcard; in ocs_tgt_resource_get()
2620 return &fcp->targ_rsrc[lun]; in ocs_tgt_resource_get()
2635 ccb = (union ccb *)STAILQ_FIRST(&trsrc->atio); in ocs_tgt_resource_abort()
2637 STAILQ_REMOVE_HEAD(&trsrc->atio, sim_links.stqe); in ocs_tgt_resource_abort()
2638 ccb->ccb_h.status = CAM_REQ_ABORTED; in ocs_tgt_resource_abort()
2644 ccb = (union ccb *)STAILQ_FIRST(&trsrc->inot); in ocs_tgt_resource_abort()
2646 STAILQ_REMOVE_HEAD(&trsrc->inot, sim_links.stqe); in ocs_tgt_resource_abort()
2647 ccb->ccb_h.status = CAM_REQ_ABORTED; in ocs_tgt_resource_abort()
2663 union ccb *accb = ccb->cab.abort_ccb; in ocs_abort_atio()
2665 int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)); in ocs_abort_atio()
2668 trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status); in ocs_abort_atio()
2670 STAILQ_FOREACH(cur, &trsrc->atio, sim_links.stqe) { in ocs_abort_atio()
2671 if (cur != &accb->ccb_h) in ocs_abort_atio()
2674 STAILQ_REMOVE(&trsrc->atio, cur, ccb_hdr, in ocs_abort_atio()
2676 accb->ccb_h.status = CAM_REQ_ABORTED; in ocs_abort_atio()
2683 /* if the ATIO has a valid IO pointer, CAM is telling in ocs_abort_atio()
2687 aio = accb->ccb_h.ccb_io_ptr; in ocs_abort_atio()
2689 ccb->ccb_h.status = CAM_UA_ABORT; in ocs_abort_atio()
2693 device_printf(ocs->dev, in ocs_abort_atio()
2696 aio->tgt_io.state, aio->tag, in ocs_abort_atio()
2697 aio->init_task_tag, aio->tgt_io.flags); in ocs_abort_atio()
2699 * - abort task was received in ocs_abort_atio()
2700 * - already aborted IO in the DEVICE in ocs_abort_atio()
2701 * - already received NOTIFY ACKNOWLEDGE */ in ocs_abort_atio()
2703 if ((aio->tgt_io.flags & OCS_CAM_IO_F_ABORT_RECV) == 0) { in ocs_abort_atio()
2704 device_printf(ocs->dev, "%s: abort not received or io completed \n", __func__); in ocs_abort_atio()
2709 aio->tgt_io.flags |= OCS_CAM_IO_F_ABORT_CAM; in ocs_abort_atio()
2722 union ccb *accb = ccb->cab.abort_ccb; in ocs_abort_inot()
2724 int bus = cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)); in ocs_abort_inot()
2727 trsrc = ocs_tgt_resource_get(fcp, &accb->ccb_h, &status); in ocs_abort_inot()
2729 STAILQ_FOREACH(cur, &trsrc->inot, sim_links.stqe) { in ocs_abort_inot()
2730 if (cur != &accb->ccb_h) in ocs_abort_inot()
2733 STAILQ_REMOVE(&trsrc->inot, cur, ccb_hdr, in ocs_abort_inot()
2735 accb->ccb_h.status = CAM_REQ_ABORTED; in ocs_abort_inot()
2751 ocs_io_t *io = NULL; in ocs_abort_initiator_io() local
2753 struct ccb_scsiio *csio = &accb->csio; in ocs_abort_initiator_io()
2755 ocs_fcport *fcp = FCPORT(ocs, cam_sim_bus(xpt_path_sim((accb)->ccb_h.path))); in ocs_abort_initiator_io()
2756 node = ocs_node_get_instance(ocs, fcp->tgt[accb->ccb_h.target_id].node_id); in ocs_abort_initiator_io()
2758 device_printf(ocs->dev, "%s: no device %d\n", in ocs_abort_initiator_io()
2759 __func__, accb->ccb_h.target_id); in ocs_abort_initiator_io()
2762 return (-1); in ocs_abort_initiator_io()
2765 io = ocs_scsi_io_alloc(node, OCS_SCSI_IO_ROLE_ORIGINATOR); in ocs_abort_initiator_io()
2766 if (io == NULL) { in ocs_abort_initiator_io()
2767 device_printf(ocs->dev, in ocs_abort_initiator_io()
2768 "%s: unable to alloc IO\n", __func__); in ocs_abort_initiator_io()
2771 return (-1); in ocs_abort_initiator_io()
2774 rc = ocs_scsi_send_tmf(node, io, in ocs_abort_initiator_io()
2775 (ocs_io_t *)csio->ccb_h.ccb_io_ptr, in ocs_abort_initiator_io()
2776 accb->ccb_h.target_lun, in ocs_abort_initiator_io()
2805 //ocs_io_t *io = obj; in ocs_scsi_ini_ddump()
2835 ocs_io_t *io = obj; in ocs_scsi_tgt_ddump() local
2838 switch (io->tgt_io.state) { in ocs_scsi_tgt_ddump()
2858 if (io->tgt_io.app) { in ocs_scsi_tgt_ddump()
2860 ((union ccb *)(io->tgt_io.app))->ccb_h.flags); in ocs_scsi_tgt_ddump()
2862 ((union ccb *)(io->tgt_io.app))->ccb_h.status); in ocs_scsi_tgt_ddump()
2873 int32_t ocs_scsi_get_block_vaddr(ocs_io_t *io, uint64_t blocknumber, in ocs_scsi_get_block_vaddr() argument
2877 return -1; in ocs_scsi_get_block_vaddr()
2887 lcrn = node->ini_node.lun_crn[idx]; in ocs_get_crn()
2890 lcrn = ocs_malloc(node->ocs, sizeof(struct ocs_lun_crn), in ocs_get_crn()
2896 lcrn->lun = lun; in ocs_get_crn()
2897 node->ini_node.lun_crn[idx] = lcrn; in ocs_get_crn()
2900 if (lcrn->lun != lun) { in ocs_get_crn()
2904 if (lcrn->crnseed == 0) in ocs_get_crn()
2905 lcrn->crnseed = 1; in ocs_get_crn()
2907 *crn = lcrn->crnseed++; in ocs_get_crn()
2918 lcrn = node->ini_node.lun_crn[i]; in ocs_del_crn()
2920 ocs_free(node->ocs, lcrn, sizeof(*lcrn)); in ocs_del_crn()
2934 lcrn = node->ini_node.lun_crn[idx]; in ocs_reset_crn()
2936 lcrn->crnseed = 0; in ocs_reset_crn()