usb: dwc3: avoid NULL access of usb_gadget_driver
Subsystems (2)
PATCH v2 1/1 usb: dwc3: avoid NULL access of usb_gadget_driver
we found crash in dwc3_disconnect_gadget(),
it is because dwc->gadget_driver become NULL before async access. 7dc0c55e9f30 ('USB: UDC core: Add udc_async_callbacks gadget op') suggest a common way to avoid such kind of issue.
this change implment the callback in dwc3 and
change related functions which have callback to usb gadget driver.
---
v2: add missing check in dwc3_reset_gadget(), found by Alan Stern.
drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/ep0.c | 10 ++++++---- drivers/usb/dwc3/gadget.c | 21 ++++++++++++++++----- 3 files changed, 23 insertions(+), 9 deletions(-)
drivers/usb/dwc3/core.h +1 -0
@@ -1279,6 +1279,7 @@ struct dwc3 { unsigned dis_metastability_quirk:1; unsigned dis_split_quirk:1; + unsigned async_callbacks:1;u16 imod_interval; };
drivers/usb/dwc3/ep0.c +6 -4
@@ -597,11 +597,13 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)static int dwc3_ep0_delegate_req (struct dwc3 *dwc,struct usb_ctrlrequest *ctrl) { -int ret; +int ret = -EINVAL ; -spin_unlock (&dwc->lock); - ret = dwc->gadget_driver->setup (dwc->gadget, ctrl); -spin_lock (&dwc->lock); +if (dwc->async_callbacks) { +spin_unlock (&dwc->lock); + ret = dwc->gadget_driver->setup (dwc->gadget, ctrl); +spin_lock (&dwc->lock); + }return ret; }
drivers/usb/dwc3/gadget.c +16 -5
@@ -2585,6 +2585,16 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)return ret; } +static void dwc3_gadget_async_callbacks (struct usb_gadget *g,bool enable) +{ +struct dwc3 *dwc =gadget_to_dwc (g); +unsigned long flags; + +spin_lock_irqsave (&dwc->lock, flags); + dwc->async_callbacks = enable; +spin_unlock_irqrestore (&dwc->lock, flags); +} +static const struct usb_gadget_ops dwc3_gadget_ops = { .get_frame = dwc3_gadget_get_frame, .wakeup = dwc3_gadget_wakeup,
@@ -2596,6 +2606,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { .udc_set_ssp_rate = dwc3_gadget_set_ssp_rate, .get_config_params = dwc3_gadget_config_params, .vbus_draw = dwc3_gadget_vbus_draw, + .udc_async_callbacks = dwc3_gadget_async_callbacks, };/* -------------------------------------------------------------------------- */
@@ -3231,7 +3242,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,static void dwc3_disconnect_gadget (struct dwc3 *dwc) { -if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { +if (dwc->async_callbacks && dwc->gadget_driver->disconnect) {spin_unlock (&dwc->lock); dwc->gadget_driver->disconnect (dwc->gadget);spin_lock (&dwc->lock);
@@ -3240,7 +3251,7 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)static void dwc3_suspend_gadget (struct dwc3 *dwc) { -if (dwc->gadget_driver && dwc->gadget_driver->suspend) { +if (dwc->async_callbacks && dwc->gadget_driver->suspend) {spin_unlock (&dwc->lock); dwc->gadget_driver->suspend (dwc->gadget);spin_lock (&dwc->lock);
@@ -3249,7 +3260,7 @@ static void dwc3_suspend_gadget(struct dwc3 *dwc)static void dwc3_resume_gadget (struct dwc3 *dwc) { -if (dwc->gadget_driver && dwc->gadget_driver->resume) { +if (dwc->async_callbacks && dwc->gadget_driver->resume) {spin_unlock (&dwc->lock); dwc->gadget_driver->resume (dwc->gadget);spin_lock (&dwc->lock);
@@ -3261,7 +3272,7 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)if (!dwc->gadget_driver)return ; -if (dwc->gadget->speed !=USB_SPEED_UNKNOWN ) { +if (dwc->async_callbacks && dwc->gadget->speed !=USB_SPEED_UNKNOWN ) {spin_unlock (&dwc->lock);usb_gadget_udc_reset (dwc->gadget, dwc->gadget_driver);spin_lock (&dwc->lock);
@@ -3585,7 +3596,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)* implemented. */ -if (dwc->gadget_driver && dwc->gadget_driver->resume) { +if (dwc->async_callbacks && dwc->gadget_driver->resume) {spin_unlock (&dwc->lock); dwc->gadget_driver->resume (dwc->gadget);spin_lock (&dwc->lock);
Signature · 1 line
2.25.1
Quoted 5 lines · Linyu Yuan
we found crash in
dwc3_disconnect_gadget(),
it is becausedwc->gadget_driverbecome NULL before async access.7dc0c55e9f30('USB: UDC core: Addudc_async_callbacksgadget op') suggest a common way to avoid such kind of issue.
Quoted 7 lines
this change implment the callback in dwc3 and
change related functions which have callback to usb gadget driver.Signed-off-by Linyu Yuan <[email protected]>---
v2: add missing check in
dwc3_reset_gadget(), found by Alan Stern.
This is better.