diff options
| author | Mayank Rana <mrana@codeaurora.org> | 2017-11-15 09:57:15 -0800 |
|---|---|---|
| committer | Vijayavardhan Vennapusa <vvreddy@codeaurora.org> | 2018-07-06 16:01:33 +0530 |
| commit | 36b8af952a88c5908b442f273ecdca21defd78ac (patch) | |
| tree | 3f40a693c9daed797b48f3c51bb64793848e4320 | |
| parent | fd95dadf54bf08e910a4cad0bbce8d25e8813429 (diff) | |
dwc3: gadget: Take copy of dwc->gadget_driver before releasing lock
gadget_driver can become null if gadget_stop is called while any other
gadget callbacks are in progress. As gadget callbacks needs to release
spinlock before the callback, store the local copy of gadget_driver to
avoid the race with gadget_stop.
Change-Id: I7f0cbf9af3e3b286f2826647f08215f29f699de1
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f6117ac0e301..9c4345313f1e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2674,41 +2674,55 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, static void dwc3_disconnect_gadget(struct dwc3 *dwc) { + struct usb_gadget_driver *gadget_driver; + if (dwc->gadget_driver && dwc->gadget_driver->disconnect) { + gadget_driver = dwc->gadget_driver; spin_unlock(&dwc->lock); - dwc->gadget_driver->disconnect(&dwc->gadget); + dbg_event(0xFF, "DISCONNECT", 0); + gadget_driver->disconnect(&dwc->gadget); spin_lock(&dwc->lock); } } static void dwc3_suspend_gadget(struct dwc3 *dwc) { + struct usb_gadget_driver *gadget_driver; + if (dwc->gadget_driver && dwc->gadget_driver->suspend) { + gadget_driver = dwc->gadget_driver; spin_unlock(&dwc->lock); dbg_event(0xFF, "SUSPEND", 0); - dwc->gadget_driver->suspend(&dwc->gadget); + gadget_driver->suspend(&dwc->gadget); spin_lock(&dwc->lock); } } static void dwc3_resume_gadget(struct dwc3 *dwc) { + struct usb_gadget_driver *gadget_driver; + if (dwc->gadget_driver && dwc->gadget_driver->resume) { + gadget_driver = dwc->gadget_driver; spin_unlock(&dwc->lock); dbg_event(0xFF, "RESUME", 0); - dwc->gadget_driver->resume(&dwc->gadget); + gadget_driver->resume(&dwc->gadget); spin_lock(&dwc->lock); } } static void dwc3_reset_gadget(struct dwc3 *dwc) { + struct usb_gadget_driver *gadget_driver; + if (!dwc->gadget_driver) return; if (dwc->gadget.speed != USB_SPEED_UNKNOWN) { + gadget_driver = dwc->gadget_driver; spin_unlock(&dwc->lock); - usb_gadget_udc_reset(&dwc->gadget, dwc->gadget_driver); + dbg_event(0xFF, "UDC RESET", 0); + usb_gadget_udc_reset(&dwc->gadget, gadget_driver); spin_lock(&dwc->lock); } } |
