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

scsi: mpi3mr: Task Abort EH Support

Add Task Abort support to handle SCSI command timeouts, ensuring recovery
and cleanup of timed-out commands. This completes the error handling
framework for mpi3mr driver, which already includes device reset, target
reset, bus reset, and host reset.

Co-developed-by: Sathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: Sathya Prakash <sathya.prakash@broadcom.com>
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
Link: https://lore.kernel.org/r/20250304191453.12994-1-chandrakanth.patil@broadcom.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Chandrakanth Patil and committed by
Martin K. Petersen
bde2ff79 7dcbda8a

+99
+99
drivers/scsi/mpi3mr/mpi3mr_os.c
··· 3839 3839 tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle); 3840 3840 3841 3841 if (scmd) { 3842 + if (tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { 3843 + cmd_priv = scsi_cmd_priv(scmd); 3844 + if (!cmd_priv) 3845 + goto out_unlock; 3846 + 3847 + struct op_req_qinfo *op_req_q; 3848 + 3849 + op_req_q = &mrioc->req_qinfo[cmd_priv->req_q_idx]; 3850 + tm_req.task_host_tag = cpu_to_le16(cmd_priv->host_tag); 3851 + tm_req.task_request_queue_id = 3852 + cpu_to_le16(op_req_q->qid); 3853 + } 3842 3854 sdev = scmd->device; 3843 3855 sdev_priv_data = sdev->hostdata; 3844 3856 scsi_tgt_priv_data = ((sdev_priv_data) ? ··· 4395 4383 sdev_printk(KERN_INFO, scmd->device, 4396 4384 "%s: device(LUN) reset is %s for scmd(%p)\n", mrioc->name, 4397 4385 ((retval == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); 4386 + 4387 + return retval; 4388 + } 4389 + 4390 + /** 4391 + * mpi3mr_eh_abort - Callback function for abort error handling 4392 + * @scmd: SCSI command reference 4393 + * 4394 + * Issues Abort Task Management if the command is in LLD scope 4395 + * and verifies if it is aborted successfully, and return status 4396 + * accordingly. 4397 + * 4398 + * Return: SUCCESS if the abort was successful, otherwise FAILED 4399 + */ 4400 + static int mpi3mr_eh_abort(struct scsi_cmnd *scmd) 4401 + { 4402 + struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host); 4403 + struct mpi3mr_stgt_priv_data *stgt_priv_data; 4404 + struct mpi3mr_sdev_priv_data *sdev_priv_data; 4405 + struct scmd_priv *cmd_priv; 4406 + u16 dev_handle, timeout = MPI3MR_ABORTTM_TIMEOUT; 4407 + u8 resp_code = 0; 4408 + int retval = FAILED, ret = 0; 4409 + struct request *rq = scsi_cmd_to_rq(scmd); 4410 + unsigned long scmd_age_ms = jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc); 4411 + unsigned long scmd_age_sec = scmd_age_ms / HZ; 4412 + 4413 + sdev_printk(KERN_INFO, scmd->device, 4414 + "%s: attempting abort task for scmd(%p)\n", mrioc->name, scmd); 4415 + 4416 + sdev_printk(KERN_INFO, scmd->device, 4417 + "%s: scmd(0x%p) is outstanding for %lus %lums, timeout %us, retries %d, allowed %d\n", 4418 + mrioc->name, scmd, scmd_age_sec, scmd_age_ms % HZ, rq->timeout / HZ, 4419 + scmd->retries, scmd->allowed); 4420 + 4421 + scsi_print_command(scmd); 4422 + 4423 + sdev_priv_data = scmd->device->hostdata; 4424 + if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) { 4425 + sdev_printk(KERN_INFO, scmd->device, 4426 + "%s: Device not available, Skip issuing abort task\n", 4427 + mrioc->name); 4428 + retval = SUCCESS; 4429 + goto out; 4430 + } 4431 + 4432 + stgt_priv_data = sdev_priv_data->tgt_priv_data; 4433 + dev_handle = stgt_priv_data->dev_handle; 4434 + 4435 + cmd_priv = scsi_cmd_priv(scmd); 4436 + if (!cmd_priv->in_lld_scope || 4437 + cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID) { 4438 + sdev_printk(KERN_INFO, scmd->device, 4439 + "%s: scmd (0x%p) not in LLD scope, Skip issuing Abort Task\n", 4440 + mrioc->name, scmd); 4441 + retval = SUCCESS; 4442 + goto out; 4443 + } 4444 + 4445 + if (stgt_priv_data->dev_removed) { 4446 + sdev_printk(KERN_INFO, scmd->device, 4447 + "%s: Device (handle = 0x%04x) removed, Skip issuing Abort Task\n", 4448 + mrioc->name, dev_handle); 4449 + retval = FAILED; 4450 + goto out; 4451 + } 4452 + 4453 + ret = mpi3mr_issue_tm(mrioc, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 4454 + dev_handle, sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS, 4455 + timeout, &mrioc->host_tm_cmds, &resp_code, scmd); 4456 + 4457 + if (ret) 4458 + goto out; 4459 + 4460 + if (cmd_priv->in_lld_scope) { 4461 + sdev_printk(KERN_INFO, scmd->device, 4462 + "%s: Abort task failed. scmd (0x%p) was not terminated\n", 4463 + mrioc->name, scmd); 4464 + goto out; 4465 + } 4466 + 4467 + retval = SUCCESS; 4468 + out: 4469 + sdev_printk(KERN_INFO, scmd->device, 4470 + "%s: Abort Task %s for scmd (0x%p)\n", mrioc->name, 4471 + ((retval == SUCCESS) ? "SUCCEEDED" : "FAILED"), scmd); 4398 4472 4399 4473 return retval; 4400 4474 } ··· 5167 5069 .scan_finished = mpi3mr_scan_finished, 5168 5070 .scan_start = mpi3mr_scan_start, 5169 5071 .change_queue_depth = mpi3mr_change_queue_depth, 5072 + .eh_abort_handler = mpi3mr_eh_abort, 5170 5073 .eh_device_reset_handler = mpi3mr_eh_dev_reset, 5171 5074 .eh_target_reset_handler = mpi3mr_eh_target_reset, 5172 5075 .eh_bus_reset_handler = mpi3mr_eh_bus_reset,