usb: dwc3: ep0: handle unexpected XferNotReady events
[pandora-kernel.git] / drivers / usb / dwc3 / ep0.c
index 24b447e..36482f4 100644 (file)
@@ -733,6 +733,41 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc,
 static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
                const struct dwc3_event_depevt *event)
 {
+       /*
+        * This part is very tricky: If we has just handled
+        * XferNotReady(Setup) and we're now expecting a
+        * XferComplete but, instead, we receive another
+        * XferNotReady(Setup), we should STALL and restart
+        * the state machine.
+        *
+        * In all other cases, we just continue waiting
+        * for the XferComplete event.
+        *
+        * We are a little bit unsafe here because we're
+        * not trying to ensure that last event was, indeed,
+        * XferNotReady(Setup).
+        *
+        * Still, we don't expect any condition where that
+        * should happen and, even if it does, it would be
+        * another error condition.
+        */
+       if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) {
+               switch (event->status) {
+               case DEPEVT_STATUS_CONTROL_SETUP:
+                       dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n");
+                       dwc3_ep0_stall_and_restart(dwc);
+                       break;
+               case DEPEVT_STATUS_CONTROL_DATA:
+                       /* FALLTHROUGH */
+               case DEPEVT_STATUS_CONTROL_STATUS:
+                       /* FALLTHROUGH */
+               default:
+                       dev_vdbg(dwc->dev, "waiting for XferComplete\n");
+               }
+
+               return;
+       }
+
        switch (event->status) {
        case DEPEVT_STATUS_CONTROL_SETUP:
                dev_vdbg(dwc->dev, "Control Setup\n");