Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ctl/ctl.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
| Show First 20 Lines • Show All 611 Lines • ▼ Show 20 Lines | |||||
| ctl_ha_datamove(union ctl_io *io) | ctl_ha_datamove(union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_lun *lun = CTL_LUN(io); | struct ctl_lun *lun = CTL_LUN(io); | ||||
| struct ctl_sg_entry *sgl; | struct ctl_sg_entry *sgl; | ||||
| union ctl_ha_msg msg; | union ctl_ha_msg msg; | ||||
| uint32_t sg_entries_sent; | uint32_t sg_entries_sent; | ||||
| int do_sg_copy, i, j; | int do_sg_copy, i, j; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| memset(&msg.dt, 0, sizeof(msg.dt)); | memset(&msg.dt, 0, sizeof(msg.dt)); | ||||
| msg.hdr.msg_type = CTL_MSG_DATAMOVE; | msg.hdr.msg_type = CTL_MSG_DATAMOVE; | ||||
| msg.hdr.original_sc = io->io_hdr.remote_io; | msg.hdr.original_sc = io->io_hdr.remote_io; | ||||
| msg.hdr.serializing_sc = io; | msg.hdr.serializing_sc = io; | ||||
| msg.hdr.nexus = io->io_hdr.nexus; | msg.hdr.nexus = io->io_hdr.nexus; | ||||
| msg.hdr.status = io->io_hdr.status; | msg.hdr.status = io->io_hdr.status; | ||||
| msg.dt.flags = io->io_hdr.flags; | msg.dt.flags = io->io_hdr.flags; | ||||
| ▲ Show 20 Lines • Show All 895 Lines • ▼ Show 20 Lines | case CTL_MSG_DATAMOVE: { | ||||
| int i, j; | int i, j; | ||||
| io = msg->hdr.original_sc; | io = msg->hdr.original_sc; | ||||
| if (io == NULL) { | if (io == NULL) { | ||||
| printf("%s: original_sc == NULL!\n", __func__); | printf("%s: original_sc == NULL!\n", __func__); | ||||
| /* XXX KDM do something here */ | /* XXX KDM do something here */ | ||||
| break; | break; | ||||
| } | } | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| io->io_hdr.msg_type = CTL_MSG_DATAMOVE; | io->io_hdr.msg_type = CTL_MSG_DATAMOVE; | ||||
| io->io_hdr.flags |= CTL_FLAG_IO_ACTIVE; | io->io_hdr.flags |= CTL_FLAG_IO_ACTIVE; | ||||
| /* | /* | ||||
| * Keep track of this, we need to send it back over | * Keep track of this, we need to send it back over | ||||
| * when the datamove is complete. | * when the datamove is complete. | ||||
| */ | */ | ||||
| io->io_hdr.remote_io = msg->hdr.serializing_sc; | io->io_hdr.remote_io = msg->hdr.serializing_sc; | ||||
| if (msg->hdr.status == CTL_SUCCESS) | if (msg->hdr.status == CTL_SUCCESS) | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | case CTL_MSG_DATAMOVE_DONE: { | ||||
| break; | break; | ||||
| } | } | ||||
| /* | /* | ||||
| * We grab the sense information here in case | * We grab the sense information here in case | ||||
| * there was a failure, so we can return status | * there was a failure, so we can return status | ||||
| * back to the initiator. | * back to the initiator. | ||||
| */ | */ | ||||
| io = msg->hdr.serializing_sc; | io = msg->hdr.serializing_sc; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| io->io_hdr.msg_type = CTL_MSG_DATAMOVE_DONE; | io->io_hdr.msg_type = CTL_MSG_DATAMOVE_DONE; | ||||
| io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; | io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; | ||||
| io->io_hdr.flags |= CTL_FLAG_IO_ACTIVE; | io->io_hdr.flags |= CTL_FLAG_IO_ACTIVE; | ||||
| io->io_hdr.port_status = msg->scsi.port_status; | io->io_hdr.port_status = msg->scsi.port_status; | ||||
| io->scsiio.kern_data_resid = msg->scsi.kern_data_resid; | io->scsiio.kern_data_resid = msg->scsi.kern_data_resid; | ||||
| if (msg->hdr.status != CTL_STATUS_NONE) { | if (msg->hdr.status != CTL_STATUS_NONE) { | ||||
| io->io_hdr.status = msg->hdr.status; | io->io_hdr.status = msg->hdr.status; | ||||
| io->scsiio.scsi_status = msg->scsi.scsi_status; | io->scsiio.scsi_status = msg->scsi.scsi_status; | ||||
| ▲ Show 20 Lines • Show All 825 Lines • ▼ Show 20 Lines | if (ioh == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| while (LIST_NEXT(ioh, ooa_links) != NULL) | while (LIST_NEXT(ioh, ooa_links) != NULL) | ||||
| ioh = LIST_NEXT(ioh, ooa_links); | ioh = LIST_NEXT(ioh, ooa_links); | ||||
| for ( ; ioh; ioh = LIST_PREV(ioh, &lun->ooa_queue, ctl_io_hdr, ooa_links)) { | for ( ; ioh; ioh = LIST_PREV(ioh, &lun->ooa_queue, ctl_io_hdr, ooa_links)) { | ||||
| union ctl_io *io = (union ctl_io *)ioh; | union ctl_io *io = (union ctl_io *)ioh; | ||||
| struct ctl_ooa_entry *entry; | struct ctl_ooa_entry *entry; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| /* | /* | ||||
| * If we've got more than we can fit, just count the | * If we've got more than we can fit, just count the | ||||
| * remaining entries. | * remaining entries. | ||||
| */ | */ | ||||
| if (*cur_fill_num >= ooa_hdr->alloc_num) { | if (*cur_fill_num >= ooa_hdr->alloc_num) { | ||||
| (*cur_fill_num)++; | (*cur_fill_num)++; | ||||
| continue; | continue; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 3,085 Lines • ▼ Show 20 Lines | |||||
| static int | static int | ||||
| ctl_write_same_cont(union ctl_io *io) | ctl_write_same_cont(union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_lun *lun = CTL_LUN(io); | struct ctl_lun *lun = CTL_LUN(io); | ||||
| struct ctl_scsiio *ctsio; | struct ctl_scsiio *ctsio; | ||||
| struct ctl_lba_len_flags *lbalen; | struct ctl_lba_len_flags *lbalen; | ||||
| int retval; | int retval; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| ctsio = &io->scsiio; | ctsio = &io->scsiio; | ||||
| ctsio->io_hdr.status = CTL_STATUS_NONE; | ctsio->io_hdr.status = CTL_STATUS_NONE; | ||||
| lbalen = (struct ctl_lba_len_flags *) | lbalen = (struct ctl_lba_len_flags *) | ||||
| &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; | &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; | ||||
| lbalen->lba += lbalen->len; | lbalen->lba += lbalen->len; | ||||
| if ((lun->be_lun->maxlba + 1) - lbalen->lba <= UINT32_MAX) { | if ((lun->be_lun->maxlba + 1) - lbalen->lba <= UINT32_MAX) { | ||||
| ctsio->io_hdr.flags &= ~CTL_FLAG_IO_CONT; | ctsio->io_hdr.flags &= ~CTL_FLAG_IO_CONT; | ||||
| lbalen->len = (lun->be_lun->maxlba + 1) - lbalen->lba; | lbalen->len = (lun->be_lun->maxlba + 1) - lbalen->lba; | ||||
| ▲ Show 20 Lines • Show All 329 Lines • ▼ Show 20 Lines | ctl_do_mode_select(union ctl_io *io) | ||||
| struct scsi_mode_page_header *page_header; | struct scsi_mode_page_header *page_header; | ||||
| struct ctl_page_index *page_index; | struct ctl_page_index *page_index; | ||||
| struct ctl_scsiio *ctsio; | struct ctl_scsiio *ctsio; | ||||
| int page_len, page_len_offset, page_len_size; | int page_len, page_len_offset, page_len_size; | ||||
| union ctl_modepage_info *modepage_info; | union ctl_modepage_info *modepage_info; | ||||
| uint16_t *len_left, *len_used; | uint16_t *len_left, *len_used; | ||||
| int retval, i; | int retval, i; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| ctsio = &io->scsiio; | ctsio = &io->scsiio; | ||||
| page_index = NULL; | page_index = NULL; | ||||
| page_len = 0; | page_len = 0; | ||||
| modepage_info = (union ctl_modepage_info *) | modepage_info = (union ctl_modepage_info *) | ||||
| ctsio->io_hdr.ctl_private[CTL_PRIV_MODEPAGE].bytes; | ctsio->io_hdr.ctl_private[CTL_PRIV_MODEPAGE].bytes; | ||||
| len_left = &modepage_info->header.len_left; | len_left = &modepage_info->header.len_left; | ||||
| len_used = &modepage_info->header.len_used; | len_used = &modepage_info->header.len_used; | ||||
| ▲ Show 20 Lines • Show All 2,897 Lines • ▼ Show 20 Lines | |||||
| static int | static int | ||||
| ctl_cnw_cont(union ctl_io *io) | ctl_cnw_cont(union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_lun *lun = CTL_LUN(io); | struct ctl_lun *lun = CTL_LUN(io); | ||||
| struct ctl_scsiio *ctsio; | struct ctl_scsiio *ctsio; | ||||
| struct ctl_lba_len_flags *lbalen; | struct ctl_lba_len_flags *lbalen; | ||||
| int retval; | int retval; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| ctsio = &io->scsiio; | ctsio = &io->scsiio; | ||||
| ctsio->io_hdr.status = CTL_STATUS_NONE; | ctsio->io_hdr.status = CTL_STATUS_NONE; | ||||
| ctsio->io_hdr.flags &= ~CTL_FLAG_IO_CONT; | ctsio->io_hdr.flags &= ~CTL_FLAG_IO_CONT; | ||||
| lbalen = (struct ctl_lba_len_flags *) | lbalen = (struct ctl_lba_len_flags *) | ||||
| &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; | &ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN]; | ||||
| lbalen->flags &= ~CTL_LLF_COMPARE; | lbalen->flags &= ~CTL_LLF_COMPARE; | ||||
| lbalen->flags |= CTL_LLF_WRITE; | lbalen->flags |= CTL_LLF_WRITE; | ||||
| ▲ Show 20 Lines • Show All 2,024 Lines • ▼ Show 20 Lines | if (lba1 + len1 == lba2) | ||||
| return (CTL_ACTION_BLOCK); | return (CTL_ACTION_BLOCK); | ||||
| return (CTL_ACTION_PASS); | return (CTL_ACTION_PASS); | ||||
| } | } | ||||
| static ctl_action | static ctl_action | ||||
| ctl_check_for_blockage(struct ctl_lun *lun, union ctl_io *pending_io, | ctl_check_for_blockage(struct ctl_lun *lun, union ctl_io *pending_io, | ||||
| const uint8_t *serialize_row, union ctl_io *ooa_io) | const uint8_t *serialize_row, union ctl_io *ooa_io) | ||||
| { | { | ||||
| CTL_IO_ASSERT(pending_io, SCSI); | |||||
| CTL_IO_ASSERT(ooa_io, SCSI); | |||||
| /* | /* | ||||
| * The initiator attempted multiple untagged commands at the same | * The initiator attempted multiple untagged commands at the same | ||||
| * time. Can't do that. | * time. Can't do that. | ||||
| */ | */ | ||||
| if (__predict_false(pending_io->scsiio.tag_type == CTL_TAG_UNTAGGED) | if (__predict_false(pending_io->scsiio.tag_type == CTL_TAG_UNTAGGED) | ||||
| && __predict_false(ooa_io->scsiio.tag_type == CTL_TAG_UNTAGGED) | && __predict_false(ooa_io->scsiio.tag_type == CTL_TAG_UNTAGGED) | ||||
| && ((pending_io->io_hdr.nexus.targ_port == | && ((pending_io->io_hdr.nexus.targ_port == | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| static ctl_action | static ctl_action | ||||
| ctl_check_ooa(struct ctl_lun *lun, union ctl_io *pending_io, | ctl_check_ooa(struct ctl_lun *lun, union ctl_io *pending_io, | ||||
| union ctl_io **starting_io) | union ctl_io **starting_io) | ||||
| { | { | ||||
| union ctl_io *ooa_io = *starting_io; | union ctl_io *ooa_io = *starting_io; | ||||
| const uint8_t *serialize_row; | const uint8_t *serialize_row; | ||||
| ctl_action action; | ctl_action action; | ||||
| CTL_IO_ASSERT(pending_io, SCSI); | |||||
| mtx_assert(&lun->lun_lock, MA_OWNED); | mtx_assert(&lun->lun_lock, MA_OWNED); | ||||
| /* | /* | ||||
| * Aborted commands are not going to be executed and may even | * Aborted commands are not going to be executed and may even | ||||
| * not report completion, so we don't care about their order. | * not report completion, so we don't care about their order. | ||||
| * Let them complete ASAP to clean the OOA queue. | * Let them complete ASAP to clean the OOA queue. | ||||
| */ | */ | ||||
| if (__predict_false(pending_io->io_hdr.flags & CTL_FLAG_ABORT)) | if (__predict_false(pending_io->io_hdr.flags & CTL_FLAG_ABORT)) | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
| ctl_try_unblock_io(struct ctl_lun *lun, union ctl_io *io, bool skip) | ctl_try_unblock_io(struct ctl_lun *lun, union ctl_io *io, bool skip) | ||||
| { | { | ||||
| struct ctl_softc *softc = lun->ctl_softc; | struct ctl_softc *softc = lun->ctl_softc; | ||||
| union ctl_io *bio, *obio; | union ctl_io *bio, *obio; | ||||
| const struct ctl_cmd_entry *entry; | const struct ctl_cmd_entry *entry; | ||||
| union ctl_ha_msg msg_info; | union ctl_ha_msg msg_info; | ||||
| ctl_action action; | ctl_action action; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| mtx_assert(&lun->lun_lock, MA_OWNED); | mtx_assert(&lun->lun_lock, MA_OWNED); | ||||
| if (io->io_hdr.blocker == NULL) | if (io->io_hdr.blocker == NULL) | ||||
| return; | return; | ||||
| obio = bio = io->io_hdr.blocker; | obio = bio = io->io_hdr.blocker; | ||||
| if (skip) | if (skip) | ||||
| bio = (union ctl_io *)LIST_NEXT(&bio->io_hdr, ooa_links); | bio = (union ctl_io *)LIST_NEXT(&bio->io_hdr, ooa_links); | ||||
| ▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | |||||
| bailout: | bailout: | ||||
| return (retval); | return (retval); | ||||
| } | } | ||||
| static void | static void | ||||
| ctl_failover_io(union ctl_io *io, int have_lock) | ctl_failover_io(union ctl_io *io, int have_lock) | ||||
| { | { | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| ctl_set_busy(&io->scsiio); | ctl_set_busy(&io->scsiio); | ||||
| ctl_done(io); | ctl_done(io); | ||||
| } | } | ||||
| static void | static void | ||||
| ctl_failover_lun(union ctl_io *rio) | ctl_failover_lun(union ctl_io *rio) | ||||
| { | { | ||||
| struct ctl_softc *softc = CTL_SOFTC(rio); | struct ctl_softc *softc = CTL_SOFTC(rio); | ||||
| ▲ Show 20 Lines • Show All 551 Lines • ▼ Show 20 Lines | if ((targ_port == UINT32_MAX || | ||||
| init_id == xioh->nexus.initid)) { | init_id == xioh->nexus.initid)) { | ||||
| if (targ_port != xioh->nexus.targ_port || | if (targ_port != xioh->nexus.targ_port || | ||||
| init_id != xioh->nexus.initid) | init_id != xioh->nexus.initid) | ||||
| xioh->flags |= CTL_FLAG_ABORT_STATUS; | xioh->flags |= CTL_FLAG_ABORT_STATUS; | ||||
| xioh->flags |= CTL_FLAG_ABORT; | xioh->flags |= CTL_FLAG_ABORT; | ||||
| if (!other_sc && !(lun->flags & CTL_LUN_PRIMARY_SC)) { | if (!other_sc && !(lun->flags & CTL_LUN_PRIMARY_SC)) { | ||||
| union ctl_ha_msg msg_info; | union ctl_ha_msg msg_info; | ||||
| CTL_IO_ASSERT(xio, SCSI); | |||||
| msg_info.hdr.nexus = xioh->nexus; | msg_info.hdr.nexus = xioh->nexus; | ||||
| msg_info.task.task_action = CTL_TASK_ABORT_TASK; | msg_info.task.task_action = CTL_TASK_ABORT_TASK; | ||||
| msg_info.task.tag_num = xio->scsiio.tag_num; | msg_info.task.tag_num = xio->scsiio.tag_num; | ||||
| msg_info.task.tag_type = xio->scsiio.tag_type; | msg_info.task.tag_type = xio->scsiio.tag_type; | ||||
| msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS; | msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS; | ||||
| msg_info.hdr.original_sc = NULL; | msg_info.hdr.original_sc = NULL; | ||||
| msg_info.hdr.serializing_sc = NULL; | msg_info.hdr.serializing_sc = NULL; | ||||
| ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info, | ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info, | ||||
| ▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | ctl_abort_task(union ctl_io *io) | ||||
| * Run through the OOA queue and attempt to find the given I/O. | * Run through the OOA queue and attempt to find the given I/O. | ||||
| * The target port, initiator ID, tag type and tag number have to | * The target port, initiator ID, tag type and tag number have to | ||||
| * match the values that we got from the initiator. If we have an | * match the values that we got from the initiator. If we have an | ||||
| * untagged command to abort, simply abort the first untagged command | * untagged command to abort, simply abort the first untagged command | ||||
| * we come to. We only allow one untagged command at a time of course. | * we come to. We only allow one untagged command at a time of course. | ||||
| */ | */ | ||||
| LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) { | LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) { | ||||
| union ctl_io *xio = (union ctl_io *)xioh; | union ctl_io *xio = (union ctl_io *)xioh; | ||||
| CTL_IO_ASSERT(xio, SCSI); | |||||
| if ((xioh->nexus.targ_port != io->io_hdr.nexus.targ_port) | if ((xioh->nexus.targ_port != io->io_hdr.nexus.targ_port) | ||||
| || (xioh->nexus.initid != io->io_hdr.nexus.initid) | || (xioh->nexus.initid != io->io_hdr.nexus.initid) | ||||
| || (xioh->flags & CTL_FLAG_ABORT)) | || (xioh->flags & CTL_FLAG_ABORT)) | ||||
| continue; | continue; | ||||
| /* | /* | ||||
| * If the abort says that the task is untagged, the | * If the abort says that the task is untagged, the | ||||
| * task in the queue must be untagged. Otherwise, | * task in the queue must be untagged. Otherwise, | ||||
| ▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | if (targ_lun >= ctl_max_luns || | ||||
| mtx_unlock(&softc->ctl_lock); | mtx_unlock(&softc->ctl_lock); | ||||
| io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST; | io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST; | ||||
| return (1); | return (1); | ||||
| } | } | ||||
| mtx_lock(&lun->lun_lock); | mtx_lock(&lun->lun_lock); | ||||
| mtx_unlock(&softc->ctl_lock); | mtx_unlock(&softc->ctl_lock); | ||||
| LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) { | LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) { | ||||
| union ctl_io *xio = (union ctl_io *)xioh; | union ctl_io *xio = (union ctl_io *)xioh; | ||||
| CTL_IO_ASSERT(xio, SCSI); | |||||
| if ((xioh->nexus.targ_port != io->io_hdr.nexus.targ_port) | if ((xioh->nexus.targ_port != io->io_hdr.nexus.targ_port) | ||||
| || (xioh->nexus.initid != io->io_hdr.nexus.initid) | || (xioh->nexus.initid != io->io_hdr.nexus.initid) | ||||
| || (xioh->flags & CTL_FLAG_ABORT)) | || (xioh->flags & CTL_FLAG_ABORT)) | ||||
| continue; | continue; | ||||
| if (task_set || xio->scsiio.tag_num == io->taskio.tag_num) { | if (task_set || xio->scsiio.tag_num == io->taskio.tag_num) { | ||||
| found = 1; | found = 1; | ||||
| break; | break; | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
| static void | static void | ||||
| ctl_handle_isc(union ctl_io *io) | ctl_handle_isc(union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_softc *softc = CTL_SOFTC(io); | struct ctl_softc *softc = CTL_SOFTC(io); | ||||
| struct ctl_lun *lun; | struct ctl_lun *lun; | ||||
| const struct ctl_cmd_entry *entry; | const struct ctl_cmd_entry *entry; | ||||
| uint32_t targ_lun; | uint32_t targ_lun; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| targ_lun = io->io_hdr.nexus.targ_mapped_lun; | targ_lun = io->io_hdr.nexus.targ_mapped_lun; | ||||
| switch (io->io_hdr.msg_type) { | switch (io->io_hdr.msg_type) { | ||||
| case CTL_MSG_SERIALIZE: | case CTL_MSG_SERIALIZE: | ||||
| ctl_serialize_other_sc_cmd(&io->scsiio); | ctl_serialize_other_sc_cmd(&io->scsiio); | ||||
| break; | break; | ||||
| case CTL_MSG_R2R: /* Only used in SER_ONLY mode. */ | case CTL_MSG_R2R: /* Only used in SER_ONLY mode. */ | ||||
| entry = ctl_get_cmd_entry(&io->scsiio, NULL); | entry = ctl_get_cmd_entry(&io->scsiio, NULL); | ||||
| if (targ_lun >= ctl_max_luns || | if (targ_lun >= ctl_max_luns || | ||||
| ▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | ctl_cmd_pattern_match(struct ctl_scsiio *ctsio, struct ctl_error_desc *desc) | ||||
| return (filtered_pattern); | return (filtered_pattern); | ||||
| } | } | ||||
| static void | static void | ||||
| ctl_inject_error(struct ctl_lun *lun, union ctl_io *io) | ctl_inject_error(struct ctl_lun *lun, union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_error_desc *desc, *desc2; | struct ctl_error_desc *desc, *desc2; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| mtx_assert(&lun->lun_lock, MA_OWNED); | mtx_assert(&lun->lun_lock, MA_OWNED); | ||||
| STAILQ_FOREACH_SAFE(desc, &lun->error_list, links, desc2) { | STAILQ_FOREACH_SAFE(desc, &lun->error_list, links, desc2) { | ||||
| ctl_lun_error_pattern pattern; | ctl_lun_error_pattern pattern; | ||||
| /* | /* | ||||
| * Check to see whether this particular command matches | * Check to see whether this particular command matches | ||||
| * the pattern in the descriptor. | * the pattern in the descriptor. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | |||||
| static void | static void | ||||
| ctl_send_datamove_done(union ctl_io *io, int have_lock) | ctl_send_datamove_done(union ctl_io *io, int have_lock) | ||||
| { | { | ||||
| union ctl_ha_msg msg; | union ctl_ha_msg msg; | ||||
| #ifdef CTL_TIME_IO | #ifdef CTL_TIME_IO | ||||
| struct bintime cur_bt; | struct bintime cur_bt; | ||||
| #endif | #endif | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| memset(&msg, 0, sizeof(msg)); | memset(&msg, 0, sizeof(msg)); | ||||
| msg.hdr.msg_type = CTL_MSG_DATAMOVE_DONE; | msg.hdr.msg_type = CTL_MSG_DATAMOVE_DONE; | ||||
| msg.hdr.original_sc = io; | msg.hdr.original_sc = io; | ||||
| msg.hdr.serializing_sc = io->io_hdr.remote_io; | msg.hdr.serializing_sc = io->io_hdr.remote_io; | ||||
| msg.hdr.nexus = io->io_hdr.nexus; | msg.hdr.nexus = io->io_hdr.nexus; | ||||
| msg.hdr.status = io->io_hdr.status; | msg.hdr.status = io->io_hdr.status; | ||||
| msg.scsi.kern_data_resid = io->scsiio.kern_data_resid; | msg.scsi.kern_data_resid = io->scsiio.kern_data_resid; | ||||
| msg.scsi.tag_num = io->scsiio.tag_num; | msg.scsi.tag_num = io->scsiio.tag_num; | ||||
| Show All 26 Lines | |||||
| */ | */ | ||||
| static void | static void | ||||
| ctl_datamove_remote_write_cb(struct ctl_ha_dt_req *rq) | ctl_datamove_remote_write_cb(struct ctl_ha_dt_req *rq) | ||||
| { | { | ||||
| union ctl_io *io; | union ctl_io *io; | ||||
| uint32_t i; | uint32_t i; | ||||
| io = rq->context; | io = rq->context; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| if (rq->ret != CTL_HA_STATUS_SUCCESS) { | if (rq->ret != CTL_HA_STATUS_SUCCESS) { | ||||
| printf("%s: ISC DMA write failed with error %d", __func__, | printf("%s: ISC DMA write failed with error %d", __func__, | ||||
| rq->ret); | rq->ret); | ||||
| ctl_set_internal_failure(&io->scsiio, | ctl_set_internal_failure(&io->scsiio, | ||||
| /*sks_valid*/ 1, | /*sks_valid*/ 1, | ||||
| /*retry_count*/ rq->ret); | /*retry_count*/ rq->ret); | ||||
| } | } | ||||
| Show All 28 Lines | |||||
| } | } | ||||
| static void | static void | ||||
| ctl_datamove_remote_write(union ctl_io *io) | ctl_datamove_remote_write(union ctl_io *io) | ||||
| { | { | ||||
| int retval; | int retval; | ||||
| void (*fe_datamove)(union ctl_io *io); | void (*fe_datamove)(union ctl_io *io); | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| /* | /* | ||||
| * - Get the data from the host/HBA into local memory. | * - Get the data from the host/HBA into local memory. | ||||
| * - DMA memory from the local controller to the remote controller. | * - DMA memory from the local controller to the remote controller. | ||||
| * - Send status back to the remote controller. | * - Send status back to the remote controller. | ||||
| */ | */ | ||||
| retval = ctl_datamove_remote_sgl_setup(io); | retval = ctl_datamove_remote_sgl_setup(io); | ||||
| if (retval != 0) | if (retval != 0) | ||||
| Show All 12 Lines | ctl_datamove_remote_write(union ctl_io *io) | ||||
| fe_datamove(io); | fe_datamove(io); | ||||
| } | } | ||||
| static int | static int | ||||
| ctl_datamove_remote_dm_read_cb(union ctl_io *io, bool samethr) | ctl_datamove_remote_dm_read_cb(union ctl_io *io, bool samethr) | ||||
| { | { | ||||
| uint32_t i; | uint32_t i; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| for (i = 0; i < io->scsiio.kern_sg_entries; i++) | for (i = 0; i < io->scsiio.kern_sg_entries; i++) | ||||
| free(CTL_LSGLT(io)[i].addr, M_CTL); | free(CTL_LSGLT(io)[i].addr, M_CTL); | ||||
| free(CTL_RSGL(io), M_CTL); | free(CTL_RSGL(io), M_CTL); | ||||
| CTL_RSGL(io) = NULL; | CTL_RSGL(io) = NULL; | ||||
| CTL_LSGL(io) = NULL; | CTL_LSGL(io) = NULL; | ||||
| /* | /* | ||||
| * The read is done, now we need to send status (good or bad) back | * The read is done, now we need to send status (good or bad) back | ||||
| * to the other side. | * to the other side. | ||||
| */ | */ | ||||
| ctl_send_datamove_done(io, /*have_lock*/ 0); | ctl_send_datamove_done(io, /*have_lock*/ 0); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static void | static void | ||||
| ctl_datamove_remote_read_cb(struct ctl_ha_dt_req *rq) | ctl_datamove_remote_read_cb(struct ctl_ha_dt_req *rq) | ||||
| { | { | ||||
| union ctl_io *io; | union ctl_io *io; | ||||
| void (*fe_datamove)(union ctl_io *io); | void (*fe_datamove)(union ctl_io *io); | ||||
| io = rq->context; | io = rq->context; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| if (rq->ret != CTL_HA_STATUS_SUCCESS) { | if (rq->ret != CTL_HA_STATUS_SUCCESS) { | ||||
| printf("%s: ISC DMA read failed with error %d\n", __func__, | printf("%s: ISC DMA read failed with error %d\n", __func__, | ||||
| rq->ret); | rq->ret); | ||||
| ctl_set_internal_failure(&io->scsiio, | ctl_set_internal_failure(&io->scsiio, | ||||
| /*sks_valid*/ 1, | /*sks_valid*/ 1, | ||||
| /*retry_count*/ rq->ret); | /*retry_count*/ rq->ret); | ||||
| } | } | ||||
| Show All 18 Lines | |||||
| static int | static int | ||||
| ctl_datamove_remote_sgl_setup(union ctl_io *io) | ctl_datamove_remote_sgl_setup(union ctl_io *io) | ||||
| { | { | ||||
| struct ctl_sg_entry *local_sglist; | struct ctl_sg_entry *local_sglist; | ||||
| uint32_t len_to_go; | uint32_t len_to_go; | ||||
| int retval; | int retval; | ||||
| int i; | int i; | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| retval = 0; | retval = 0; | ||||
| local_sglist = CTL_LSGL(io); | local_sglist = CTL_LSGL(io); | ||||
| len_to_go = io->scsiio.kern_data_len; | len_to_go = io->scsiio.kern_data_len; | ||||
| /* | /* | ||||
| * The difficult thing here is that the size of the various | * The difficult thing here is that the size of the various | ||||
| * S/G segments may be different than the size from the | * S/G segments may be different than the size from the | ||||
| * remote controller. That'll make it harder when DMAing | * remote controller. That'll make it harder when DMAing | ||||
| Show All 21 Lines | |||||
| { | { | ||||
| struct ctl_ha_dt_req *rq; | struct ctl_ha_dt_req *rq; | ||||
| struct ctl_sg_entry *remote_sglist, *local_sglist; | struct ctl_sg_entry *remote_sglist, *local_sglist; | ||||
| uint32_t local_used, remote_used, total_used; | uint32_t local_used, remote_used, total_used; | ||||
| int i, j, isc_ret; | int i, j, isc_ret; | ||||
| rq = ctl_dt_req_alloc(); | rq = ctl_dt_req_alloc(); | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| /* | /* | ||||
| * If we failed to allocate the request, and if the DMA didn't fail | * If we failed to allocate the request, and if the DMA didn't fail | ||||
| * anyway, set busy status. This is just a resource allocation | * anyway, set busy status. This is just a resource allocation | ||||
| * failure. | * failure. | ||||
| */ | */ | ||||
| if ((rq == NULL) | if ((rq == NULL) | ||||
| && ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE && | && ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE && | ||||
| (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) | (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) | ||||
| ▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | |||||
| * XFER mode only, not SER_ONLY mode. For writes, we DMA into local memory | * XFER mode only, not SER_ONLY mode. For writes, we DMA into local memory | ||||
| * first. Once that is complete, the data gets DMAed into the remote | * first. Once that is complete, the data gets DMAed into the remote | ||||
| * controller's memory. For reads, we DMA from the remote controller's | * controller's memory. For reads, we DMA from the remote controller's | ||||
| * memory into our memory first, and then move it out to the FETD. | * memory into our memory first, and then move it out to the FETD. | ||||
| */ | */ | ||||
| static void | static void | ||||
| ctl_datamove_remote(union ctl_io *io) | ctl_datamove_remote(union ctl_io *io) | ||||
| { | { | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| mtx_assert(&((struct ctl_softc *)CTL_SOFTC(io))->ctl_lock, MA_NOTOWNED); | mtx_assert(&((struct ctl_softc *)CTL_SOFTC(io))->ctl_lock, MA_NOTOWNED); | ||||
| if (io->io_hdr.flags & CTL_FLAG_FAILOVER) { | if (io->io_hdr.flags & CTL_FLAG_FAILOVER) { | ||||
| ctl_failover_io(io, /*have_lock*/ 0); | ctl_failover_io(io, /*have_lock*/ 0); | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| struct ctl_softc *softc = CTL_SOFTC(io); | struct ctl_softc *softc = CTL_SOFTC(io); | ||||
| struct ctl_port *port = CTL_PORT(io); | struct ctl_port *port = CTL_PORT(io); | ||||
| struct ctl_lun *lun; | struct ctl_lun *lun; | ||||
| struct scsi_sense_data *ps; | struct scsi_sense_data *ps; | ||||
| uint32_t initidx, p, targ_lun; | uint32_t initidx, p, targ_lun; | ||||
| CTL_DEBUG_PRINT(("ctl_queue_sense\n")); | CTL_DEBUG_PRINT(("ctl_queue_sense\n")); | ||||
| CTL_IO_ASSERT(io, SCSI); | |||||
| targ_lun = ctl_lun_map_from_port(port, io->io_hdr.nexus.targ_lun); | targ_lun = ctl_lun_map_from_port(port, io->io_hdr.nexus.targ_lun); | ||||
| /* | /* | ||||
| * LUN lookup will likely move to the ctl_work_thread() once we | * LUN lookup will likely move to the ctl_work_thread() once we | ||||
| * have our new queueing infrastructure (that doesn't put things on | * have our new queueing infrastructure (that doesn't put things on | ||||
| * a per-LUN queue initially). That is so that we can handle | * a per-LUN queue initially). That is so that we can handle | ||||
| * things like an INQUIRY to a LUN that we don't have enabled. We | * things like an INQUIRY to a LUN that we don't have enabled. We | ||||
| ▲ Show 20 Lines • Show All 449 Lines • Show Last 20 Lines | |||||