|
@@ -1550,6 +1550,21 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|
|
|
|
|
is_on = !!is_on;
|
|
|
|
|
|
+ /*
|
|
|
+ * Per databook, when we want to stop the gadget, if a control transfer
|
|
|
+ * is still in process, complete it and get the core into setup phase.
|
|
|
+ */
|
|
|
+ if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) {
|
|
|
+ reinit_completion(&dwc->ep0_in_setup);
|
|
|
+
|
|
|
+ ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
|
|
|
+ msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
|
|
|
+ if (ret == 0) {
|
|
|
+ dev_err(dwc->dev, "timed out waiting for SETUP phase\n");
|
|
|
+ return -ETIMEDOUT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
spin_lock_irqsave(&dwc->lock, flags);
|
|
|
ret = dwc3_gadget_run_stop(dwc, is_on, false);
|
|
|
spin_unlock_irqrestore(&dwc->lock, flags);
|
|
@@ -2945,6 +2960,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
|
|
goto err4;
|
|
|
}
|
|
|
|
|
|
+ init_completion(&dwc->ep0_in_setup);
|
|
|
+
|
|
|
dwc->gadget.ops = &dwc3_gadget_ops;
|
|
|
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
|
|
dwc->gadget.sg_supported = true;
|