From: Pengpeng Hou <hppiscas@163.com>
To: b-liu@ti.com
Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org,
s.nawrocki@samsung.com, kishon@kernel.org, balbi@ti.com,
tony@atomide.com, hppiscas@163.com
Subject: [PATCH v2 1/3] usb: musb: omap2430: track PHY references and check initial setup
Date: Tue, 22 Sep 2026 08:44:12 +0800 [thread overview]
Message-ID: <20260922004414.4192-2-hppiscas@163.com> (raw)
In-Reply-To: <20260922004414.4192-1-hppiscas@163.com>
omap2430_musb_init() ignores generic PHY initialization and power-on
errors before accessing the controller. The same PHY is later acquired
and released by runtime PM, system PM and platform exit.
Track initialization and power references separately, and use shared
helpers at all these acquisition and release sites. A failed power-on
releases its initialization reference when possible; a failed release
retains the corresponding ownership flag so a later cleanup does not
double-release or lose track of it. Suspend failures attempt to restore
the PHY before returning the original error.
Abort initial setup before accessing the interface registers on failure.
musb_init_controller() skips platform exit when platform init fails, so
initial setup must unwind its own references. Platform exit uses the same
ownership-aware release path when entered after later setup failures.
Keep the PHY pointer in the parent glue, which owns the managed PHY
handle, so parent removal can retry a release left by a failed child
initialization or exit even after the child clears musb->phy.
Keep phy_suspended as the system-sleep ordering flag: it defers access to
I2C/SPI PHYs until their normal resume phase. It is not a substitute for
tracking the two generic PHY reference counts.
The issue was found by our static-analysis tool.
Fixes: 3e3101d57c50 ("usb: musb: omap2430: use the new generic PHY framework")
Assisted-by: gpt 5
Signed-off-by: Pengpeng Hou <hppiscas@163.com>
---
drivers/usb/musb/omap2430.c | 105 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 93 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 6e749faac33c..df807ee9deec 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -34,14 +34,71 @@ struct omap2430_glue {
enum musb_vbus_id_status status;
struct work_struct omap_musb_mailbox_work;
struct device *control_otghs;
+ struct phy *phy;
unsigned int is_runtime_suspended:1;
unsigned int needs_resume:1;
+ /* Defer PHY access until the normal system-resume phase. */
unsigned int phy_suspended:1;
+ unsigned int phy_initialized:1;
+ unsigned int phy_powered:1;
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
static struct omap2430_glue *_glue;
+static int omap2430_phy_power_on(struct omap2430_glue *glue)
+{
+ int ret;
+
+ if (!glue->phy)
+ return 0;
+
+ if (!glue->phy_initialized) {
+ ret = phy_init(glue->phy);
+ if (ret)
+ return ret;
+ glue->phy_initialized = 1;
+ }
+
+ if (glue->phy_powered)
+ return 0;
+
+ ret = phy_power_on(glue->phy);
+ if (ret) {
+ /* Keep ownership if phy_exit() itself cannot release the reference. */
+ if (!phy_exit(glue->phy))
+ glue->phy_initialized = 0;
+ return ret;
+ }
+ glue->phy_powered = 1;
+
+ return 0;
+}
+
+static int omap2430_phy_power_off(struct omap2430_glue *glue)
+{
+ int ret;
+
+ if (!glue->phy)
+ return 0;
+
+ if (glue->phy_powered) {
+ ret = phy_power_off(glue->phy);
+ if (ret)
+ return ret;
+ glue->phy_powered = 0;
+ }
+
+ if (glue->phy_initialized) {
+ ret = phy_exit(glue->phy);
+ if (ret)
+ return ret;
+ glue->phy_initialized = 0;
+ }
+
+ return 0;
+}
+
static inline void omap2430_low_level_exit(struct musb *musb)
{
u32 l;
@@ -192,6 +249,7 @@ static int omap2430_musb_init(struct musb *musb)
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
struct omap_musb_board_data *data = plat->board_data;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
/* We require some kind of external transceiver, hooked
* up through ULPI. TWL4030-family PMICs include one,
@@ -222,8 +280,10 @@ static int omap2430_musb_init(struct musb *musb)
return PTR_ERR(musb->phy);
}
musb->isr = omap2430_musb_interrupt;
- phy_init(musb->phy);
- phy_power_on(musb->phy);
+ glue->phy = musb->phy;
+ status = omap2430_phy_power_on(glue);
+ if (status)
+ return status;
l = musb_readl(musb->mregs, OTG_INTERFSEL);
@@ -272,10 +332,12 @@ static int omap2430_musb_exit(struct musb *musb)
{
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+ int ret;
omap2430_low_level_exit(musb);
- phy_power_off(musb->phy);
- phy_exit(musb->phy);
+ ret = omap2430_phy_power_off(glue);
+ if (ret)
+ dev_err(dev, "failed to shut down PHY: %d\n", ret);
musb->phy = NULL;
cancel_work_sync(&glue->omap_musb_mailbox_work);
@@ -471,9 +533,13 @@ static int omap2430_probe(struct platform_device *pdev)
static void omap2430_remove(struct platform_device *pdev)
{
struct omap2430_glue *glue = platform_get_drvdata(pdev);
+ int ret;
platform_device_unregister(glue->musb);
pm_runtime_disable(glue->dev);
+ ret = omap2430_phy_power_off(glue);
+ if (ret)
+ dev_err(&pdev->dev, "failed to release PHY references: %d\n", ret);
if (!IS_ERR(glue->control_otghs))
put_device(glue->control_otghs);
}
@@ -484,6 +550,7 @@ static int omap2430_runtime_suspend(struct device *dev)
{
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
+ int ret;
if (!musb)
return 0;
@@ -494,8 +561,13 @@ static int omap2430_runtime_suspend(struct device *dev)
omap2430_low_level_exit(musb);
if (!glue->phy_suspended) {
- phy_power_off(musb->phy);
- phy_exit(musb->phy);
+ ret = omap2430_phy_power_off(glue);
+ if (ret) {
+ if (omap2430_phy_power_on(glue))
+ dev_err(dev, "failed to restore PHY after suspend error\n");
+ omap2430_low_level_init(musb);
+ return ret;
+ }
}
glue->is_runtime_suspended = 1;
@@ -512,8 +584,7 @@ static int omap2430_runtime_resume(struct device *dev)
return 0;
if (!glue->phy_suspended) {
- phy_init(musb->phy);
- phy_power_on(musb->phy);
+ omap2430_phy_power_on(glue);
}
omap2430_low_level_init(musb);
@@ -533,9 +604,17 @@ static int omap2430_suspend(struct device *dev)
{
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
+ int ret;
- phy_power_off(musb->phy);
- phy_exit(musb->phy);
+ if (!musb)
+ return 0;
+
+ ret = omap2430_phy_power_off(glue);
+ if (ret) {
+ if (omap2430_phy_power_on(glue))
+ dev_err(dev, "failed to restore PHY after suspend error\n");
+ return ret;
+ }
glue->phy_suspended = 1;
return 0;
@@ -571,8 +650,10 @@ static int omap2430_resume(struct device *dev)
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- phy_init(musb->phy);
- phy_power_on(musb->phy);
+ if (!musb)
+ return 0;
+
+ omap2430_phy_power_on(glue);
glue->phy_suspended = 0;
return 0;
base-commit: f0100363d8c374bd8e9ea7c9ba02744f0b802ca4
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-09-22 0:44 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 0:44 [PATCH v2 0/3] usb: musb: omap2430: handle PHY setup failures across PM Pengpeng Hou
2026-09-22 0:44 ` Pengpeng Hou [this message]
2026-09-22 0:44 ` [PATCH v2 2/3] usb: musb: omap2430: stop runtime resume after PHY setup failure Pengpeng Hou
2026-09-22 0:44 ` [PATCH v2 3/3] usb: musb: omap2430: report system-resume PHY setup failures Pengpeng Hou
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=20260922004414.4192-2-hppiscas@163.com \
--to=hppiscas@163.com \
--cc=b-liu@ti.com \
--cc=balbi@ti.com \
--cc=gregkh@linuxfoundation.org \
--cc=kishon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=s.nawrocki@samsung.com \
--cc=tony@atomide.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®