Skip to content

Commit 51c1c5f

Browse files
peter changmartinkpetersen
authored andcommitted
scsi: pm80xx: Cleanup command when a reset times out
Added the fix so the if driver properly sent the abort it tries to remove it from the firmware's list of outstanding commands regardless of the abort status. This means that the task gets freed 'now' rather than possibly getting freed later when the scsi layer thinks it's leaked but still valid. Link: https://lore.kernel.org/r/[email protected] Acked-by: Jack Wang <[email protected]> Signed-off-by: peter chang <[email protected]> Signed-off-by: Deepak Ukey <[email protected]> Signed-off-by: Viswas G <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 91a43fa commit 51c1c5f

File tree

1 file changed

+37
-13
lines changed

1 file changed

+37
-13
lines changed

drivers/scsi/pm8001/pm8001_sas.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task)
12041204
pm8001_dev = dev->lldd_dev;
12051205
pm8001_ha = pm8001_find_ha_by_dev(dev);
12061206
phy_id = pm8001_dev->attached_phy;
1207-
rc = pm8001_find_tag(task, &tag);
1208-
if (rc == 0) {
1207+
ret = pm8001_find_tag(task, &tag);
1208+
if (ret == 0) {
12091209
pm8001_printk("no tag for task:%p\n", task);
12101210
return TMF_RESP_FUNC_FAILED;
12111211
}
@@ -1243,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task)
12431243

12441244
/* 2. Send Phy Control Hard Reset */
12451245
reinit_completion(&completion);
1246+
phy->port_reset_status = PORT_RESET_TMO;
12461247
phy->reset_success = false;
12471248
phy->enable_completion = &completion;
12481249
phy->reset_completion = &completion_reset;
12491250
ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
12501251
PHY_HARD_RESET);
1251-
if (ret)
1252-
goto out;
1253-
PM8001_MSG_DBG(pm8001_ha,
1254-
pm8001_printk("Waiting for local phy ctl\n"));
1255-
wait_for_completion(&completion);
1256-
if (!phy->reset_success)
1252+
if (ret) {
1253+
phy->enable_completion = NULL;
1254+
phy->reset_completion = NULL;
12571255
goto out;
1256+
}
12581257

1259-
/* 3. Wait for Port Reset complete / Port reset TMO */
1258+
/* In the case of the reset timeout/fail we still
1259+
* abort the command at the firmware. The assumption
1260+
* here is that the drive is off doing something so
1261+
* that it's not processing requests, and we want to
1262+
* avoid getting a completion for this and either
1263+
* leaking the task in libsas or losing the race and
1264+
* getting a double free.
1265+
*/
12601266
PM8001_MSG_DBG(pm8001_ha,
1267+
pm8001_printk("Waiting for local phy ctl\n"));
1268+
ret = wait_for_completion_timeout(&completion,
1269+
PM8001_TASK_TIMEOUT * HZ);
1270+
if (!ret || !phy->reset_success) {
1271+
phy->enable_completion = NULL;
1272+
phy->reset_completion = NULL;
1273+
} else {
1274+
/* 3. Wait for Port Reset complete or
1275+
* Port reset TMO
1276+
*/
1277+
PM8001_MSG_DBG(pm8001_ha,
12611278
pm8001_printk("Waiting for Port reset\n"));
1262-
wait_for_completion(&completion_reset);
1263-
if (phy->port_reset_status) {
1264-
pm8001_dev_gone_notify(dev);
1265-
goto out;
1279+
ret = wait_for_completion_timeout(
1280+
&completion_reset,
1281+
PM8001_TASK_TIMEOUT * HZ);
1282+
if (!ret)
1283+
phy->reset_completion = NULL;
1284+
WARN_ON(phy->port_reset_status ==
1285+
PORT_RESET_TMO);
1286+
if (phy->port_reset_status == PORT_RESET_TMO) {
1287+
pm8001_dev_gone_notify(dev);
1288+
goto out;
1289+
}
12661290
}
12671291

12681292
/*

0 commit comments

Comments
 (0)