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 4/7] ufs: core: Switch from clock gating to RPM
Date: Fri, 16 Jan 2026 10:26:06 -0800 [thread overview]
Message-ID: <20260116182628.3255116-5-bvanassche@acm.org> (raw)
In-Reply-To: <20260116182628.3255116-1-bvanassche@acm.org>
Make ufshcd_hold() and ufshcd_release() call RPM functions instead of
controlling clock gating directly. This patch does not change the power
consumption of systems with UFS devices: both clock gating and RPM
switch to the same low power state if the UFS device is not in use.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/ufs/core/ufshcd.c | 103 +++-----------------------------------
1 file changed, 8 insertions(+), 95 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 900b945444d1..b3d75152abd9 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -1936,72 +1936,10 @@ static void ufshcd_ungate_work(struct work_struct *work)
*/
void ufshcd_hold(struct ufs_hba *hba)
{
- bool flush_result;
- unsigned long flags;
-
- if (!ufshcd_is_clkgating_allowed(hba) ||
- !hba->clk_gating.is_initialized)
- return;
- spin_lock_irqsave(&hba->clk_gating.lock, flags);
- hba->clk_gating.active_reqs++;
-
-start:
- switch (hba->clk_gating.state) {
- case CLKS_ON:
- /*
- * Wait for the ungate work to complete if in progress.
- * Though the clocks may be in ON state, the link could
- * still be in hibner8 state if hibern8 is allowed
- * during clock gating.
- * Make sure we exit hibern8 state also in addition to
- * clocks being ON.
- */
- if (ufshcd_can_hibern8_during_gating(hba) &&
- ufshcd_is_link_hibern8(hba)) {
- spin_unlock_irqrestore(&hba->clk_gating.lock, flags);
- flush_result = flush_work(&hba->clk_gating.ungate_work);
- if (hba->clk_gating.is_suspended && !flush_result)
- return;
- spin_lock_irqsave(&hba->clk_gating.lock, flags);
- goto start;
- }
- break;
- case REQ_CLKS_OFF:
- if (cancel_delayed_work(&hba->clk_gating.gate_work)) {
- hba->clk_gating.state = CLKS_ON;
- trace_ufshcd_clk_gating(hba,
- hba->clk_gating.state);
- break;
- }
- /*
- * If we are here, it means gating work is either done or
- * currently running. Hence, fall through to cancel gating
- * work and to enable clocks.
- */
- fallthrough;
- case CLKS_OFF:
- hba->clk_gating.state = REQ_CLKS_ON;
- trace_ufshcd_clk_gating(hba,
- hba->clk_gating.state);
- queue_work(hba->clk_gating.clk_gating_workq,
- &hba->clk_gating.ungate_work);
- /*
- * fall through to check if we should wait for this
- * work to be done or not.
- */
- fallthrough;
- case REQ_CLKS_ON:
- spin_unlock_irqrestore(&hba->clk_gating.lock, flags);
- flush_work(&hba->clk_gating.ungate_work);
- /* Make sure state is CLKS_ON before returning */
- spin_lock_irqsave(&hba->clk_gating.lock, flags);
- goto start;
- default:
- dev_err(hba->dev, "%s: clk gating is in invalid state %d\n",
- __func__, hba->clk_gating.state);
- break;
- }
- spin_unlock_irqrestore(&hba->clk_gating.lock, flags);
+ /* blk_pm_runtime_init() sets q->dev */
+ if (hba->ufs_device_wlun && hba->ufs_device_wlun->request_queue->dev &&
+ !hba->pm_op_in_progress)
+ ufshcd_rpm_get_sync(hba);
}
EXPORT_SYMBOL_GPL(ufshcd_hold);
@@ -2073,37 +2011,12 @@ static void ufshcd_gate_work(struct work_struct *work)
}
}
-static void __ufshcd_release(struct ufs_hba *hba)
-{
- lockdep_assert_held(&hba->clk_gating.lock);
-
- if (!ufshcd_is_clkgating_allowed(hba))
- return;
-
- hba->clk_gating.active_reqs--;
-
- if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended ||
- !hba->clk_gating.is_initialized ||
- hba->clk_gating.state == CLKS_OFF)
- return;
-
- scoped_guard(spinlock_irqsave, hba->host->host_lock) {
- if (ufshcd_has_pending_tasks(hba) ||
- hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)
- return;
- }
-
- hba->clk_gating.state = REQ_CLKS_OFF;
- trace_ufshcd_clk_gating(hba, hba->clk_gating.state);
- queue_delayed_work(hba->clk_gating.clk_gating_workq,
- &hba->clk_gating.gate_work,
- msecs_to_jiffies(hba->clk_gating.delay_ms));
-}
-
void ufshcd_release(struct ufs_hba *hba)
{
- guard(spinlock_irqsave)(&hba->clk_gating.lock);
- __ufshcd_release(hba);
+ /* blk_pm_runtime_init() sets q->dev */
+ if (hba->ufs_device_wlun && hba->ufs_device_wlun->request_queue->dev &&
+ !hba->pm_op_in_progress)
+ ufshcd_rpm_put(hba);
}
EXPORT_SYMBOL_GPL(ufshcd_release);
next prev parent reply other threads:[~2026-01-16 18:27 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 ` [PATCH 3/7] ufs: core: Redirect clock gating to RPM Bart Van Assche
2026-01-17 2:05 ` kernel test robot
2026-01-17 2:16 ` kernel test robot
2026-01-16 18:26 ` Bart Van Assche [this message]
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-5-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