diff options
Diffstat (limited to 'drivers/target/loopback/tcm_loop.c')
-rw-r--r-- | drivers/target/loopback/tcm_loop.c | 77 |
1 files changed, 17 insertions, 60 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 5091b31b3e56..b6a913e38b30 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
@@ -51,19 +51,7 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd); | |||
51 | */ | 51 | */ |
52 | static int tcm_loop_check_stop_free(struct se_cmd *se_cmd) | 52 | static int tcm_loop_check_stop_free(struct se_cmd *se_cmd) |
53 | { | 53 | { |
54 | /* | 54 | return transport_generic_free_cmd(se_cmd, 0); |
55 | * Do not release struct se_cmd's containing a valid TMR | ||
56 | * pointer. These will be released directly in tcm_loop_device_reset() | ||
57 | * with transport_generic_free_cmd(). | ||
58 | */ | ||
59 | if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) | ||
60 | return 0; | ||
61 | /* | ||
62 | * Release the struct se_cmd, which will make a callback to release | ||
63 | * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd() | ||
64 | */ | ||
65 | transport_generic_free_cmd(se_cmd, 0); | ||
66 | return 1; | ||
67 | } | 55 | } |
68 | 56 | ||
69 | static void tcm_loop_release_cmd(struct se_cmd *se_cmd) | 57 | static void tcm_loop_release_cmd(struct se_cmd *se_cmd) |
@@ -218,10 +206,8 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, | |||
218 | { | 206 | { |
219 | struct se_cmd *se_cmd = NULL; | 207 | struct se_cmd *se_cmd = NULL; |
220 | struct se_session *se_sess; | 208 | struct se_session *se_sess; |
221 | struct se_portal_group *se_tpg; | ||
222 | struct tcm_loop_nexus *tl_nexus; | 209 | struct tcm_loop_nexus *tl_nexus; |
223 | struct tcm_loop_cmd *tl_cmd = NULL; | 210 | struct tcm_loop_cmd *tl_cmd = NULL; |
224 | struct tcm_loop_tmr *tl_tmr = NULL; | ||
225 | int ret = TMR_FUNCTION_FAILED, rc; | 211 | int ret = TMR_FUNCTION_FAILED, rc; |
226 | 212 | ||
227 | /* | 213 | /* |
@@ -240,55 +226,29 @@ static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, | |||
240 | return ret; | 226 | return ret; |
241 | } | 227 | } |
242 | 228 | ||
243 | tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL); | 229 | init_completion(&tl_cmd->tmr_done); |
244 | if (!tl_tmr) { | ||
245 | pr_err("Unable to allocate memory for tl_tmr\n"); | ||
246 | goto release; | ||
247 | } | ||
248 | init_waitqueue_head(&tl_tmr->tl_tmr_wait); | ||
249 | 230 | ||
250 | se_cmd = &tl_cmd->tl_se_cmd; | 231 | se_cmd = &tl_cmd->tl_se_cmd; |
251 | se_tpg = &tl_tpg->tl_se_tpg; | ||
252 | se_sess = tl_tpg->tl_nexus->se_sess; | 232 | se_sess = tl_tpg->tl_nexus->se_sess; |
253 | /* | ||
254 | * Initialize struct se_cmd descriptor from target_core_mod infrastructure | ||
255 | */ | ||
256 | transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, 0, | ||
257 | DMA_NONE, TCM_SIMPLE_TAG, | ||
258 | &tl_cmd->tl_sense_buf[0]); | ||
259 | 233 | ||
260 | rc = core_tmr_alloc_req(se_cmd, tl_tmr, tmr, GFP_KERNEL); | 234 | rc = target_submit_tmr(se_cmd, se_sess, tl_cmd->tl_sense_buf, lun, |
235 | NULL, tmr, GFP_KERNEL, task, | ||
236 | TARGET_SCF_ACK_KREF); | ||
261 | if (rc < 0) | 237 | if (rc < 0) |
262 | goto release; | 238 | goto release; |
239 | wait_for_completion(&tl_cmd->tmr_done); | ||
240 | ret = se_cmd->se_tmr_req->response; | ||
241 | target_put_sess_cmd(se_cmd); | ||
263 | 242 | ||
264 | if (tmr == TMR_ABORT_TASK) | 243 | out: |
265 | se_cmd->se_tmr_req->ref_task_tag = task; | 244 | return ret; |
266 | 245 | ||
267 | /* | ||
268 | * Locate the underlying TCM struct se_lun | ||
269 | */ | ||
270 | if (transport_lookup_tmr_lun(se_cmd, lun) < 0) { | ||
271 | ret = TMR_LUN_DOES_NOT_EXIST; | ||
272 | goto release; | ||
273 | } | ||
274 | /* | ||
275 | * Queue the TMR to TCM Core and sleep waiting for | ||
276 | * tcm_loop_queue_tm_rsp() to wake us up. | ||
277 | */ | ||
278 | transport_generic_handle_tmr(se_cmd); | ||
279 | wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete)); | ||
280 | /* | ||
281 | * The TMR LUN_RESET has completed, check the response status and | ||
282 | * then release allocations. | ||
283 | */ | ||
284 | ret = se_cmd->se_tmr_req->response; | ||
285 | release: | 246 | release: |
286 | if (se_cmd) | 247 | if (se_cmd) |
287 | transport_generic_free_cmd(se_cmd, 1); | 248 | transport_generic_free_cmd(se_cmd, 0); |
288 | else | 249 | else |
289 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); | 250 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); |
290 | kfree(tl_tmr); | 251 | goto out; |
291 | return ret; | ||
292 | } | 252 | } |
293 | 253 | ||
294 | static int tcm_loop_abort_task(struct scsi_cmnd *sc) | 254 | static int tcm_loop_abort_task(struct scsi_cmnd *sc) |
@@ -669,14 +629,11 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd) | |||
669 | 629 | ||
670 | static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) | 630 | static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) |
671 | { | 631 | { |
672 | struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; | 632 | struct tcm_loop_cmd *tl_cmd = container_of(se_cmd, |
673 | struct tcm_loop_tmr *tl_tmr = se_tmr->fabric_tmr_ptr; | 633 | struct tcm_loop_cmd, tl_se_cmd); |
674 | /* | 634 | |
675 | * The SCSI EH thread will be sleeping on se_tmr->tl_tmr_wait, go ahead | 635 | /* Wake up tcm_loop_issue_tmr(). */ |
676 | * and wake up the wait_queue_head_t in tcm_loop_device_reset() | 636 | complete(&tl_cmd->tmr_done); |
677 | */ | ||
678 | atomic_set(&tl_tmr->tmr_complete, 1); | ||
679 | wake_up(&tl_tmr->tl_tmr_wait); | ||
680 | } | 637 | } |
681 | 638 | ||
682 | static void tcm_loop_aborted_task(struct se_cmd *se_cmd) | 639 | static void tcm_loop_aborted_task(struct se_cmd *se_cmd) |