pxa_udc_probe() looks up the USB2 transceiver with usb_get_phy() on
non-DT platforms. That helper returns a reference which the caller has
to drop, and the driver only drops it in pxa_udc_remove(). Every probe
failure after the lookup (the clock lookup, clk_prepare() and all the
err labels) returns without a usb_put_phy(), so a failed probe leaks the
transceiver.
The DT path already uses devm_usb_get_phy_by_phandle(), so there devres
owns the reference. pxa_udc_remove() nevertheless calls usb_put_phy()
for it as well, dropping the managed reference a second time.
Use devm_usb_get_phy() for the non-DT lookup, like the pxa25x UDC
driver does, so that both paths are managed, and drop the hand written
usb_put_phy() from pxa_udc_remove().
Fixes: 0c0e287d454a ("usb: gadget: pxa27x: add phy notifier event handler")
Cc: <redacted>
Assisted-by: DeepSeek-V4.1-Flash and OpenAI Codex
Signed-off-by: Wentao Liang <redacted>
---
drivers/usb/gadget/udc/pxa27x_udc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index df5cca43afbe..74fc75c9d7c1 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2393,7 +2393,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
if (IS_ERR(udc->transceiver))
return PTR_ERR(udc->transceiver);
} else {
- udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ udc->transceiver = devm_usb_get_phy(udc->dev, USB_PHY_TYPE_USB2);
}
if (udc->gpiod)@@ -2458,10 +2458,8 @@ static void pxa_udc_remove(struct platform_device *_dev)
usb_del_gadget_udc(&udc->gadget);
pxa_cleanup_debugfs(udc);
- if (!IS_ERR_OR_NULL(udc->transceiver)) {
+ if (!IS_ERR_OR_NULL(udc->transceiver))
usb_unregister_notifier(udc->transceiver, &pxa27x_udc_phy);
- usb_put_phy(udc->transceiver);
- }
udc->transceiver = NULL;
the_controller = NULL;--
2.34.1