[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251110133612.159057-1-Pavel.Zhigulin@kaspersky.com>
Date: Mon, 10 Nov 2025 16:36:09 +0300
From: Pavel Zhigulin <Pavel.Zhigulin@...persky.com>
To: " Chunfeng Yun " <chunfeng.yun@...iatek.com>, <linux-usb@...r.kernel.org>
CC: Pavel Zhigulin <Pavel.Zhigulin@...persky.com>, Greg Kroah-Hartman
<gregkh@...uxfoundation.org>, Matthias Brugger <matthias.bgg@...il.com>,
AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>,
<linux-arm-kernel@...ts.infradead.org>, <linux-mediatek@...ts.infradead.org>,
<linux-kernel@...r.kernel.org>, <lvc-project@...uxtesting.org>
Subject: [PATCH] usb: gadget: pxa27x_udc: add proper errors hanling
The udc_enable() function previously returned void and ignored
potential errors from clk_enable(). This patch changes it to return
int and propagates clock enable errors back to the caller.
pxa_udc_pullup() now handles these return values correctly.
Also, both pxa27x_change_configuration() and pxa27x_change_interface()
now check and log negative return codes from the gadget driver’s .setup()
callback to aid debugging of failed reconfiguration events.
No functional behavior change expected under normal conditions.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: eb50702539f9 ("USB: pxa27x_udc: factor pullup code to prepare otg transceiver")
Fixes: f4fd094cdfd1 ("usb: gadget: pxa27x_udc: fix clock prepare and enable")
Fixes: d75379a53870 ("usb: pxa27x_udc driver")
Signed-off-by: Pavel Zhigulin <Pavel.Zhigulin@...persky.com>
---
drivers/usb/gadget/udc/pxa27x_udc.c | 42 ++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index 897f53601b5b..58b7f85667bd 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -1462,7 +1462,7 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget)
return 0;
}
-static void udc_enable(struct pxa_udc *udc);
+static int udc_enable(struct pxa_udc *udc);
static void udc_disable(struct pxa_udc *udc);
/**
@@ -1519,17 +1519,21 @@ static int should_disable_udc(struct pxa_udc *udc)
static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
{
struct pxa_udc *udc = to_gadget_udc(_gadget);
+ int ret = 0;
- if (!udc->gpiod && !udc->udc_command)
- return -EOPNOTSUPP;
+ if (!udc->gpiod && !udc->udc_command) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
dplus_pullup(udc, is_active);
if (should_enable_udc(udc))
- udc_enable(udc);
+ ret = udc_enable(udc);
if (should_disable_udc(udc))
udc_disable(udc);
- return 0;
+out:
+ return ret;
}
/**
@@ -1691,12 +1695,18 @@ static void udc_init_data(struct pxa_udc *dev)
* Enables the udc device : enables clocks, udc interrupts, control endpoint
* interrupts, sets usb as UDC client and setups endpoints.
*/
-static void udc_enable(struct pxa_udc *udc)
+static int udc_enable(struct pxa_udc *udc)
{
+ int ret = 0;
+
if (udc->enabled)
- return;
+ goto out;
- clk_enable(udc->clk);
+ ret = clk_enable(udc->clk);
+ if (ret < 0) {
+ dev_err(udc->dev, "failed to enable clock=%d\n", ret);
+ goto out;
+ }
udc_writel(udc, UDCICR0, 0);
udc_writel(udc, UDCICR1, 0);
udc_clear_mask_UDCCR(udc, UDCCR_UDE);
@@ -1726,6 +1736,8 @@ static void udc_enable(struct pxa_udc *udc)
pio_irq_enable(&udc->pxa_ep[0]);
udc->enabled = 1;
+out:
+ return ret;
}
/**
@@ -2078,6 +2090,7 @@ static void handle_ep(struct pxa_ep *ep)
static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
{
struct usb_ctrlrequest req ;
+ int setup_result;
dev_dbg(udc->dev, "config=%d\n", config);
@@ -2092,7 +2105,11 @@ static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
req.wLength = 0;
set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
- udc->driver->setup(&udc->gadget, &req);
+
+ setup_result = udc->driver->setup(&udc->gadget, &req);
+ if (setup_result < 0)
+ dev_dbg(udc->dev, "driver setup failed=%d\n", setup_result);
+
ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
}
@@ -2108,6 +2125,7 @@ static void pxa27x_change_configuration(struct pxa_udc *udc, int config)
static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
{
struct usb_ctrlrequest req;
+ int setup_result;
dev_dbg(udc->dev, "interface=%d, alternate setting=%d\n", iface, alt);
@@ -2121,7 +2139,11 @@ static void pxa27x_change_interface(struct pxa_udc *udc, int iface, int alt)
req.wLength = 0;
set_ep0state(udc, WAIT_ACK_SET_CONF_INTERF);
- udc->driver->setup(&udc->gadget, &req);
+
+ setup_result = udc->driver->setup(&udc->gadget, &req);
+ if (setup_result < 0)
+ dev_dbg(udc->dev, "driver setup failed=%d\n", setup_result);
+
ep_write_UDCCSR(&udc->pxa_ep[0], UDCCSR0_AREN);
}
--
2.43.0
Powered by blists - more mailing lists