scsi: pm8001: Modify task abort handling for SATA task
When we try to abort a SATA task, the CCB of the task which we are trying to avoid may still complete. In this case, we should not touch the task associated with that CCB as we can race with libsas freeing the last later in sas_eh_handle_sas_errors() -> sas_eh_finish_cmd() for when TASK_IS_ABORTED is returned from sas_scsi_find_task() Signed-off-by: John Garry <john.garry@huawei.com> Link: https://lore.kernel.org/r/1665998435-199946-6-git-send-email-john.garry@huawei.com Tested-by: Damien Le Moal <damien.lemoal@opensource.wdc.com> Tested-by: Niklas Cassel <niklas.cassel@wdc.com> # pm80xx Acked-by: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
4ef4f1a615
commit
0b639decf6
drivers/scsi/pm8001
@ -2295,7 +2295,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
if (t->dev && (t->dev->lldd_dev))
|
if (t->dev && (t->dev->lldd_dev))
|
||||||
pm8001_dev = t->dev->lldd_dev;
|
pm8001_dev = t->dev->lldd_dev;
|
||||||
} else {
|
} else {
|
||||||
pm8001_dbg(pm8001_ha, FAIL, "task null\n");
|
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
|
||||||
|
ccb->ccb_tag);
|
||||||
|
pm8001_ccb_free(pm8001_ha, ccb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2675,8 +2677,17 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
|
|||||||
pm8001_dev = ccb->device;
|
pm8001_dev = ccb->device;
|
||||||
if (event)
|
if (event)
|
||||||
pm8001_dbg(pm8001_ha, FAIL, "sata IO status 0x%x\n", event);
|
pm8001_dbg(pm8001_ha, FAIL, "sata IO status 0x%x\n", event);
|
||||||
if (unlikely(!t || !t->lldd_task || !t->dev))
|
|
||||||
|
if (unlikely(!t)) {
|
||||||
|
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
|
||||||
|
ccb->ccb_tag);
|
||||||
|
pm8001_ccb_free(pm8001_ha, ccb);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(!t->lldd_task || !t->dev))
|
||||||
|
return;
|
||||||
|
|
||||||
ts = &t->task_status;
|
ts = &t->task_status;
|
||||||
pm8001_dbg(pm8001_ha, DEVIO,
|
pm8001_dbg(pm8001_ha, DEVIO,
|
||||||
"port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
|
"port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
|
||||||
|
@ -983,6 +983,7 @@ int pm8001_query_task(struct sas_task *task)
|
|||||||
/* mandatory SAM-3, still need free task/ccb info, abort the specified task */
|
/* mandatory SAM-3, still need free task/ccb info, abort the specified task */
|
||||||
int pm8001_abort_task(struct sas_task *task)
|
int pm8001_abort_task(struct sas_task *task)
|
||||||
{
|
{
|
||||||
|
struct pm8001_ccb_info *ccb = task->lldd_task;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 tag;
|
u32 tag;
|
||||||
struct domain_device *dev ;
|
struct domain_device *dev ;
|
||||||
@ -1113,6 +1114,13 @@ int pm8001_abort_task(struct sas_task *task)
|
|||||||
pm8001_dev, DS_OPERATIONAL);
|
pm8001_dev, DS_OPERATIONAL);
|
||||||
wait_for_completion(&completion);
|
wait_for_completion(&completion);
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* Ensure that if we see a completion for the ccb
|
||||||
|
* associated with the task which we are trying to
|
||||||
|
* abort then we should not touch the sas_task as it
|
||||||
|
* may race with libsas freeing it when return here.
|
||||||
|
*/
|
||||||
|
ccb->task = NULL;
|
||||||
ret = sas_execute_internal_abort_single(dev, tag, 0, NULL);
|
ret = sas_execute_internal_abort_single(dev, tag, 0, NULL);
|
||||||
}
|
}
|
||||||
rc = TMF_RESP_FUNC_COMPLETE;
|
rc = TMF_RESP_FUNC_COMPLETE;
|
||||||
|
@ -2396,7 +2396,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
|
|||||||
if (t->dev && (t->dev->lldd_dev))
|
if (t->dev && (t->dev->lldd_dev))
|
||||||
pm8001_dev = t->dev->lldd_dev;
|
pm8001_dev = t->dev->lldd_dev;
|
||||||
} else {
|
} else {
|
||||||
pm8001_dbg(pm8001_ha, FAIL, "task null\n");
|
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
|
||||||
|
ccb->ccb_tag);
|
||||||
|
pm8001_ccb_free(pm8001_ha, ccb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2813,12 +2815,16 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,
|
|||||||
ccb = &pm8001_ha->ccb_info[tag];
|
ccb = &pm8001_ha->ccb_info[tag];
|
||||||
t = ccb->task;
|
t = ccb->task;
|
||||||
pm8001_dev = ccb->device;
|
pm8001_dev = ccb->device;
|
||||||
|
if (unlikely(!t)) {
|
||||||
if (unlikely(!t || !t->lldd_task || !t->dev)) {
|
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
|
||||||
pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
|
ccb->ccb_tag);
|
||||||
|
pm8001_ccb_free(pm8001_ha, ccb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(!t->lldd_task || !t->dev))
|
||||||
|
return;
|
||||||
|
|
||||||
ts = &t->task_status;
|
ts = &t->task_status;
|
||||||
pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
|
pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
|
||||||
port_id, tag, event);
|
port_id, tag, event);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user