From: Vladimir Oltean <vladimir.oltean@nxp.com>
To: linux-phy@lists.infradead.org
Cc: Vinod Koul <vkoul@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-can@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-ide@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
linux-pci@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
linux-riscv@lists.infradead.org,
linux-rockchip@lists.infradead.org,
linux-samsung-soc@vger.kernel.org, linux-scsi@vger.kernel.org,
linux-sunxi@lists.linux.dev, linux-tegra@vger.kernel.org,
linux-usb@vger.kernel.org, netdev@vger.kernel.org,
spacemit@lists.linux.dev, UNGLinuxDriver@microchip.com,
Can Guo <quic_cang@quicinc.com>,
"James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
"Martin K. Petersen" <martin.petersen@oracle.com>,
Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>,
Nitin Rawat <quic_nitirawa@quicinc.com>,
Manivannan Sadhasivam <mani@kernel.org>
Subject: [PATCH v8 phy-next 13/31] scsi: ufs: qcom: keep separate track of PHY power state
Date: Tue, 5 May 2026 13:05:05 +0300 [thread overview]
Message-ID: <20260505100523.1922388-14-vladimir.oltean@nxp.com> (raw)
In-Reply-To: <20260505100523.1922388-1-vladimir.oltean@nxp.com>
The Generic PHY API needs the following call order:
phy_init() -> phy_power_on() -> phy_power_off() -> phy_exit()
with a balanced number of phy_init() <-> phy_exit() and
phy_power_on() <-> phy_power_off() calls.
The UFS framework is not exactly great in helping out with obeying these
requirements. For example, the Qualcomm UFS HCD driver insists pairing
the PHY power to the clock setup operations. But during driver removal,
we have:
ufshcd_hba_exit()
-> ufshcd_variant_hba_exit()
-> ufs_qcom_exit()
-> ufshcd_setup_clocks(hba, false)
which means that we will underflow the PHY power_count.
Adding a "bool power_count" to the driver and checking it before each
call helps avoid this issue.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Cc: Can Guo <quic_cang@quicinc.com>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Cc: Nitin Rawat <quic_nitirawa@quicinc.com>
Cc: Manivannan Sadhasivam <mani@kernel.org>
v7->v8: patch is new to fix an issue reported by Sashiko
https://sashiko.dev/#/patchset/20260430110652.558622-1-vladimir.oltean@nxp.com
---
drivers/ufs/host/ufs-qcom.c | 53 ++++++++++++++++++++++++++++---------
drivers/ufs/host/ufs-qcom.h | 1 +
2 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index e28edcfd13a1..c547d8643480 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -485,6 +485,42 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
return UFS_HS_G3;
}
+static int ufs_qcom_phy_power_on(struct ufs_qcom_host *host)
+{
+ int ret;
+
+ if (host->phy_powered_on)
+ return 0;
+
+ ret = phy_power_on(host->generic_phy);
+ if (ret) {
+ dev_err(host->hba->dev, "Failed to power on PHY: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ host->phy_powered_on = true;
+
+ return 0;
+}
+
+static void ufs_qcom_phy_power_off(struct ufs_qcom_host *host)
+{
+ int ret;
+
+ if (!host->phy_powered_on)
+ return;
+
+ ret = phy_power_off(host->generic_phy);
+ if (ret) {
+ dev_warn(host->hba->dev, "Failed to power off PHY: %pe\n",
+ ERR_PTR(ret));
+ return;
+ }
+
+ host->phy_powered_on = false;
+}
+
static int ufs_qcom_phy_change_mode(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -1390,7 +1426,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy;
int err;
/*
@@ -1401,8 +1436,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
if (!host)
return 0;
- phy = host->generic_phy;
-
switch (status) {
case PRE_CHANGE:
if (on) {
@@ -1420,20 +1453,14 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
ufs_qcom_dev_ref_clk_ctrl(host, false);
}
- err = phy_power_off(phy);
- if (err) {
- dev_err(hba->dev, "phy power off failed, ret=%d\n", err);
- return err;
- }
+ ufs_qcom_phy_power_off(host);
}
break;
case POST_CHANGE:
if (on) {
- err = phy_power_on(phy);
- if (err) {
- dev_err(hba->dev, "phy power on failed, ret = %d\n", err);
+ err = ufs_qcom_phy_power_on(host);
+ if (err)
return err;
- }
/* enable the device ref clock for HS mode*/
if (ufshcd_is_hs_mode(&hba->pwr_info))
@@ -1629,7 +1656,7 @@ static void ufs_qcom_exit(struct ufs_hba *hba)
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
ufs_qcom_disable_lane_clks(host);
- phy_power_off(host->generic_phy);
+ ufs_qcom_phy_power_off(host);
phy_exit(host->generic_phy);
}
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index 5d083331a7f4..6eafba3c203b 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -322,6 +322,7 @@ struct ufs_qcom_host {
struct clk_bulk_data *clks;
u32 num_clks;
bool is_lane_clks_enabled;
+ bool phy_powered_on;
struct icc_path *icc_ddr;
struct icc_path *icc_cpu;
--
2.34.1
next prev parent reply other threads:[~2026-05-05 10:07 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260505100523.1922388-1-vladimir.oltean@nxp.com>
2026-05-05 10:04 ` [PATCH v8 phy-next 01/31] PCI: cadence: Preserve all error codes in cdns_plat_pcie_probe() Vladimir Oltean
2026-05-05 16:26 ` Bjorn Helgaas
2026-05-05 10:04 ` [PATCH v8 phy-next 02/31] ata: add <linux/pm_runtime.h> where missing Vladimir Oltean
2026-05-05 10:04 ` [PATCH v8 phy-next 03/31] PCI: Add missing headers transitively included by <linux/phy/phy.h> Vladimir Oltean
2026-05-05 10:04 ` [PATCH v8 phy-next 04/31] usb: add " Vladimir Oltean
2026-05-05 10:04 ` [PATCH v8 phy-next 05/31] drm: add <linux/pm_runtime.h> where missing Vladimir Oltean
2026-05-05 10:04 ` [PATCH v8 phy-next 06/31] phy: " Vladimir Oltean
2026-05-05 10:04 ` [PATCH v8 phy-next 07/31] phy: spacemit: include missing <linux/phy/phy.h> Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 08/31] net: lan969x: include missing <linux/of.h> Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 09/31] PCI: Remove device links to PHY Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 10/31] scsi: ufs: exynos: use dedicated API for updating PHY bus width Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 11/31] scsi: ufs: qcom: call phy_init() before phy_power_on() Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 12/31] scsi: ufs: qcom: make use of QMP PHY dynamic gear switching ability Vladimir Oltean
2026-05-05 10:05 ` Vladimir Oltean [this message]
2026-05-05 10:05 ` [PATCH v8 phy-next 14/31] scsi: ufs: qcom: include missing <linux/interrupt.h> Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 15/31] drm/rockchip: dw_hdmi: avoid direct dereference of phy->dev.of_node Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 16/31] usb: host: tegra: " Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 17/31] usb: gadget: tegra-xudc: " Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 19/31] phy: make phy_get_mode(), phy_get_bus_width() NULL tolerant Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 20/31] phy: introduce phy_get_max_link_rate() helper for consumers Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 21/31] drm/rockchip: dsi: include PHY provider header Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 22/31] drm: bridge: cdns-mhdp8546: use consumer API for getting PHY bus width Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 23/31] media: sunxi: a83-mips-csi2: include PHY provider header Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 24/31] net: renesas: rswitch: " Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 25/31] pinctrl: tegra-xusb: " Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 26/31] power: supply: cpcap-charger: include missing <linux/property.h> Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 27/31] phy: move ulpi_phy.h from include/linux/phy/ to drivers/phy/ Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 28/31] phy: include PHY provider header (1/2) Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 29/31] phy: include PHY provider header (2/2) Vladimir Oltean
2026-05-05 10:05 ` [PATCH v8 phy-next 31/31] MAINTAINERS: add regexes for linux-phy Vladimir Oltean
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=20260505100523.1922388-14-vladimir.oltean@nxp.com \
--to=vladimir.oltean@nxp.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=UNGLinuxDriver@microchip.com \
--cc=dmitry.baryshkov@oss.qualcomm.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-can@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=linux-sunxi@lists.linux.dev \
--cc=linux-tegra@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mani@kernel.org \
--cc=martin.petersen@oracle.com \
--cc=neil.armstrong@linaro.org \
--cc=netdev@vger.kernel.org \
--cc=quic_cang@quicinc.com \
--cc=quic_nitirawa@quicinc.com \
--cc=spacemit@lists.linux.dev \
--cc=vkoul@kernel.org \
/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