diff options
| -rw-r--r-- | drivers/target/target_core_transport.c | 86 | ||||
| -rw-r--r-- | include/target/target_core_base.h | 5 | ||||
| -rw-r--r-- | include/target/target_core_fabric.h | 4 |
3 files changed, 92 insertions, 3 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 176f956665e8..e4389d40c057 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -1642,6 +1642,80 @@ int transport_handle_cdb_direct( | |||
| 1642 | } | 1642 | } |
| 1643 | EXPORT_SYMBOL(transport_handle_cdb_direct); | 1643 | EXPORT_SYMBOL(transport_handle_cdb_direct); |
| 1644 | 1644 | ||
| 1645 | /** | ||
| 1646 | * target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd | ||
| 1647 | * | ||
| 1648 | * @se_cmd: command descriptor to submit | ||
| 1649 | * @se_sess: associated se_sess for endpoint | ||
| 1650 | * @cdb: pointer to SCSI CDB | ||
| 1651 | * @sense: pointer to SCSI sense buffer | ||
| 1652 | * @unpacked_lun: unpacked LUN to reference for struct se_lun | ||
| 1653 | * @data_length: fabric expected data transfer length | ||
| 1654 | * @task_addr: SAM task attribute | ||
| 1655 | * @data_dir: DMA data direction | ||
| 1656 | * @flags: flags for command submission from target_sc_flags_tables | ||
| 1657 | * | ||
| 1658 | * This may only be called from process context, and also currently | ||
| 1659 | * assumes internal allocation of fabric payload buffer by target-core. | ||
| 1660 | **/ | ||
| 1661 | int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, | ||
| 1662 | unsigned char *cdb, unsigned char *sense, u32 unpacked_lun, | ||
| 1663 | u32 data_length, int task_attr, int data_dir, int flags) | ||
| 1664 | { | ||
| 1665 | struct se_portal_group *se_tpg; | ||
| 1666 | int rc; | ||
| 1667 | |||
| 1668 | se_tpg = se_sess->se_tpg; | ||
| 1669 | BUG_ON(!se_tpg); | ||
| 1670 | BUG_ON(se_cmd->se_tfo || se_cmd->se_sess); | ||
| 1671 | BUG_ON(in_interrupt()); | ||
| 1672 | /* | ||
| 1673 | * Initialize se_cmd for target operation. From this point | ||
| 1674 | * exceptions are handled by sending exception status via | ||
| 1675 | * target_core_fabric_ops->queue_status() callback | ||
| 1676 | */ | ||
| 1677 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, | ||
| 1678 | data_length, data_dir, task_attr, sense); | ||
| 1679 | /* | ||
| 1680 | * Obtain struct se_cmd->cmd_kref reference and add new cmd to | ||
| 1681 | * se_sess->sess_cmd_list. A second kref_get here is necessary | ||
| 1682 | * for fabrics using TARGET_SCF_ACK_KREF that expect a second | ||
| 1683 | * kref_put() to happen during fabric packet acknowledgement. | ||
| 1684 | */ | ||
| 1685 | target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF)); | ||
| 1686 | /* | ||
| 1687 | * Signal bidirectional data payloads to target-core | ||
| 1688 | */ | ||
| 1689 | if (flags & TARGET_SCF_BIDI_OP) | ||
| 1690 | se_cmd->se_cmd_flags |= SCF_BIDI; | ||
| 1691 | /* | ||
| 1692 | * Locate se_lun pointer and attach it to struct se_cmd | ||
| 1693 | */ | ||
| 1694 | if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) | ||
| 1695 | goto out_check_cond; | ||
| 1696 | /* | ||
| 1697 | * Sanitize CDBs via transport_generic_cmd_sequencer() and | ||
| 1698 | * allocate the necessary tasks to complete the received CDB+data | ||
| 1699 | */ | ||
| 1700 | rc = transport_generic_allocate_tasks(se_cmd, cdb); | ||
| 1701 | if (rc != 0) | ||
| 1702 | goto out_check_cond; | ||
| 1703 | /* | ||
| 1704 | * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend | ||
| 1705 | * for immediate execution of READs, otherwise wait for | ||
| 1706 | * transport_generic_handle_data() to be called for WRITEs | ||
| 1707 | * when fabric has filled the incoming buffer. | ||
| 1708 | */ | ||
| 1709 | transport_handle_cdb_direct(se_cmd); | ||
| 1710 | return 0; | ||
| 1711 | |||
| 1712 | out_check_cond: | ||
| 1713 | transport_send_check_condition_and_sense(se_cmd, | ||
| 1714 | se_cmd->scsi_sense_reason, 0); | ||
| 1715 | return 0; | ||
| 1716 | } | ||
| 1717 | EXPORT_SYMBOL(target_submit_cmd); | ||
| 1718 | |||
| 1645 | /* | 1719 | /* |
| 1646 | * Used by fabric module frontends defining a TFO->new_cmd_map() caller | 1720 | * Used by fabric module frontends defining a TFO->new_cmd_map() caller |
| 1647 | * to queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to | 1721 | * to queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to |
| @@ -3910,13 +3984,21 @@ EXPORT_SYMBOL(transport_generic_free_cmd); | |||
| 3910 | /* target_get_sess_cmd - Add command to active ->sess_cmd_list | 3984 | /* target_get_sess_cmd - Add command to active ->sess_cmd_list |
| 3911 | * @se_sess: session to reference | 3985 | * @se_sess: session to reference |
| 3912 | * @se_cmd: command descriptor to add | 3986 | * @se_cmd: command descriptor to add |
| 3987 | * @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd() | ||
| 3913 | */ | 3988 | */ |
| 3914 | void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd) | 3989 | void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, |
| 3990 | bool ack_kref) | ||
| 3915 | { | 3991 | { |
| 3916 | unsigned long flags; | 3992 | unsigned long flags; |
| 3917 | 3993 | ||
| 3918 | kref_init(&se_cmd->cmd_kref); | 3994 | kref_init(&se_cmd->cmd_kref); |
| 3919 | kref_get(&se_cmd->cmd_kref); | 3995 | /* |
| 3996 | * Add a second kref if the fabric caller is expecting to handle | ||
| 3997 | * fabric acknowledgement that requires two target_put_sess_cmd() | ||
| 3998 | * invocations before se_cmd descriptor release. | ||
| 3999 | */ | ||
| 4000 | if (ack_kref == true) | ||
| 4001 | kref_get(&se_cmd->cmd_kref); | ||
| 3920 | 4002 | ||
| 3921 | spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); | 4003 | spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); |
| 3922 | list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); | 4004 | list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index af088a9e4905..28190dc10eef 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
| @@ -226,6 +226,11 @@ enum tcm_sense_reason_table { | |||
| 226 | TCM_RESERVATION_CONFLICT = 0x10, | 226 | TCM_RESERVATION_CONFLICT = 0x10, |
| 227 | }; | 227 | }; |
| 228 | 228 | ||
| 229 | enum target_sc_flags_table { | ||
| 230 | TARGET_SCF_BIDI_OP = 0x01, | ||
| 231 | TARGET_SCF_ACK_KREF = 0x02, | ||
| 232 | }; | ||
| 233 | |||
| 229 | /* fabric independent task management function values */ | 234 | /* fabric independent task management function values */ |
| 230 | enum tcm_tmreq_table { | 235 | enum tcm_tmreq_table { |
| 231 | TMR_ABORT_TASK = 1, | 236 | TMR_ABORT_TASK = 1, |
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index d035d865dbef..aaa26da5a527 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h | |||
| @@ -118,6 +118,8 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *, | |||
| 118 | struct se_session *, u32, int, int, unsigned char *); | 118 | struct se_session *, u32, int, int, unsigned char *); |
| 119 | int transport_lookup_cmd_lun(struct se_cmd *, u32); | 119 | int transport_lookup_cmd_lun(struct se_cmd *, u32); |
| 120 | int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); | 120 | int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); |
| 121 | int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, | ||
| 122 | unsigned char *, u32, u32, int, int, int); | ||
| 121 | int transport_handle_cdb_direct(struct se_cmd *); | 123 | int transport_handle_cdb_direct(struct se_cmd *); |
| 122 | int transport_generic_handle_cdb_map(struct se_cmd *); | 124 | int transport_generic_handle_cdb_map(struct se_cmd *); |
| 123 | int transport_generic_handle_data(struct se_cmd *); | 125 | int transport_generic_handle_data(struct se_cmd *); |
| @@ -134,7 +136,7 @@ bool transport_wait_for_tasks(struct se_cmd *); | |||
| 134 | int transport_check_aborted_status(struct se_cmd *, int); | 136 | int transport_check_aborted_status(struct se_cmd *, int); |
| 135 | int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); | 137 | int transport_send_check_condition_and_sense(struct se_cmd *, u8, int); |
| 136 | 138 | ||
| 137 | void target_get_sess_cmd(struct se_session *, struct se_cmd *); | 139 | void target_get_sess_cmd(struct se_session *, struct se_cmd *, bool); |
| 138 | int target_put_sess_cmd(struct se_session *, struct se_cmd *); | 140 | int target_put_sess_cmd(struct se_session *, struct se_cmd *); |
| 139 | void target_splice_sess_cmd_list(struct se_session *); | 141 | void target_splice_sess_cmd_list(struct se_session *); |
| 140 | void target_wait_for_sess_cmds(struct se_session *, int); | 142 | void target_wait_for_sess_cmds(struct se_session *, int); |
