From: Naomi Chu <naomi.chu@mediatek.com>
To: <linux-scsi@vger.kernel.org>, <mkp@kernel.org>,
<avri.altman@sandisk.com>, <alim.akhtar@samsung.com>,
<James.Bottomley@HansenPartnership.com>, <bvanassche@acm.org>
Cc: <wsd_upstream@mediatek.com>, <naomi.chu@mediatek.com>,
<peter.wang@mediatek.com>, <alice.chao@mediatek.com>,
<chun-hung.wu@mediatek.com>, <linux-mediatek@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <ed.tsai@mediatek.com>
Subject: [PATCH v1] scsi: ufs: core: Hold a clock reference across the probe
Date: Wed, 9 Sep 2026 17:10:45 +0800 [thread overview]
Message-ID: <20260909091045.1134956-1-naomi.chu@mediatek.com> (raw)
Clock gating becomes possible as soon as ufshcd_init_clk_gating() has
run, and from that point on the probe keeps accessing host registers
without ever taking a clock reference. This has been safe only because
of the state check in __ufshcd_release(): gate_work is not queued
unless hba->ufshcd_state is UFSHCD_STATE_OPERATIONAL, and the promotion
to that state used to happen after the last register access of the
probe, at the end of ufshcd_probe_hba().
That is fragile: it only works while the promotion happens after the
register accesses. Commit a390e6677f41 ("scsi: ufs: core: Expand the
ufshcd_device_init(hba, true) call") changed that ordering by moving
the promotion into ufshcd_init(), which schedules ufshcd_async_scan()
afterwards. ufshcd_probe_hba() therefore now runs with the state
already promoted, and it accesses host registers without holding a
clock reference:
- on hosts with UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH it calls
ufshcd_hba_stop() and ufshcd_hba_enable() before
ufshcd_device_init() sets the state back to UFSHCD_STATE_RESET, and
both read REG_CONTROLLER_ENABLE, so gated clocks stall there instead
of just losing a write.
- it ends with an ufshcd_configure_auto_hibern8() write, which its
other callers do take a clock reference for.
Take a clock reference as soon as clock gating has been initialised and
keep it until the probe is over. It then does not matter who drops a
clock reference while the probe is running, and the register accesses
of the probe no longer depend on hba->ufshcd_state. The reference is
dropped by ufshcd_async_scan() once the scan has finished, or by the
new out_release label if the probe fails after it was taken.
Fixes: a390e6677f41 ("scsi: ufs: core: Expand the ufshcd_device_init(hba, true) call")
Signed-off-by: Naomi Chu <naomi.chu@mediatek.com>
---
drivers/ufs/core/ufshcd.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index ee21388e74f5..7d63287b5ca9 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -9550,6 +9550,7 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
ret = ufshcd_add_lus(hba);
out:
+ ufshcd_release(hba);
pm_runtime_put_sync(hba->dev);
if (ret)
@@ -11272,6 +11273,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
ufshcd_init_clk_gating(hba);
+ /* Released by ufshcd_async_scan(), or by out_release on failure. */
+ ufshcd_hold(hba);
+
ufshcd_init_clk_scaling(hba);
/*
@@ -11292,7 +11296,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
if (err) {
dev_err(hba->dev, "request irq failed\n");
- goto out_disable;
+ goto out_release;
} else {
hba->is_irq_enabled = true;
}
@@ -11308,7 +11312,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
dev_err(hba->dev, "Host controller enable failed\n");
ufshcd_print_evt_hist(hba);
ufshcd_print_host_state(hba);
- goto out_disable;
+ goto out_release;
}
INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work, ufshcd_rpm_dev_flush_recheck_work);
@@ -11322,7 +11326,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
err = ufshcd_add_scsi_host(hba);
if (err)
- goto out_disable;
+ goto out_release;
/* Hold auto suspend until async scan completes */
pm_runtime_get_sync(dev);
@@ -11342,7 +11346,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
err = ufshcd_link_startup(hba);
if (err)
- goto out_disable;
+ goto out_release;
if (hba->mcq_enabled)
ufshcd_config_mcq(hba);
@@ -11359,23 +11363,23 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Verify device initialization by sending NOP OUT UPIU */
err = ufshcd_verify_dev_init(hba);
if (err)
- goto out_disable;
+ goto out_release;
/* Initiate UFS initialization, and waiting until completion */
err = ufshcd_complete_dev_init(hba);
if (err)
- goto out_disable;
+ goto out_release;
err = ufshcd_device_params_init(hba);
if (err)
- goto out_disable;
+ goto out_release;
err = ufshcd_post_device_init(hba);
initialized:
ufshcd_process_probe_result(hba, probe_start, err);
if (err)
- goto out_disable;
+ goto out_release;
ufs_sysfs_add_nodes(hba->dev);
hba->dme_qos_sysfs_handle = sysfs_get_dirent(hba->dev->kobj.sd,
@@ -11386,6 +11390,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
ufshcd_pm_qos_init(hba);
return 0;
+out_release:
+ ufshcd_release(hba);
out_disable:
hba->is_irq_enabled = false;
ufshcd_hba_exit(hba);
--
2.45.2
next reply other threads:[~2026-09-09 9:11 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 9:10 Naomi Chu [this message]
2026-09-21 13:21 ` Peter Wang
2026-10-01 8:41 ` Stanley Jhu
2026-10-06 2:43 ` Martin K. Petersen (Oracle)
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=20260909091045.1134956-1-naomi.chu@mediatek.com \
--to=naomi.chu@mediatek.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=alice.chao@mediatek.com \
--cc=alim.akhtar@samsung.com \
--cc=avri.altman@sandisk.com \
--cc=bvanassche@acm.org \
--cc=chun-hung.wu@mediatek.com \
--cc=ed.tsai@mediatek.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-scsi@vger.kernel.org \
--cc=mkp@kernel.org \
--cc=peter.wang@mediatek.com \
--cc=wsd_upstream@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®