aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/loopback/tcm_loop.c62
1 files changed, 8 insertions, 54 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 7a0da1ae0040..2d444b1ccd33 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -166,7 +166,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
166 struct tcm_loop_tpg *tl_tpg; 166 struct tcm_loop_tpg *tl_tpg;
167 struct scatterlist *sgl_bidi = NULL; 167 struct scatterlist *sgl_bidi = NULL;
168 u32 sgl_bidi_count = 0; 168 u32 sgl_bidi_count = 0;
169 int ret; 169 int rc;
170 170
171 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); 171 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
172 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; 172 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
@@ -187,12 +187,6 @@ static void tcm_loop_submission_work(struct work_struct *work)
187 set_host_byte(sc, DID_ERROR); 187 set_host_byte(sc, DID_ERROR);
188 goto out_done; 188 goto out_done;
189 } 189 }
190
191 transport_init_se_cmd(se_cmd, tl_tpg->tl_se_tpg.se_tpg_tfo,
192 tl_nexus->se_sess,
193 scsi_bufflen(sc), sc->sc_data_direction,
194 tcm_loop_sam_attr(sc), &tl_cmd->tl_sense_buf[0]);
195
196 if (scsi_bidi_cmnd(sc)) { 190 if (scsi_bidi_cmnd(sc)) {
197 struct scsi_data_buffer *sdb = scsi_in(sc); 191 struct scsi_data_buffer *sdb = scsi_in(sc);
198 192
@@ -201,56 +195,16 @@ static void tcm_loop_submission_work(struct work_struct *work)
201 se_cmd->se_cmd_flags |= SCF_BIDI; 195 se_cmd->se_cmd_flags |= SCF_BIDI;
202 196
203 } 197 }
204 198 rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
205 if (transport_lookup_cmd_lun(se_cmd, tl_cmd->sc->device->lun) < 0) { 199 &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
206 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); 200 scsi_bufflen(sc), tcm_loop_sam_attr(sc),
201 sc->sc_data_direction, 0,
202 scsi_sglist(sc), scsi_sg_count(sc),
203 sgl_bidi, sgl_bidi_count);
204 if (rc < 0) {
207 set_host_byte(sc, DID_NO_CONNECT); 205 set_host_byte(sc, DID_NO_CONNECT);
208 goto out_done; 206 goto out_done;
209 } 207 }
210
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 * non-data CDBs. Also note that this is currently guaranteed to be a
215 * single SGL for this case by target core in
216 * target_setup_cmd_from_cdb() -> transport_generic_cmd_sequencer().
217 */
218 if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
219 se_cmd->data_direction == DMA_FROM_DEVICE) {
220 struct scatterlist *sg = scsi_sglist(sc);
221 unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
222
223 if (buf != NULL) {
224 memset(buf, 0, sg->length);
225 kunmap(sg_page(sg));
226 }
227 }
228
229 ret = target_setup_cmd_from_cdb(se_cmd, sc->cmnd);
230 if (ret == -ENOMEM) {
231 transport_send_check_condition_and_sense(se_cmd,
232 TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
233 transport_generic_free_cmd(se_cmd, 0);
234 return;
235 } else if (ret < 0) {
236 if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
237 tcm_loop_queue_status(se_cmd);
238 else
239 transport_send_check_condition_and_sense(se_cmd,
240 se_cmd->scsi_sense_reason, 0);
241 transport_generic_free_cmd(se_cmd, 0);
242 return;
243 }
244
245 ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
246 scsi_sg_count(sc), sgl_bidi, sgl_bidi_count);
247 if (ret) {
248 transport_send_check_condition_and_sense(se_cmd,
249 se_cmd->scsi_sense_reason, 0);
250 transport_generic_free_cmd(se_cmd, 0);
251 return;
252 }
253 transport_handle_cdb_direct(se_cmd);
254 return; 208 return;
255 209
256out_done: 210out_done: