From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch adds a target_submit_cmd() caller that can be used by fabrics to submit an uninitialized se_cmd descriptor to an struct se_session + unpacked_lun from workqueue process context. This call will invoke the following steps: - transport_init_se_cmd() to setup se_cmd specific pointers - Obtain se_cmd->cmd_kref references with target_get_sess_cmd() - set se_cmd->t_tasks_bidi - transport_lookup_cmd_lun() to setup struct se_cmd->se_lun from the passed unpacked_lun - transport_generic_allocate_tasks() to setup the passed *cdb, and - transport_handle_cdb_direct() handle READ dispatch or WRITE ready-to-transfer callback to fabric Cc: Christoph Hellwig <hch@xxxxxx> Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx> Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/target/target_core_transport.c | 95 ++++++++++++++++++++++++++++++++ include/target/target_core_transport.h | 2 + 2 files changed, 97 insertions(+), 0 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 203d386..a307fbe 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1673,6 +1673,101 @@ int transport_handle_cdb_direct( } EXPORT_SYMBOL(transport_handle_cdb_direct); +/** + * target_submit_cmd() - Lookup unpacked lun and submit a previously + * uninitialized se_cmd descriptor to struct se_lun->lun_se_dev + * backend using struct se_sess nexus. + * + * This may only be called from process context, and also currently + * assumes internal allocation of fabric payload buffer by target-core. + * + * @se_cmd: command descriptor to submit + * @se_sess: associated se_sess for endpoint + * @cdb: pointer to SCSI CDB + * @sense: pointer to SCSI sense buffer + * @unpacked_lun: unpacked LUN to reference for struct se_lun + * @data_length: fabric expected data transfer length + * @task_addr: SAM task attribute + * @data_dir: DMA data direction + * @bidi: signal bidirectional data payload + **/ +int target_submit_cmd( + struct se_cmd *se_cmd, + struct se_session *se_sess, + unsigned char *cdb, + unsigned char *sense, + u32 unpacked_lun, + u32 data_length, + int task_attr, + int data_dir, + int bidi) +{ + struct se_portal_group *se_tpg; + int rc; + + if (!se_cmd || !se_sess) { + pr_err("Missing se_cmd or se_sess descriptor\n"); + return -EINVAL; + } + se_tpg = se_sess->se_tpg; + if (!se_tpg) { + pr_err("Unable to locate se_tpg in target_submit_cmd\n"); + return -EINVAL; + } + if (se_cmd->se_tfo || se_cmd->se_sess) { + pr_err("struct se_cmd already initialized\n"); + return -EEXIST; + } + if (in_interrupt()) { + pr_err("target_submit_cmd() may only be used from process context\n"); + return -ENOSYS; + } + /* + * Initialize se_cmd for target operation. From this point + * exceptions are handled by sending exception status via + * target_core_fabric_ops->queue_status() callback + */ + transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, + data_length, data_dir, task_attr, sense); + /* + * Obtain struct se_cmd->cmd_kref references and add new cmd to + * se_sess->sess_cmd_list + */ + target_get_sess_cmd(se_sess, se_cmd); + /* + * Signal bidirectional data payloads to target-core + */ + if (bidi) + se_cmd->t_tasks_bidi = 1; + /* + * Locate se_lun pointer and attach it to struct se_cmd + */ + if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { + transport_send_check_condition_and_sense(se_cmd, + se_cmd->scsi_sense_reason, 0); + return 0; + } + /* + * Sanitize CDBs via transport_generic_cmd_sequencer() and + * allocate the necessary tasks to complete the received CDB+data + */ + rc = transport_generic_allocate_tasks(se_cmd, cdb); + if (rc != 0) { + transport_send_check_condition_and_sense(se_cmd, + se_cmd->scsi_sense_reason, 0); + return 0; + } + /* + * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend + * for immediate execution of READs, otherwise wait for + * transport_generic_handle_data() to be called for WRITEs + * when fabric has filled the incoming buffer. + */ + transport_handle_cdb_direct(se_cmd); + return 0; +} +EXPORT_SYMBOL(target_submit_cmd); + /* * Used by fabric module frontends defining a TFO->new_cmd_map() caller * to queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index dac4f2d..407aff9 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h @@ -132,6 +132,8 @@ extern void transport_init_se_cmd(struct se_cmd *, void *transport_kmap_first_data_page(struct se_cmd *cmd); void transport_kunmap_first_data_page(struct se_cmd *cmd); extern int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); +extern int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, + unsigned char *, u32, u32, int, int, int); extern int transport_handle_cdb_direct(struct se_cmd *); extern int transport_generic_handle_cdb_map(struct se_cmd *); extern int transport_generic_handle_data(struct se_cmd *); -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html