All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] scsi: libsas: Fix SMP IO deadlock during HA resume
@ 2026-09-17 13:06 Xingui Yang
  2026-09-17 13:17 ` sashiko-bot
  0 siblings, 1 reply; 3+ messages in thread
From: Xingui Yang @ 2026-09-17 13:06 UTC (permalink / raw)
  To: john.garry, yanaijie, jejb, mkp
  Cc: linux-scsi, linux-kernel, linuxarm, yangxingui, liuyonglong,
	kangfenglong

When the controller resumes, sas_resume_ha() -> sas_drain_work()
processes the DISCE_RESUME work, which restores the ATA ports through
the libata error handler (ata_sas_port_resume() requests ATA_EH_RESET)
and waits for it in sas_ata_flush_pm_eh(). For an expander-attached
ATA device the hard reset in that recovery is an SMP PHY CONTROL
command sent to the expander:

  ata_eh_recover() -> ata_eh_reset() -> sas_ata_hard_reset()
    -> lldd_I_T_nexus_reset() -> sas_phy_reset()
      -> sas_smp_phy_control() -> smp_execute_task_sg()

For a runtime resume ha->dev is still RPM_RESUMING while the callback
runs, so the pm_runtime_get_sync() in smp_execute_task_sg() blocks
waiting for the resume to complete, but the resume is blocked in
sas_drain_work() waiting for that very SMP IO — a deadlock.

Use pm_runtime_get_noresume()/pm_runtime_put_noidle() when
SAS_HA_RESUMING is set: the usage counter stays elevated for the whole
duration of the IO, so the controller cannot autosuspend underneath an
in-flight SMP IO issued by a thread which the drain does not wait on,
while avoiding the wait for the already ongoing resume. The hardware
is already initialized by the LLDD before sas_resume_ha() runs.
SAS_HA_RESUMING is also set during a system sleep resume, where
ha->dev is RPM_ACTIVE and the noresume variants are harmless.

Outside of the resume window, convert the pm_runtime_get_sync() call
to pm_runtime_resume_and_get() and check the result, so that an SMP IO
is not submitted to a host whose runtime resume failed (the return
value was previously ignored).

Only hisi_sas enables runtime PM among libsas LLDDs, so other drivers
(pm8001, isci, aic94xx, mvsas) are unaffected.

Fixes: 0da7ca4c4fd9 ("scsi: libsas: Resume host while sending SMP I/Os")
Signed-off-by: Xingui Yang <yangxingui@huawei.com>
---
Changes since v1:

- Use pm_runtime_get_noresume()/put_noidle() during HA resume instead
  of skipping the PM reference entirely, so an in-flight SMP IO always
  keeps autosuspend away.
- Convert pm_runtime_get_sync() to pm_runtime_resume_and_get() and
  check the result (pre-existing issue flagged by sashiko).

 drivers/scsi/libsas/sas_expander.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 811c9eb4fef1..43cb90188f44 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -61,8 +61,23 @@ static int smp_execute_task_sg(struct domain_device *dev,
 	struct sas_internal *i =
 		to_sas_internal(dev->port->ha->shost->transportt);
 	struct sas_ha_struct *ha = dev->port->ha;
-
-	pm_runtime_get_sync(ha->dev);
+	bool ha_resuming = test_bit(SAS_HA_RESUMING, &ha->state);
+
+	/*
+	 * While the host is resuming, ha->dev may be RPM_RESUMING and
+	 * the resume blocked in sas_drain_work() waiting for this very
+	 * SMP IO, so waiting for the host to resume here would deadlock.
+	 * Use the noresume/noidle variants to still hold a PM reference
+	 * for the duration of the IO, the hardware is already initialized
+	 * by the LLDD before sas_resume_ha() runs.
+	 */
+	if (ha_resuming) {
+		pm_runtime_get_noresume(ha->dev);
+	} else {
+		res = pm_runtime_resume_and_get(ha->dev);
+		if (res)
+			return res;
+	}
 	mutex_lock(&dev->ex_dev.cmd_mutex);
 	for (retry = 0; retry < 3; retry++) {
 		if (test_bit(SAS_DEV_GONE, &dev->state)) {
@@ -135,7 +150,10 @@ static int smp_execute_task_sg(struct domain_device *dev,
 		}
 	}
 	mutex_unlock(&dev->ex_dev.cmd_mutex);
-	pm_runtime_put_sync(ha->dev);
+	if (ha_resuming)
+		pm_runtime_put_noidle(ha->dev);
+	else
+		pm_runtime_put_sync(ha->dev);
 
 	BUG_ON(retry == 3 && task != NULL);
 	sas_free_task(task);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] scsi: libsas: Fix SMP IO deadlock during HA resume
  2026-09-17 13:06 [PATCH v2] scsi: libsas: Fix SMP IO deadlock during HA resume Xingui Yang
@ 2026-09-17 13:17 ` sashiko-bot
  2026-09-18  6:59   ` yangxingui
  0 siblings, 1 reply; 3+ messages in thread
From: sashiko-bot @ 2026-09-17 13:17 UTC (permalink / raw)
  To: Xingui Yang; +Cc: linux-scsi

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] libsas: missed PM autosuspend in smp_execute_task_sg()
--

commit 8e09b6455fc925eb255f96d9d3584cbd10d1bdaa
Author: Xingui Yang <yangxingui@huawei.com>

scsi: libsas: Fix SMP IO deadlock during HA resume

This commit fixes a deadlock during controller resume by using
pm_runtime_get_noresume() and pm_runtime_put_noidle() when
SAS_HA_RESUMING is set. Outside of the resume window, it converts
pm_runtime_get_sync() to pm_runtime_resume_and_get() to handle
runtime resume failures.

> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
> index 811c9eb4fef11..a17b938cd3b7c 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c

[ ... ]

> @@ -135,7 +150,10 @@ static int smp_execute_task_sg(struct domain_device *dev,
>  		}
>  	}
>  	mutex_unlock(&dev->ex_dev.cmd_mutex);
> -	pm_runtime_put_sync(ha->dev);
> +	if (ha_resuming)
> +		pm_runtime_put_noidle(ha->dev);

[Severity: Medium]
Does this leave the device permanently in the RPM_ACTIVE state if this
thread outlives the host resume?

If an independent thread starts an SMP IO while SAS_HA_RESUMING is set,
it increments the PM usage count via pm_runtime_get_noresume(). If the
host resume process finishes before this SMP IO completes, the PM core
drops its own reference and performs an idle check, which fails because
this independent thread still holds a reference.

When this thread finishes and calls pm_runtime_put_noidle(), the usage
count drops to 0 but the idle check is explicitly skipped. This means
no autosuspend will be queued, and the device might leak its active
state, preventing the controller from autosuspending and leading to
higher power consumption.

> +	else
> +		pm_runtime_put_sync(ha->dev);
>  
>  	BUG_ON(retry == 3 && task != NULL);
>  	sas_free_task(task);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260917130642.1796231-1-yangxingui@huawei.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] scsi: libsas: Fix SMP IO deadlock during HA resume
  2026-09-17 13:17 ` sashiko-bot
@ 2026-09-18  6:59   ` yangxingui
  0 siblings, 0 replies; 3+ messages in thread
From: yangxingui @ 2026-09-18  6:59 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: linux-scsi



On 2026/9/17 21:17, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] libsas: missed PM autosuspend in smp_execute_task_sg()
> --
> 
> commit 8e09b6455fc925eb255f96d9d3584cbd10d1bdaa
> Author: Xingui Yang <yangxingui@huawei.com>
> 
> scsi: libsas: Fix SMP IO deadlock during HA resume
> 
> This commit fixes a deadlock during controller resume by using
> pm_runtime_get_noresume() and pm_runtime_put_noidle() when
> SAS_HA_RESUMING is set. Outside of the resume window, it converts
> pm_runtime_get_sync() to pm_runtime_resume_and_get() to handle
> runtime resume failures.
> 
>> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
>> index 811c9eb4fef11..a17b938cd3b7c 100644
>> --- a/drivers/scsi/libsas/sas_expander.c
>> +++ b/drivers/scsi/libsas/sas_expander.c
> 
> [ ... ]
> 
>> @@ -135,7 +150,10 @@ static int smp_execute_task_sg(struct domain_device *dev,
>>   		}
>>   	}
>>   	mutex_unlock(&dev->ex_dev.cmd_mutex);
>> -	pm_runtime_put_sync(ha->dev);
>> +	if (ha_resuming)
>> +		pm_runtime_put_noidle(ha->dev);
> 
> [Severity: Medium]
> Does this leave the device permanently in the RPM_ACTIVE state if this
> thread outlives the host resume?

Ok, v3 drops the reference with pm_runtime_put() instead. ^_^

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-18  6:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-17 13:06 [PATCH v2] scsi: libsas: Fix SMP IO deadlock during HA resume Xingui Yang
2026-09-17 13:17 ` sashiko-bot
2026-09-18  6:59   ` yangxingui

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.