From: Stanley Jhu <stanleyjhu@google.com>
To: linux-scsi@vger.kernel.org, "Martin K. Petersen" <mkp@kernel.org>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
Bart Van Assche <bvanassche@acm.org>,
Alim Akhtar <alim.akhtar@samsung.com>,
Avri Altman <avri.altman@sandisk.com>,
Bean Huo <beanhuo@micron.com>,
Peter Wang <peter.wang@mediatek.com>,
Stanley Chu <stanley.chu@mediatek.com>,
Can Guo <quic_cang@quicinc.com>,
"Bao D. Nguyen" <quic_nguyenb@quicinc.com>,
Asutosh Das <quic_asutoshd@quicinc.com>,
Hongjie Fang <hongjiefang@asrmicro.com>,
Praveen Talari <praveen.talari@oss.qualcomm.com>,
HOYOUNG SEO <hy50.seo@samsung.com>,
Brian Kao <powenkao@google.com>, Jens Axboe <axboe@kernel.dk>,
"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 8/9] scsi: ufs: core: Wake suspended consumer queues after host reset
Date: Thu, 12 Nov 2026 13:15:41 +0800 [thread overview]
Message-ID: <20261112051542.1539779-9-stanleyjhu@google.com> (raw)
In-Reply-To: <20261112051542.1539779-1-stanleyjhu@google.com>
ufshcd_err_handling_prepare() now disables runtime PM of the UFS device
W-LUN, and ufshcd_err_handling_unprepare() enables it again and learns
whether a host reset in the error handler run succeeded.
ufshcd_recover_pm_error() wakes the runtime-suspended logical units
after a host reset only when hba->dev or the W-LUN has
power.runtime_error set, so I/O waiting on a runtime-suspended logical
unit stays blocked when both flags are clear:
1. I/O to a runtime-suspended logical unit blocks in
__bio_queue_enter() and queues a runtime resume of the logical unit.
2. START STOP UNIT fails in the resume of the W-LUN supplier, and
rpm_resume() rolls the logical unit back to RPM_SUSPENDED with
power.runtime_error clear.
3. A later W-LUN runtime resume succeeds.
4. A fatal error makes ufshcd_err_handler() reset the host.
5. ufshcd_recover_pm_error() finds power.runtime_error clear on both
devices and skips the wake loop.
6. The I/O stays blocked in __bio_queue_enter() until another request
reaches the same queue.
Request a runtime resume of every runtime-suspended logical unit from
ufshcd_err_handling_unprepare() after every successful host reset,
whether or not power.runtime_error is set. Waking an idle logical unit
sends no SCSI command, and the logical unit returns to runtime suspend
after its autosuspend delay.
Requesting the resumes from ufshcd_err_handling_unprepare() needs two
more changes. First, issue them after pm_runtime_enable() on the W-LUN.
ufshcd_recover_pm_error() runs while W-LUN runtime PM is disabled, and
rpm_get_suppliers() ignores -EACCES from a disabled supplier. A logical
unit woken there resumes while its W-LUN supplier stays RPM_SUSPENDED.
Second, also runtime resume the UFS device W-LUN, synchronously and
before the logical units. ufshcd_err_handling_prepare() disables W-LUN
runtime PM without resuming the W-LUN, so the W-LUN stays RPM_SUSPENDED
after the reset when no logical unit is left runtime suspended to resume
it through the runtime PM device link. pm_request_resume() takes no
reference on hba->dev, so the pm_runtime_put(hba->dev) that follows
can runtime suspend hba->dev while the link is active and every
logical unit is runtime suspended.
Fixes: eef1d74bf88f ("PM: runtime: Only set runtime_error on suspend callback failures")
Cc: stable@vger.kernel.org # 7.3.x
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
drivers/ufs/core/ufshcd.c | 51 +++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 21 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 286ffb44772d..87d475e323b1 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -6961,6 +6961,33 @@ static bool ufshcd_err_handling_prepare(struct ufs_hba *hba)
return vops_resumed;
}
+#ifdef CONFIG_PM
+/*
+ * A logical unit whose runtime resume failed against the W-LUN may still have
+ * bios waiting in blk_queue_enter(). Request a runtime resume for every
+ * suspended logical unit to unblock them. Resume the W-LUN first and
+ * synchronously. ufshcd_err_handling_prepare() disabled its runtime PM
+ * without resuming it, and the caller drops its hba->dev reference next.
+ */
+static void ufshcd_resume_sdevs_after_reset(struct ufs_hba *hba)
+{
+ struct scsi_device *sdev;
+ struct request_queue *q;
+
+ ufshcd_rpm_resume(hba);
+ shost_for_each_device(sdev, hba->host) {
+ q = sdev->request_queue;
+ if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+ q->rpm_status == RPM_SUSPENDING))
+ pm_request_resume(q->dev);
+ }
+}
+#else
+static inline void ufshcd_resume_sdevs_after_reset(struct ufs_hba *hba)
+{
+}
+#endif
+
static void ufshcd_err_handling_unprepare(struct ufs_hba *hba,
bool vops_resumed, bool pm_recovered)
{
@@ -6981,6 +7008,9 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba,
if (ufshcd_is_clkscaling_supported(hba))
ufshcd_clk_scaling_suspend(hba, false);
pm_runtime_enable(&hba->ufs_device_wlun->sdev_gendev);
+ /* The W-LUN and logical units resume only after pm_runtime_enable(). */
+ if (pm_recovered)
+ ufshcd_resume_sdevs_after_reset(hba);
ufshcd_rpm_put(hba);
pm_runtime_put(hba->dev);
}
@@ -6998,10 +7028,6 @@ static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)
static void ufshcd_recover_pm_error(struct ufs_hba *hba)
{
struct scsi_target *starget = hba->ufs_device_wlun->sdev_target;
- struct Scsi_Host *shost = hba->host;
- struct scsi_device *sdev;
- struct request_queue *q;
- bool resume_sdev_queues = false;
hba->is_sys_suspended = false;
@@ -7012,7 +7038,6 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba)
if (hba->dev->power.runtime_error) {
/* hba->dev has no functional parent thus simplily set RPM_ACTIVE */
pm_runtime_set_active(hba->dev);
- resume_sdev_queues = true;
}
if (hba->ufs_device_wlun->sdev_gendev.power.runtime_error) {
@@ -7023,22 +7048,6 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba)
pm_runtime_get_sync(&starget->dev);
pm_runtime_set_active(&hba->ufs_device_wlun->sdev_gendev);
pm_runtime_put_sync(&starget->dev);
- resume_sdev_queues = true;
- }
-
- /*
- * If wlun device had runtime error, we also need to resume those
- * consumer scsi devices in case any of them has failed to be
- * resumed due to supplier runtime resume failure. This is to unblock
- * blk_queue_enter in case there are bios waiting inside it.
- */
- if (resume_sdev_queues) {
- shost_for_each_device(sdev, shost) {
- q = sdev->request_queue;
- if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
- q->rpm_status == RPM_SUSPENDING))
- pm_request_resume(q->dev);
- }
}
}
#else
--
2.56.0.567.gdb80ae8cd5-goog
next prev parent reply other threads:[~2026-11-12 5:16 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 5:15 [PATCH 0/9] scsi: ufs: core: Fix device management and PM recovery Stanley Jhu
2026-11-12 5:15 ` [PATCH 1/9] scsi: ufs: core: Do not poll unconfigured MCQ queues in the error handler Stanley Jhu
2026-11-12 5:15 ` [PATCH 2/9] scsi: ufs: core: Defer link recovery on reserved PM command timeout Stanley Jhu
2026-11-12 5:15 ` [PATCH 3/9] scsi: ufs: core: Wait for the reserved tag in ufshcd_get_dev_mgmt_cmd() Stanley Jhu
2026-11-12 5:15 ` [PATCH 4/9] scsi: ufs: core: Fail PM commands fast when fatal recovery is scheduled Stanley Jhu
2026-11-12 5:15 ` [PATCH 5/9] scsi: ufs: core: Disable W-LUN runtime PM in ufshcd_err_handling_prepare() Stanley Jhu
2026-11-12 5:15 ` [PATCH 6/9] block: Keep RPM_ACTIVE in blk_pre_runtime_resume() when already active Stanley Jhu
2026-11-12 5:15 ` [PATCH 7/9] scsi: ufs: core: Unwind variant resume in EH when reset fails Stanley Jhu
2026-11-12 5:15 ` Stanley Jhu [this message]
2026-11-12 5:15 ` [PATCH 9/9] scsi: ufs: core: Do not recover the link concurrently with a PM callback Stanley Jhu
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=20261112051542.1539779-9-stanleyjhu@google.com \
--to=stanleyjhu@google.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=alim.akhtar@samsung.com \
--cc=avri.altman@sandisk.com \
--cc=axboe@kernel.dk \
--cc=beanhuo@micron.com \
--cc=bvanassche@acm.org \
--cc=hongjiefang@asrmicro.com \
--cc=hy50.seo@samsung.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=mkp@kernel.org \
--cc=peter.wang@mediatek.com \
--cc=powenkao@google.com \
--cc=praveen.talari@oss.qualcomm.com \
--cc=quic_asutoshd@quicinc.com \
--cc=quic_cang@quicinc.com \
--cc=quic_nguyenb@quicinc.com \
--cc=rafael.j.wysocki@intel.com \
--cc=stanley.chu@mediatek.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®