From: John Garry <john.garry@linux.dev>
To: Xingui Yang <yangxingui@huawei.com>,
yanaijie@huawei.com, jejb@linux.ibm.com, mkp@kernel.org
Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
linuxarm@huawei.com, liuyonglong@huawei.com,
kangfenglong@huawei.com
Subject: Re: [PATCH v3] scsi: libsas: Fix SMP IO deadlock during HA resume
Date: Mon, 21 Sep 2026 12:37:42 +0100 [thread overview]
Message-ID: <9a72eeb3-ca32-4241-9e21-74cf894a9bf1@linux.dev> (raw)
In-Reply-To: <20260918070307.381207-1-yangxingui@huawei.com>
On 9/18/26 08:03, Xingui Yang wrote:
> 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()
This seems like an obvious issue. How come it was not found earlier? It
is apparently fixing a patch which is 5 years old.
>
> 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() to take the reference while
> SAS_HA_RESUMING is set, and pm_runtime_put() to drop it. 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 the
> usage counter is still held from the sleep prepare and the put is
> 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 v2:
> - Drop the reference with pm_runtime_put() instead of
> pm_runtime_put_noidle().
>
> 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 | 20 +++++++++++++++++---
> 1 file changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
> index 811c9eb4fef1..5a8cdd3682fe 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -61,8 +61,22 @@ 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.
> + * Hold the reference without resuming, 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 +149,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
> }
> }
> mutex_unlock(&dev->ex_dev.cmd_mutex);
> - pm_runtime_put_sync(ha->dev);
> + pm_runtime_put(ha->dev);
>
> BUG_ON(retry == 3 && task != NULL);
> sas_free_task(task);
next prev parent reply other threads:[~2026-09-21 11:37 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 7:03 [PATCH v3] scsi: libsas: Fix SMP IO deadlock during HA resume Xingui Yang
2026-09-18 7:15 ` sashiko-bot
2026-09-20 6:27 ` yangxingui
2026-09-21 11:37 ` John Garry [this message]
2026-09-21 12:21 ` yangxingui
2026-09-21 14:05 ` John Garry
2026-09-22 3:10 ` yangxingui
2026-09-22 10:37 ` John Garry
2026-09-28 3:47 ` yangxingui
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9a72eeb3-ca32-4241-9e21-74cf894a9bf1@linux.dev \
--to=john.garry@linux.dev \
--cc=jejb@linux.ibm.com \
--cc=kangfenglong@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=liuyonglong@huawei.com \
--cc=mkp@kernel.org \
--cc=yanaijie@huawei.com \
--cc=yangxingui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.