aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/loopback/tcm_loop.c112
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
50static int tcm_loop_hba_no_cnt; 50static int tcm_loop_hba_no_cnt;
51 51
52/* 52static 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 */
58static 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
257out_done: 258out_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;