Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcm_loop: TCQ and command abort support

Implement TCQ support, which enables us to do proper command
abort, too.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Hannes Reinecke and committed by
Nicholas Bellinger
969871cd a314d700

+69 -4
+67 -4
drivers/target/loopback/tcm_loop.c
··· 135 135 return sdev->queue_depth; 136 136 } 137 137 138 + static 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 154 * Locate the SAM Task Attr from struct scsi_cmnd * 140 155 */ ··· 251 236 } 252 237 253 238 tl_cmd->sc = sc; 239 + tl_cmd->sc_cmd_tag = sc->tag; 254 240 INIT_WORK(&tl_cmd->work, tcm_loop_submission_work); 255 241 queue_work(tcm_loop_workqueue, &tl_cmd->work); 256 242 return 0; ··· 263 247 */ 264 248 static int tcm_loop_issue_tmr(struct tcm_loop_tpg *tl_tpg, 265 249 struct tcm_loop_nexus *tl_nexus, 266 - int lun, enum tcm_tmreq_table tmr) 250 + int lun, int task, enum tcm_tmreq_table tmr) 267 251 { 268 252 struct se_cmd *se_cmd = NULL; 269 253 struct se_session *se_sess; ··· 299 283 if (rc < 0) 300 284 goto release; 301 285 286 + if (tmr == TMR_ABORT_TASK) 287 + se_cmd->se_tmr_req->ref_task_tag = task; 288 + 302 289 /* 303 290 * Locate the underlying TCM struct se_lun 304 291 */ ··· 327 308 kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); 328 309 kfree(tl_tmr); 329 310 return ret; 311 + } 312 + 313 + static int tcm_loop_abort_task(struct scsi_cmnd *sc) 314 + { 315 + struct tcm_loop_hba *tl_hba; 316 + struct tcm_loop_nexus *tl_nexus; 317 + struct tcm_loop_tpg *tl_tpg; 318 + int ret = FAILED; 319 + 320 + /* 321 + * Locate the tcm_loop_hba_t pointer 322 + */ 323 + tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host); 324 + /* 325 + * Locate the tl_nexus and se_sess pointers 326 + */ 327 + tl_nexus = tl_hba->tl_nexus; 328 + if (!tl_nexus) { 329 + pr_err("Unable to perform device reset without" 330 + " active I_T Nexus\n"); 331 + return FAILED; 332 + } 333 + 334 + /* 335 + * Locate the tl_tpg pointer from TargetID in sc->device->id 336 + */ 337 + tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; 338 + ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, 339 + sc->tag, TMR_ABORT_TASK); 340 + return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; 330 341 } 331 342 332 343 /* ··· 387 338 * Locate the tl_tpg pointer from TargetID in sc->device->id 388 339 */ 389 340 tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; 390 - ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, 391 - sc->device->lun, TMR_LUN_RESET); 341 + ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun, 342 + 0, TMR_LUN_RESET); 392 343 return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED; 393 344 } 394 345 ··· 400 351 401 352 static int tcm_loop_slave_configure(struct scsi_device *sd) 402 353 { 354 + if (sd->tagged_supported) { 355 + scsi_activate_tcq(sd, sd->queue_depth); 356 + scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG, 357 + sd->host->cmd_per_lun); 358 + } else { 359 + scsi_adjust_queue_depth(sd, 0, 360 + sd->host->cmd_per_lun); 361 + } 362 + 403 363 return 0; 404 364 } 405 365 ··· 418 360 .name = "TCM_Loopback", 419 361 .queuecommand = tcm_loop_queuecommand, 420 362 .change_queue_depth = tcm_loop_change_queue_depth, 363 + .change_queue_type = tcm_loop_change_queue_type, 364 + .eh_abort_handler = tcm_loop_abort_task, 421 365 .eh_device_reset_handler = tcm_loop_device_reset, 422 366 .can_queue = 1024, 423 367 .this_id = -1, ··· 779 719 780 720 static u32 tcm_loop_get_task_tag(struct se_cmd *se_cmd) 781 721 { 782 - return 1; 722 + struct tcm_loop_cmd *tl_cmd = container_of(se_cmd, 723 + struct tcm_loop_cmd, tl_se_cmd); 724 + 725 + return tl_cmd->sc_cmd_tag; 783 726 } 784 727 785 728 static int tcm_loop_get_cmd_state(struct se_cmd *se_cmd)
+2
drivers/target/loopback/tcm_loop.h
··· 10 10 struct tcm_loop_cmd { 11 11 /* State of Linux/SCSI CDB+Data descriptor */ 12 12 u32 sc_cmd_state; 13 + /* Tagged command queueing */ 14 + u32 sc_cmd_tag; 13 15 /* Pointer to the CDB+Data descriptor from Linux/SCSI subsystem */ 14 16 struct scsi_cmnd *sc; 15 17 /* The TCM I/O descriptor that is accessed via container_of() */