diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-02-02 17:04:42 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-02-25 17:37:48 -0500 |
commit | 16786454acec0e0e55e32d508b3058b32c1f23f3 (patch) | |
tree | 2f0039c11ef0d69cb7839db7b2f1e570bbaf7644 /drivers/target | |
parent | afe2cb7fb111ac52ec95ab2bfb19d9d9e0d52ed8 (diff) |
tcm_loop: switch to using transport_handle_cdb_direct
Now that we use a workqueue for I/O submission there is no need to use
transport_generic_handle_cdb_map any more.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/loopback/tcm_loop.c | 112 |
1 files changed, 56 insertions, 56 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index cb8893f303a5..88fb3d1b0ad5 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
@@ -49,59 +49,7 @@ static struct kmem_cache *tcm_loop_cmd_cache; | |||
49 | 49 | ||
50 | static int tcm_loop_hba_no_cnt; | 50 | static int tcm_loop_hba_no_cnt; |
51 | 51 | ||
52 | /* | 52 | static int tcm_loop_queue_status(struct se_cmd *se_cmd); |
53 | * Called by struct target_core_fabric_ops->new_cmd_map() | ||
54 | * | ||
55 | * Always called in process context. A non zero return value | ||
56 | * here will signal to handle an exception based on the return code. | ||
57 | */ | ||
58 | static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) | ||
59 | { | ||
60 | struct tcm_loop_cmd *tl_cmd = container_of(se_cmd, | ||
61 | struct tcm_loop_cmd, tl_se_cmd); | ||
62 | struct scsi_cmnd *sc = tl_cmd->sc; | ||
63 | struct scatterlist *sgl_bidi = NULL; | ||
64 | u32 sgl_bidi_count = 0; | ||
65 | int ret; | ||
66 | /* | ||
67 | * Allocate the necessary tasks to complete the received CDB+data | ||
68 | */ | ||
69 | ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd); | ||
70 | if (ret != 0) | ||
71 | return ret; | ||
72 | /* | ||
73 | * For BIDI commands, pass in the extra READ buffer | ||
74 | * to transport_generic_map_mem_to_cmd() below.. | ||
75 | */ | ||
76 | if (se_cmd->se_cmd_flags & SCF_BIDI) { | ||
77 | struct scsi_data_buffer *sdb = scsi_in(sc); | ||
78 | |||
79 | sgl_bidi = sdb->table.sgl; | ||
80 | sgl_bidi_count = sdb->table.nents; | ||
81 | } | ||
82 | /* | ||
83 | * Because some userspace code via scsi-generic do not memset their | ||
84 | * associated read buffers, go ahead and do that here for type | ||
85 | * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently | ||
86 | * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB | ||
87 | * by target core in transport_generic_allocate_tasks() -> | ||
88 | * transport_generic_cmd_sequencer(). | ||
89 | */ | ||
90 | if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB && | ||
91 | se_cmd->data_direction == DMA_FROM_DEVICE) { | ||
92 | struct scatterlist *sg = scsi_sglist(sc); | ||
93 | unsigned char *buf = kmap(sg_page(sg)) + sg->offset; | ||
94 | |||
95 | if (buf != NULL) { | ||
96 | memset(buf, 0, sg->length); | ||
97 | kunmap(sg_page(sg)); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /* Tell the core about our preallocated memory */ | ||
102 | return transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), | ||
103 | scsi_sg_count(sc), sgl_bidi, sgl_bidi_count); | ||
104 | } | ||
105 | 53 | ||
106 | /* | 54 | /* |
107 | * Called from struct target_core_fabric_ops->check_stop_free() | 55 | * Called from struct target_core_fabric_ops->check_stop_free() |
@@ -216,6 +164,9 @@ static void tcm_loop_submission_work(struct work_struct *work) | |||
216 | struct tcm_loop_nexus *tl_nexus; | 164 | struct tcm_loop_nexus *tl_nexus; |
217 | struct tcm_loop_hba *tl_hba; | 165 | struct tcm_loop_hba *tl_hba; |
218 | struct tcm_loop_tpg *tl_tpg; | 166 | struct tcm_loop_tpg *tl_tpg; |
167 | struct scatterlist *sgl_bidi = NULL; | ||
168 | u32 sgl_bidi_count = 0; | ||
169 | int ret; | ||
219 | 170 | ||
220 | tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); | 171 | tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); |
221 | tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; | 172 | tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; |
@@ -242,16 +193,66 @@ static void tcm_loop_submission_work(struct work_struct *work) | |||
242 | scsi_bufflen(sc), sc->sc_data_direction, | 193 | scsi_bufflen(sc), sc->sc_data_direction, |
243 | tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]); | 194 | tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]); |
244 | 195 | ||
245 | if (scsi_bidi_cmnd(sc)) | 196 | if (scsi_bidi_cmnd(sc)) { |
197 | struct scsi_data_buffer *sdb = scsi_in(sc); | ||
198 | |||
199 | sgl_bidi = sdb->table.sgl; | ||
200 | sgl_bidi_count = sdb->table.nents; | ||
246 | se_cmd->se_cmd_flags |= SCF_BIDI; | 201 | se_cmd->se_cmd_flags |= SCF_BIDI; |
247 | 202 | ||
203 | } | ||
204 | |||
248 | if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) { | 205 | if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) { |
249 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); | 206 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); |
250 | set_host_byte(sc, DID_NO_CONNECT); | 207 | set_host_byte(sc, DID_NO_CONNECT); |
251 | goto out_done; | 208 | goto out_done; |
252 | } | 209 | } |
253 | 210 | ||
254 | transport_generic_handle_cdb_map(se_cmd); | 211 | /* |
212 | * Because some userspace code via scsi-generic do not memset their | ||
213 | * associated read buffers, go ahead and do that here for type | ||
214 | * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently | ||
215 | * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB | ||
216 | * by target core in transport_generic_allocate_tasks() -> | ||
217 | * transport_generic_cmd_sequencer(). | ||
218 | */ | ||
219 | if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB && | ||
220 | se_cmd->data_direction == DMA_FROM_DEVICE) { | ||
221 | struct scatterlist *sg = scsi_sglist(sc); | ||
222 | unsigned char *buf = kmap(sg_page(sg)) + sg->offset; | ||
223 | |||
224 | if (buf != NULL) { | ||
225 | memset(buf, 0, sg->length); | ||
226 | kunmap(sg_page(sg)); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd); | ||
231 | if (ret == -ENOMEM) { | ||
232 | transport_send_check_condition_and_sense(se_cmd, | ||
233 | TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); | ||
234 | transport_generic_free_cmd(se_cmd, 0); | ||
235 | return; | ||
236 | } | ||
237 | if (ret == -EINVAL) { | ||
238 | if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) | ||
239 | tcm_loop_queue_status(se_cmd); | ||
240 | else | ||
241 | transport_send_check_condition_and_sense(se_cmd, | ||
242 | se_cmd->scsi_sense_reason, 0); | ||
243 | transport_generic_free_cmd(se_cmd, 0); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc), | ||
248 | scsi_sg_count(sc), sgl_bidi, sgl_bidi_count); | ||
249 | if (ret) { | ||
250 | transport_send_check_condition_and_sense(se_cmd, | ||
251 | se_cmd->scsi_sense_reason, 0); | ||
252 | transport_generic_free_cmd(se_cmd, 0); | ||
253 | return; | ||
254 | } | ||
255 | transport_handle_cdb_direct(se_cmd); | ||
255 | return; | 256 | return; |
256 | 257 | ||
257 | out_done: | 258 | out_done: |
@@ -1380,7 +1381,6 @@ static int tcm_loop_register_configfs(void) | |||
1380 | /* | 1381 | /* |
1381 | * Used for setting up remaining TCM resources in process context | 1382 | * Used for setting up remaining TCM resources in process context |
1382 | */ | 1383 | */ |
1383 | fabric->tf_ops.new_cmd_map = &tcm_loop_new_cmd_map; | ||
1384 | fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free; | 1384 | fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free; |
1385 | fabric->tf_ops.release_cmd = &tcm_loop_release_cmd; | 1385 | fabric->tf_ops.release_cmd = &tcm_loop_release_cmd; |
1386 | fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session; | 1386 | fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session; |