usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()
Subsystems (3)
PATCH v3 1/1 usb: dwc3: gadget: Improve dwc3_gadget_suspend() and dwc3_gadget_resume()
Prevent -ETIMEDOUT error on .suspend().
e.g. If gadget driver is loaded and we are connected to a USB host, all transfers must be stopped before stopping the controller else we will not get a clean stop i.e. dwc3_gadget_run_stop() will take several seconds to complete and will return -ETIMEDOUT.
Handle error cases properly in dwc3_gadget_suspend(). Simplify dwc3_gadget_resume() by using the introduced helper function.
---
Changelog:
v3:
- dropped patch 1. Now no longer check for softconnect during .suspend
- in suspend error path check for softconnect and enable softconnect accordingly
- added Acked-by tag by Thinh Nguyen
v2:
- rebase on greg/usb-next
- split into 2 patches. Add Fixes tag and cc stable.
- do not check for !softconnect in error condition in dwc3_gadget_suspend()
drivers/usb/dwc3/gadget.c | 67 ++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 33 deletions(-)
drivers/usb/dwc3/gadget.c +34 -33
@@ -2699,6 +2699,21 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)return ret; } +static int dwc3_gadget_soft_connect (struct dwc3 *dwc) +{ +/* +* In the Synopsys DWC_usb31 1.90a programming guide section +* 4.1.9, it specifies that for a reconnect after a +* device-initiated disconnect requires a core soft reset +* (DCTL.CSftRst) before enabling the run/stop bit. +*/ +dwc3_core_soft_reset (dwc); + +dwc3_event_buffers_setup (dwc); +__dwc3_gadget_start (dwc); +return dwc3_gadget_run_stop (dwc, true); +} +static int dwc3_gadget_pullup (struct usb_gadget *g,int is_on) {struct dwc3 *dwc =gadget_to_dwc (g);
@@ -2737,21 +2752,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)synchronize_irq (dwc->irq_gadget); -if (!is_on) { +if (!is_on) ret =dwc3_gadget_soft_disconnect (dwc); - }else { -/* -* In the Synopsys DWC_usb31 1.90a programming guide section -* 4.1.9, it specifies that for a reconnect after a -* device-initiated disconnect requires a core soft reset -* (DCTL.CSftRst) before enabling the run/stop bit. -*/ -dwc3_core_soft_reset (dwc); - -dwc3_event_buffers_setup (dwc); -__dwc3_gadget_start (dwc); - ret =dwc3_gadget_run_stop (dwc, true); - } +else + ret =dwc3_gadget_soft_connect (dwc);pm_runtime_put (dwc->dev);
@@ -4655,42 +4659,39 @@ void dwc3_gadget_exit(struct dwc3 *dwc)int dwc3_gadget_suspend (struct dwc3 *dwc) {unsigned long flags; +int ret;if (!dwc->gadget_driver)return 0 ; -dwc3_gadget_run_stop (dwc, false); + ret =dwc3_gadget_soft_disconnect (dwc); +if (ret) + goto err;spin_lock_irqsave (&dwc->lock, flags);dwc3_disconnect_gadget (dwc); -__dwc3_gadget_stop (dwc);spin_unlock_irqrestore (&dwc->lock, flags);return 0 ; + +err: +/* +* Attempt to reset the controller's state. Likely no +* communication can be established until the host +* performs a port reset. +*/ +if (dwc->softconnect) +dwc3_gadget_soft_connect (dwc); + +return ret; }int dwc3_gadget_resume (struct dwc3 *dwc) { -int ret; -if (!dwc->gadget_driver || !dwc->softconnect)return 0 ; - ret =__dwc3_gadget_start (dwc); -if (ret <0 ) - goto err0; - - ret =dwc3_gadget_run_stop (dwc, true); -if (ret <0 ) - goto err1; - -return 0 ; - -err1: -__dwc3_gadget_stop (dwc); - -err0: -return ret; +return dwc3_gadget_soft_connect (dwc); }void dwc3_gadget_process_pending_events (struct dwc3 *dwc)
Signature · 1 line
2.34.1