|
@@ -1640,6 +1640,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
|
|
|
dwc->start_config_issued = false;
|
|
|
|
|
|
dwc->gadget.speed = USB_SPEED_UNKNOWN;
|
|
|
+ dwc->setup_packet_pending = false;
|
|
|
}
|
|
|
|
|
|
static void dwc3_gadget_usb3_phy_power(struct dwc3 *dwc, int on)
|
|
@@ -1676,6 +1677,37 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
|
|
|
|
|
dev_vdbg(dwc->dev, "%s\n", __func__);
|
|
|
|
|
|
+ /*
|
|
|
+ * WORKAROUND: DWC3 revisions <1.88a have an issue which
|
|
|
+ * would cause a missing Disconnect Event if there's a
|
|
|
+ * pending Setup Packet in the FIFO.
|
|
|
+ *
|
|
|
+ * There's no suggested workaround on the official Bug
|
|
|
+ * report, which states that "unless the driver/application
|
|
|
+ * is doing any special handling of a disconnect event,
|
|
|
+ * there is no functional issue".
|
|
|
+ *
|
|
|
+ * Unfortunately, it turns out that we _do_ some special
|
|
|
+ * handling of a disconnect event, namely complete all
|
|
|
+ * pending transfers, notify gadget driver of the
|
|
|
+ * disconnection, and so on.
|
|
|
+ *
|
|
|
+ * Our suggested workaround is to follow the Disconnect
|
|
|
+ * Event steps here, instead, based on a setup_packet_pending
|
|
|
+ * flag. Such flag gets set whenever we have a XferNotReady
|
|
|
+ * event on EP0 and gets cleared on XferComplete for the
|
|
|
+ * same endpoint.
|
|
|
+ *
|
|
|
+ * Refers to:
|
|
|
+ *
|
|
|
+ * STAR#9000466709: RTL: Device : Disconnect event not
|
|
|
+ * generated if setup packet pending in FIFO
|
|
|
+ */
|
|
|
+ if (dwc->revision < DWC3_REVISION_188A) {
|
|
|
+ if (dwc->setup_packet_pending)
|
|
|
+ dwc3_gadget_disconnect_interrupt(dwc);
|
|
|
+ }
|
|
|
+
|
|
|
/* Enable PHYs */
|
|
|
dwc3_gadget_usb2_phy_power(dwc, true);
|
|
|
dwc3_gadget_usb3_phy_power(dwc, true);
|