aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/loopback/tcm_loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/loopback/tcm_loop.c')
-rw-r--r--drivers/target/loopback/tcm_loop.c242
1 files changed, 201 insertions, 41 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 0f6d69dabca1..1b41e6776152 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -135,6 +135,21 @@ static int tcm_loop_change_queue_depth(
135 return sdev->queue_depth; 135 return sdev->queue_depth;
136} 136}
137 137
138static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag)
139{
140 if (sdev->tagged_supported) {
141 scsi_set_tag_type(sdev, tag);
142
143 if (tag)
144 scsi_activate_tcq(sdev, sdev->queue_depth);
145 else
146 scsi_deactivate_tcq(sdev, sdev->queue_depth);
147 } else
148 tag = 0;
149
150 return tag;
151}
152
138/* 153/*
139 * Locate the SAM Task Attr from struct scsi_cmnd * 154 * Locate the SAM Task Attr from struct scsi_cmnd *
140 */ 155 */
@@ -178,7 +193,10 @@ static void tcm_loop_submission_work(struct work_struct *work)
178 set_host_byte(sc, DID_NO_CONNECT); 193 set_host_byte(sc, DID_NO_CONNECT);
179 goto out_done; 194 goto out_done;
180 } 195 }
181 196 if (tl_tpg->tl_transport_status == TCM_TRANSPORT_OFFLINE) {
197 set_host_byte(sc, DID_TRANSPORT_DISRUPTED);
198 goto out_done;
199 }
182 tl_nexus = tl_hba->tl_nexus; 200 tl_nexus = tl_hba->tl_nexus;
183 if (!tl_nexus) { 201 if (!tl_nexus) {
184 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus" 202 scmd_printk(KERN_ERR, sc, "TCM_Loop I_T Nexus"
@@ -233,6 +251,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
233 } 251 }
234 252
235 tl_cmd->sc = sc; 253 tl_cmd->sc = sc;
254 tl_cmd->sc_cmd_tag = sc->tag;
236 INIT_WORK(&tl_cmd->work, tcm_loop_submission_work); 255 INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
237 queue_work(tcm_loop_workqueue, &tl_cmd->work); 256 queue_work(tcm_loop_workqueue, &tl_cmd->work);
238 return 0; 257 return 0;
@@ -242,41 +261,21 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
242 * Called from SCSI EH process context to issue a LUN_RESET TMR 261 * Called from SCSI EH process context to issue a LUN_RESET TMR
243 * to struct scsi_device 262 * to struct scsi_device
244 */ 263 */
245static int tcm_loop_device_reset(struct scsi_cmnd *sc) 264static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg,
265 struct tcm_loop_nexus *tl_nexus,
266 int lun, int task, enum tcm_tmreq_table tmr)
246{ 267{
247 struct se_cmd *se_cmd = NULL; 268 struct se_cmd *se_cmd = NULL;
248 struct se_portal_group *se_tpg;
249 struct se_session *se_sess; 269 struct se_session *se_sess;
270 struct se_portal_group *se_tpg;
250 struct tcm_loop_cmd *tl_cmd = NULL; 271 struct tcm_loop_cmd *tl_cmd = NULL;
251 struct tcm_loop_hba *tl_hba;
252 struct tcm_loop_nexus *tl_nexus;
253 struct tcm_loop_tmr *tl_tmr = NULL; 272 struct tcm_loop_tmr *tl_tmr = NULL;
254 struct tcm_loop_tpg *tl_tpg; 273 int ret = TMR_FUNCTION_FAILED, rc;
255 int ret = FAILED, rc;
256 /*
257 * Locate the tcm_loop_hba_t pointer
258 */
259 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
260 /*
261 * Locate the tl_nexus and se_sess pointers
262 */
263 tl_nexus = tl_hba->tl_nexus;
264 if (!tl_nexus) {
265 pr_err("Unable to perform device reset without"
266 " active I_T Nexus\n");
267 return FAILED;
268 }
269 se_sess = tl_nexus->se_sess;
270 /*
271 * Locate the tl_tpg and se_tpg pointers from TargetID in sc->device->id
272 */
273 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
274 se_tpg = &tl_tpg->tl_se_tpg;
275 274
276 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL); 275 tl_cmd = kmem_cache_zalloc(tcm_loop_cmd_cache, GFP_KERNEL);
277 if (!tl_cmd) { 276 if (!tl_cmd) {
278 pr_err("Unable to allocate memory for tl_cmd\n"); 277 pr_err("Unable to allocate memory for tl_cmd\n");
279 return FAILED; 278 return ret;
280 } 279 }
281 280
282 tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL); 281 tl_tmr = kzalloc(sizeof(struct tcm_loop_tmr), GFP_KERNEL);
@@ -287,6 +286,8 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
287 init_waitqueue_head(&tl_tmr->tl_tmr_wait); 286 init_waitqueue_head(&tl_tmr->tl_tmr_wait);
288 287
289 se_cmd = &tl_cmd->tl_se_cmd; 288 se_cmd = &tl_cmd->tl_se_cmd;
289 se_tpg = &tl_tpg->tl_se_tpg;
290 se_sess = tl_nexus->se_sess;
290 /* 291 /*
291 * Initialize struct se_cmd descriptor from target_core_mod infrastructure 292 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
292 */ 293 */
@@ -294,17 +295,23 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
294 DMA_NONE, MSG_SIMPLE_TAG, 295 DMA_NONE, MSG_SIMPLE_TAG,
295 &tl_cmd->tl_sense_buf[0]); 296 &tl_cmd->tl_sense_buf[0]);
296 297
297 rc = core_tmr_alloc_req(se_cmd, tl_tmr, TMR_LUN_RESET, GFP_KERNEL); 298 rc = core_tmr_alloc_req(se_cmd, tl_tmr, tmr, GFP_KERNEL);
298 if (rc < 0) 299 if (rc < 0)
299 goto release; 300 goto release;
301
302 if (tmr == TMR_ABORT_TASK)
303 se_cmd->se_tmr_req->ref_task_tag = task;
304
300 /* 305 /*
301 * Locate the underlying TCM struct se_lun from sc->device->lun 306 * Locate the underlying TCM struct se_lun
302 */ 307 */
303 if (transport_lookup_tmr_lun(se_cmd, sc->device->lun) < 0) 308 if (transport_lookup_tmr_lun(se_cmd, lun) < 0) {
309 ret = TMR_LUN_DOES_NOT_EXIST;
304 goto release; 310 goto release;
311 }
305 /* 312 /*
306 * Queue the TMR to TCM Core and sleep waiting for tcm_loop_queue_tm_rsp() 313 * Queue the TMR to TCM Core and sleep waiting for
307 * to wake us up. 314 * tcm_loop_queue_tm_rsp() to wake us up.
308 */ 315 */
309 transport_generic_handle_tmr(se_cmd); 316 transport_generic_handle_tmr(se_cmd);
310 wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete)); 317 wait_event(tl_tmr->tl_tmr_wait, atomic_read(&tl_tmr->tmr_complete));
@@ -312,8 +319,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
312 * The TMR LUN_RESET has completed, check the response status and 319 * The TMR LUN_RESET has completed, check the response status and
313 * then release allocations. 320 * then release allocations.
314 */ 321 */
315 ret = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ? 322 ret = se_cmd->se_tmr_req->response;
316 SUCCESS : FAILED;
317release: 323release:
318 if (se_cmd) 324 if (se_cmd)
319 transport_generic_free_cmd(se_cmd, 1); 325 transport_generic_free_cmd(se_cmd, 1);
@@ -323,6 +329,94 @@ release:
323 return ret; 329 return ret;
324} 330}
325 331
332static int tcm_loop_abort_task(struct scsi_cmnd *sc)
333{
334 struct tcm_loop_hba *tl_hba;
335 struct tcm_loop_nexus *tl_nexus;
336 struct tcm_loop_tpg *tl_tpg;
337 int ret = FAILED;
338
339 /*
340 * Locate the tcm_loop_hba_t pointer
341 */
342 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
343 /*
344 * Locate the tl_nexus and se_sess pointers
345 */
346 tl_nexus = tl_hba->tl_nexus;
347 if (!tl_nexus) {
348 pr_err("Unable to perform device reset without"
349 " active I_T Nexus\n");
350 return FAILED;
351 }
352
353 /*
354 * Locate the tl_tpg pointer from TargetID in sc->device->id
355 */
356 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
357 ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
358 sc->tag, TMR_ABORT_TASK);
359 return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
360}
361
362/*
363 * Called from SCSI EH process context to issue a LUN_RESET TMR
364 * to struct scsi_device
365 */
366static int tcm_loop_device_reset(struct scsi_cmnd *sc)
367{
368 struct tcm_loop_hba *tl_hba;
369 struct tcm_loop_nexus *tl_nexus;
370 struct tcm_loop_tpg *tl_tpg;
371 int ret = FAILED;
372
373 /*
374 * Locate the tcm_loop_hba_t pointer
375 */
376 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
377 /*
378 * Locate the tl_nexus and se_sess pointers
379 */
380 tl_nexus = tl_hba->tl_nexus;
381 if (!tl_nexus) {
382 pr_err("Unable to perform device reset without"
383 " active I_T Nexus\n");
384 return FAILED;
385 }
386 /*
387 * Locate the tl_tpg pointer from TargetID in sc->device->id
388 */
389 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
390 ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
391 0, TMR_LUN_RESET);
392 return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
393}
394
395static int tcm_loop_target_reset(struct scsi_cmnd *sc)
396{
397 struct tcm_loop_hba *tl_hba;
398 struct tcm_loop_tpg *tl_tpg;
399
400 /*
401 * Locate the tcm_loop_hba_t pointer
402 */
403 tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
404 if (!tl_hba) {
405 pr_err("Unable to perform device reset without"
406 " active I_T Nexus\n");
407 return FAILED;
408 }
409 /*
410 * Locate the tl_tpg pointer from TargetID in sc->device->id
411 */
412 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
413 if (tl_tpg) {
414 tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
415 return SUCCESS;
416 }
417 return FAILED;
418}
419
326static int tcm_loop_slave_alloc(struct scsi_device *sd) 420static int tcm_loop_slave_alloc(struct scsi_device *sd)
327{ 421{
328 set_bit(QUEUE_FLAG_BIDI, &sd->request_queue->queue_flags); 422 set_bit(QUEUE_FLAG_BIDI, &sd->request_queue->queue_flags);
@@ -331,6 +425,15 @@ static int tcm_loop_slave_alloc(struct scsi_device *sd)
331 425
332static int tcm_loop_slave_configure(struct scsi_device *sd) 426static int tcm_loop_slave_configure(struct scsi_device *sd)
333{ 427{
428 if (sd->tagged_supported) {
429 scsi_activate_tcq(sd, sd->queue_depth);
430 scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG,
431 sd->host->cmd_per_lun);
432 } else {
433 scsi_adjust_queue_depth(sd, 0,
434 sd->host->cmd_per_lun);
435 }
436
334 return 0; 437 return 0;
335} 438}
336 439
@@ -340,7 +443,10 @@ static struct scsi_host_template tcm_loop_driver_template = {
340 .name = "TCM_Loopback", 443 .name = "TCM_Loopback",
341 .queuecommand = tcm_loop_queuecommand, 444 .queuecommand = tcm_loop_queuecommand,
342 .change_queue_depth = tcm_loop_change_queue_depth, 445 .change_queue_depth = tcm_loop_change_queue_depth,
446 .change_queue_type = tcm_loop_change_queue_type,
447 .eh_abort_handler = tcm_loop_abort_task,
343 .eh_device_reset_handler = tcm_loop_device_reset, 448 .eh_device_reset_handler = tcm_loop_device_reset,
449 .eh_target_reset_handler = tcm_loop_target_reset,
344 .can_queue = 1024, 450 .can_queue = 1024,
345 .this_id = -1, 451 .this_id = -1,
346 .sg_tablesize = 256, 452 .sg_tablesize = 256,
@@ -699,7 +805,10 @@ static void tcm_loop_set_default_node_attributes(struct se_node_acl *se_acl)
699 805
700static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd) 806static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd)
701{ 807{
702 return 1; 808 struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
809 struct tcm_loop_cmd, tl_se_cmd);
810
811 return tl_cmd->sc_cmd_tag;
703} 812}
704 813
705static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd) 814static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
@@ -932,7 +1041,10 @@ static int tcm_loop_drop_nexus(
932 struct tcm_loop_nexus *tl_nexus; 1041 struct tcm_loop_nexus *tl_nexus;
933 struct tcm_loop_hba *tl_hba = tpg->tl_hba; 1042 struct tcm_loop_hba *tl_hba = tpg->tl_hba;
934 1043
935 tl_nexus = tpg->tl_hba->tl_nexus; 1044 if (!tl_hba)
1045 return -ENODEV;
1046
1047 tl_nexus = tl_hba->tl_nexus;
936 if (!tl_nexus) 1048 if (!tl_nexus)
937 return -ENODEV; 1049 return -ENODEV;
938 1050
@@ -1061,8 +1173,56 @@ check_newline:
1061 1173
1062TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR); 1174TF_TPG_BASE_ATTR(tcm_loop, nexus, S_IRUGO | S_IWUSR);
1063 1175
1176static ssize_t tcm_loop_tpg_show_transport_status(
1177 struct se_portal_group *se_tpg,
1178 char *page)
1179{
1180 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1181 struct tcm_loop_tpg, tl_se_tpg);
1182 const char *status = NULL;
1183 ssize_t ret = -EINVAL;
1184
1185 switch (tl_tpg->tl_transport_status) {
1186 case TCM_TRANSPORT_ONLINE:
1187 status = "online";
1188 break;
1189 case TCM_TRANSPORT_OFFLINE:
1190 status = "offline";
1191 break;
1192 default:
1193 break;
1194 }
1195
1196 if (status)
1197 ret = snprintf(page, PAGE_SIZE, "%s\n", status);
1198
1199 return ret;
1200}
1201
1202static ssize_t tcm_loop_tpg_store_transport_status(
1203 struct se_portal_group *se_tpg,
1204 const char *page,
1205 size_t count)
1206{
1207 struct tcm_loop_tpg *tl_tpg = container_of(se_tpg,
1208 struct tcm_loop_tpg, tl_se_tpg);
1209
1210 if (!strncmp(page, "online", 6)) {
1211 tl_tpg->tl_transport_status = TCM_TRANSPORT_ONLINE;
1212 return count;
1213 }
1214 if (!strncmp(page, "offline", 7)) {
1215 tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
1216 return count;
1217 }
1218 return -EINVAL;
1219}
1220
1221TF_TPG_BASE_ATTR(tcm_loop, transport_status, S_IRUGO | S_IWUSR);
1222
1064static struct configfs_attribute *tcm_loop_tpg_attrs[] = { 1223static struct configfs_attribute *tcm_loop_tpg_attrs[] = {
1065 &tcm_loop_tpg_nexus.attr, 1224 &tcm_loop_tpg_nexus.attr,
1225 &tcm_loop_tpg_transport_status.attr,
1066 NULL, 1226 NULL,
1067}; 1227};
1068 1228
@@ -1334,11 +1494,11 @@ static int tcm_loop_register_configfs(void)
1334 /* 1494 /*
1335 * Setup default attribute lists for various fabric->tf_cit_tmpl 1495 * Setup default attribute lists for various fabric->tf_cit_tmpl
1336 */ 1496 */
1337 TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs; 1497 fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
1338 TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs; 1498 fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
1339 TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; 1499 fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
1340 TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; 1500 fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
1341 TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; 1501 fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
1342 /* 1502 /*
1343 * Once fabric->tf_ops has been setup, now register the fabric for 1503 * Once fabric->tf_ops has been setup, now register the fabric for
1344 * use within TCM 1504 * use within TCM