mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


  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®