usb: dwc3: gadget: call gadget driver's ->suspend/->resume
authorFelipe Balbi <balbi@ti.com>
Wed, 26 Feb 2014 16:17:07 +0000 (10:17 -0600)
committerFelipe Balbi <balbi@ti.com>
Wed, 5 Mar 2014 20:40:03 +0000 (14:40 -0600)
When going into bus suspend/resume we _must_
call gadget driver's ->suspend/->resume callbacks
accordingly. This patch implements that very feature
which has been missing forever.

Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/dwc3/gadget.c

index f1cb0984046ec0be0345e94082e003c75be13a4a..9f82436b4b1ed11992b880e862425d219f8e70de 100644 (file)
@@ -2028,6 +2028,24 @@ static void dwc3_disconnect_gadget(struct dwc3 *dwc)
        }
 }
 
+static void dwc3_suspend_gadget(struct dwc3 *dwc)
+{
+       if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
+               spin_unlock(&dwc->lock);
+               dwc->gadget_driver->suspend(&dwc->gadget);
+               spin_lock(&dwc->lock);
+       }
+}
+
+static void dwc3_resume_gadget(struct dwc3 *dwc)
+{
+       if (dwc->gadget_driver && dwc->gadget_driver->disconnect) {
+               spin_unlock(&dwc->lock);
+               dwc->gadget_driver->resume(&dwc->gadget);
+               spin_lock(&dwc->lock);
+       }
+}
+
 static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
 {
        struct dwc3_ep *dep;
@@ -2414,6 +2432,23 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
 
        dwc->link_state = next;
 
+       switch (next) {
+       case DWC3_LINK_STATE_U1:
+               if (dwc->speed == USB_SPEED_SUPER)
+                       dwc3_suspend_gadget(dwc);
+               break;
+       case DWC3_LINK_STATE_U2:
+       case DWC3_LINK_STATE_U3:
+               dwc3_suspend_gadget(dwc);
+               break;
+       case DWC3_LINK_STATE_RESUME:
+               dwc3_resume_gadget(dwc);
+               break;
+       default:
+               /* do nothing */
+               break;
+       }
+
        dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
 }