Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: "Martin K . Petersen" <martin.petersen@oracle.com>
Cc: linux-scsi@vger.kernel.org, Bart Van Assche <bvanassche@acm.org>,
	"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
	Peter Wang <peter.wang@mediatek.com>,
	Avri Altman <avri.altman@sandisk.com>,
	Bean Huo <beanhuo@micron.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	"Bao D. Nguyen" <quic_nguyenb@quicinc.com>
Subject: [PATCH 3/7] ufs: core: Redirect clock gating to RPM
Date: Fri, 16 Jan 2026 10:26:05 -0800	[thread overview]
Message-ID: <20260116182628.3255116-4-bvanassche@acm.org> (raw)
In-Reply-To: <20260116182628.3255116-1-bvanassche@acm.org>

Let the clkgate_enable and clkgate_delay_ms sysfs attributes control
runtime power management instead of clock gating. Enable runtime power
management if either UFSHCD_CAP_RPM_AUTOSUSPEND or UFSHCD_CAP_CLK_GATING
have been set.

This patch prepares for removing the clock gating code because:
- The functionality of the clock gating code is identical to the runtime
  power management code. Both track the number of SCSI commands that are in
  progress, gate clocks, disable VCC and VCCQ and trigger link hibernation
  after a delay if no commands are in progress.
- The runtime power management code is more efficient because it uses a
  per-CPU counter while the clock gating code uses a single counter that
  is protected by a spinlock. Every spinlock in the I/O path has a
  measurable performance impact. Additionally, the clock gating code
  sets the BLK_MQ_F_BLOCKING flag for all SCSI request queues. This flag
  increases the amount of time spent in the block layer on processing
  requests.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/ufs/core/ufshcd.c | 49 +++++++++++++++++++++++++--------------
 include/ufs/ufshcd.h      |  2 +-
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 2ee1947af797..900b945444d1 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -2107,18 +2107,31 @@ void ufshcd_release(struct ufs_hba *hba)
 }
 EXPORT_SYMBOL_GPL(ufshcd_release);
 
+/* The struct device instance that controls RPM for the UFS device. */
+static inline struct device *ufs_rpm_dev(struct ufs_hba *hba)
+{
+	return &hba->ufs_device_wlun->sdev_gendev;
+}
+
 static ssize_t ufshcd_clkgate_delay_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct ufs_hba *hba = dev_get_drvdata(dev);
+	struct device *rpm_dev = ufs_rpm_dev(hba);
 
-	return sysfs_emit(buf, "%lu\n", hba->clk_gating.delay_ms);
+	if (!rpm_dev->power.use_autosuspend)
+		return -EIO;
+
+	return sysfs_emit(buf, "%u\n", rpm_dev->power.autosuspend_delay);
 }
 
 void ufshcd_clkgate_delay_set(struct ufs_hba *hba, unsigned long value)
 {
-	guard(spinlock_irqsave)(&hba->clk_gating.lock);
-	hba->clk_gating.delay_ms = value;
+	struct device *rpm_dev = ufs_rpm_dev(hba);
+
+	device_lock(rpm_dev);
+	pm_runtime_set_autosuspend_delay(rpm_dev, value);
+	device_unlock(rpm_dev);
 }
 EXPORT_SYMBOL_GPL(ufshcd_clkgate_delay_set);
 
@@ -2126,8 +2139,12 @@ static ssize_t ufshcd_clkgate_delay_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ufs_hba *hba = dev_get_drvdata(dev);
+	struct device *rpm_dev = ufs_rpm_dev(hba);
 	unsigned long value;
 
+	if (!rpm_dev->power.use_autosuspend)
+		return -EIO;
+
 	if (kstrtoul(buf, 0, &value))
 		return -EINVAL;
 
@@ -2140,31 +2157,27 @@ static ssize_t ufshcd_clkgate_enable_show(struct device *dev,
 {
 	struct ufs_hba *hba = dev_get_drvdata(dev);
 
-	return sysfs_emit(buf, "%d\n", hba->clk_gating.is_enabled);
+	return sysfs_emit(buf, "%d\n", ufs_rpm_dev(hba)->power.runtime_auto);
 }
 
 static ssize_t ufshcd_clkgate_enable_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ufs_hba *hba = dev_get_drvdata(dev);
-	u32 value;
-
-	if (kstrtou32(buf, 0, &value))
-		return -EINVAL;
-
-	value = !!value;
-
-	guard(spinlock_irqsave)(&hba->clk_gating.lock);
+	struct device *rpm_dev = ufs_rpm_dev(hba);
+	bool value;
+	int err;
 
-	if (value == hba->clk_gating.is_enabled)
-		return count;
+	err = kstrtobool(buf, &value);
+	if (err)
+		return err;
 
+	device_lock(rpm_dev);
 	if (value)
-		__ufshcd_release(hba);
+		pm_runtime_allow(rpm_dev);
 	else
-		hba->clk_gating.active_reqs++;
-
-	hba->clk_gating.is_enabled = value;
+		pm_runtime_forbid(rpm_dev);
+	device_unlock(rpm_dev);
 
 	return count;
 }
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index b4aef7acd351..dac07a5cd998 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1224,7 +1224,7 @@ static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba)
 }
 static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
 {
-	return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND;
+	return hba->caps & (UFSHCD_CAP_RPM_AUTOSUSPEND | UFSHCD_CAP_CLK_GATING);
 }
 
 static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)

  parent reply	other threads:[~2026-01-16 18:26 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-16 18:26 [PATCH 0/7] ufs: Remove the clock gating code Bart Van Assche
2026-01-16 18:26 ` [PATCH 1/7] ufs: core: Change the type of an ufshcd_clkgate_delay_set() argument Bart Van Assche
2026-01-16 18:26 ` [PATCH 2/7] ufs: host: mediatek: Use ufshcd_clkgate_delay_set() Bart Van Assche
2026-01-16 18:26 ` Bart Van Assche [this message]
2026-01-17  2:05   ` [PATCH 3/7] ufs: core: Redirect clock gating to RPM kernel test robot
2026-01-17  2:16   ` kernel test robot
2026-01-16 18:26 ` [PATCH 4/7] ufs: core: Switch from " Bart Van Assche
2026-01-16 18:26 ` [PATCH 5/7] ufs: core: Remove unused code and data structures Bart Van Assche
2026-01-17  2:16   ` kernel test robot
2026-01-16 18:26 ` [PATCH 6/7] ufs: core: Remove superfluous ufshcd_{hold,release}() calls Bart Van Assche
2026-01-16 18:26 ` [PATCH 7/7] ufs: core: Remove ufshcd_{hold,release}() calls from the I/O path Bart Van Assche
2026-01-22 17:30 ` [PATCH 0/7] ufs: Remove the clock gating code Manivannan Sadhasivam
2026-01-23  7:26   ` Peter Wang (王信友)
2026-01-23 23:27     ` Bart Van Assche
2026-01-26  3:44       ` Peter Wang (王信友)
2026-01-26 22:27         ` Bart Van Assche

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=20260116182628.3255116-4-bvanassche@acm.org \
    --to=bvanassche@acm.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=adrian.hunter@intel.com \
    --cc=avri.altman@sandisk.com \
    --cc=beanhuo@micron.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=peter.wang@mediatek.com \
    --cc=quic_nguyenb@quicinc.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