Skip to content

Commit bde2ff7

Browse files
cp890582martinkpetersen
authored andcommitted
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 <[email protected]> Signed-off-by: Sathya Prakash <[email protected]> Signed-off-by: Chandrakanth Patil <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Himanshu Madhani <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 7dcbda8 commit bde2ff7

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

drivers/scsi/mpi3mr/mpi3mr_os.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3839,6 +3839,18 @@ int mpi3mr_issue_tm(struct mpi3mr_ioc *mrioc, u8 tm_type,
38393839
tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, handle);
38403840

38413841
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+
}
38423854
sdev = scmd->device;
38433855
sdev_priv_data = sdev->hostdata;
38443856
scsi_tgt_priv_data = ((sdev_priv_data) ?
@@ -4387,6 +4399,92 @@ static int mpi3mr_eh_dev_reset(struct scsi_cmnd *scmd)
43874399
return retval;
43884400
}
43894401

4402+
/**
4403+
* mpi3mr_eh_abort - Callback function for abort error handling
4404+
* @scmd: SCSI command reference
4405+
*
4406+
* Issues Abort Task Management if the command is in LLD scope
4407+
* and verifies if it is aborted successfully, and return status
4408+
* accordingly.
4409+
*
4410+
* Return: SUCCESS if the abort was successful, otherwise FAILED
4411+
*/
4412+
static int mpi3mr_eh_abort(struct scsi_cmnd *scmd)
4413+
{
4414+
struct mpi3mr_ioc *mrioc = shost_priv(scmd->device->host);
4415+
struct mpi3mr_stgt_priv_data *stgt_priv_data;
4416+
struct mpi3mr_sdev_priv_data *sdev_priv_data;
4417+
struct scmd_priv *cmd_priv;
4418+
u16 dev_handle, timeout = MPI3MR_ABORTTM_TIMEOUT;
4419+
u8 resp_code = 0;
4420+
int retval = FAILED, ret = 0;
4421+
struct request *rq = scsi_cmd_to_rq(scmd);
4422+
unsigned long scmd_age_ms = jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc);
4423+
unsigned long scmd_age_sec = scmd_age_ms / HZ;
4424+
4425+
sdev_printk(KERN_INFO, scmd->device,
4426+
"%s: attempting abort task for scmd(%p)\n", mrioc->name, scmd);
4427+
4428+
sdev_printk(KERN_INFO, scmd->device,
4429+
"%s: scmd(0x%p) is outstanding for %lus %lums, timeout %us, retries %d, allowed %d\n",
4430+
mrioc->name, scmd, scmd_age_sec, scmd_age_ms % HZ, rq->timeout / HZ,
4431+
scmd->retries, scmd->allowed);
4432+
4433+
scsi_print_command(scmd);
4434+
4435+
sdev_priv_data = scmd->device->hostdata;
4436+
if (!sdev_priv_data || !sdev_priv_data->tgt_priv_data) {
4437+
sdev_printk(KERN_INFO, scmd->device,
4438+
"%s: Device not available, Skip issuing abort task\n",
4439+
mrioc->name);
4440+
retval = SUCCESS;
4441+
goto out;
4442+
}
4443+
4444+
stgt_priv_data = sdev_priv_data->tgt_priv_data;
4445+
dev_handle = stgt_priv_data->dev_handle;
4446+
4447+
cmd_priv = scsi_cmd_priv(scmd);
4448+
if (!cmd_priv->in_lld_scope ||
4449+
cmd_priv->host_tag == MPI3MR_HOSTTAG_INVALID) {
4450+
sdev_printk(KERN_INFO, scmd->device,
4451+
"%s: scmd (0x%p) not in LLD scope, Skip issuing Abort Task\n",
4452+
mrioc->name, scmd);
4453+
retval = SUCCESS;
4454+
goto out;
4455+
}
4456+
4457+
if (stgt_priv_data->dev_removed) {
4458+
sdev_printk(KERN_INFO, scmd->device,
4459+
"%s: Device (handle = 0x%04x) removed, Skip issuing Abort Task\n",
4460+
mrioc->name, dev_handle);
4461+
retval = FAILED;
4462+
goto out;
4463+
}
4464+
4465+
ret = mpi3mr_issue_tm(mrioc, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
4466+
dev_handle, sdev_priv_data->lun_id, MPI3MR_HOSTTAG_BLK_TMS,
4467+
timeout, &mrioc->host_tm_cmds, &resp_code, scmd);
4468+
4469+
if (ret)
4470+
goto out;
4471+
4472+
if (cmd_priv->in_lld_scope) {
4473+
sdev_printk(KERN_INFO, scmd->device,
4474+
"%s: Abort task failed. scmd (0x%p) was not terminated\n",
4475+
mrioc->name, scmd);
4476+
goto out;
4477+
}
4478+
4479+
retval = SUCCESS;
4480+
out:
4481+
sdev_printk(KERN_INFO, scmd->device,
4482+
"%s: Abort Task %s for scmd (0x%p)\n", mrioc->name,
4483+
((retval == SUCCESS) ? "SUCCEEDED" : "FAILED"), scmd);
4484+
4485+
return retval;
4486+
}
4487+
43904488
/**
43914489
* mpi3mr_scan_start - Scan start callback handler
43924490
* @shost: SCSI host reference
@@ -5069,6 +5167,7 @@ static const struct scsi_host_template mpi3mr_driver_template = {
50695167
.scan_finished = mpi3mr_scan_finished,
50705168
.scan_start = mpi3mr_scan_start,
50715169
.change_queue_depth = mpi3mr_change_queue_depth,
5170+
.eh_abort_handler = mpi3mr_eh_abort,
50725171
.eh_device_reset_handler = mpi3mr_eh_dev_reset,
50735172
.eh_target_reset_handler = mpi3mr_eh_target_reset,
50745173
.eh_bus_reset_handler = mpi3mr_eh_bus_reset,

0 commit comments

Comments
 (0)