From: Danny Segal Date: Tue, 17 Jun 2014 12:22:45 +0000 (+0300) Subject: usb: dwc: Fix function wakeup during suspend on SW path X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=88ffd6eb9530fa8c9e51ed4ea2411795a83dc2de;p=sagit-ice-cold%2Fkernel_xiaomi_msm8998.git usb: dwc: Fix function wakeup during suspend on SW path When the SW wants to start USB traffic during USB bus suspend state, it needs to issue remote-wakeup signaling to the USB host before sending the function wakeup notification. This patch changes the function wakeup sending notification function to check whenter the USB bus is suspended and issue remote-wakeup if needed. CRs-Fixed: 678203 Change-Id: I1b09e7763c821a0a0e62095b4dc1c8621a2316b3 Signed-off-by: Danny Segal --- diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5ef6401b3918..211014069acb 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1209,6 +1209,22 @@ static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc) return DWC3_DSTS_USBLNKST(reg); } +static bool dwc3_gadget_is_suspended(struct dwc3 *dwc) +{ + enum dwc3_link_state link_state; + + if (atomic_read(&dwc->in_lpm)) { + return true; + } else { + link_state = dwc3_get_link_state(dwc); + if (link_state == DWC3_LINK_STATE_RX_DET || + link_state == DWC3_LINK_STATE_U3) + return true; + } + + return false; +} + static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, gfp_t gfp_flags) { @@ -1234,6 +1250,13 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, goto out; } + if (dwc3_gadget_is_suspended(dwc)) { + if (dwc->gadget.remote_wakeup) + dwc3_gadget_wakeup(&dwc->gadget); + ret = dwc->gadget.remote_wakeup ? -EAGAIN : -ENOTSUPP; + goto out; + } + ret = __dwc3_gadget_ep_queue(dep, req); out: @@ -1523,6 +1546,12 @@ static int dwc_gadget_func_wakeup(struct usb_gadget *g, int interface_id) if (!g || (g->speed != USB_SPEED_SUPER)) return -ENOTSUPP; + if (dwc3_gadget_is_suspended(dwc)) { + pr_debug("USB bus is suspended. Scheduling wakeup and returning -EAGAIN.\n"); + dwc3_gadget_wakeup(&dwc->gadget); + return -EAGAIN; + } + ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_XMIT_FUNCTION, interface_id);