summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorDanny Segal <dsegal@codeaurora.org>2014-06-17 15:22:45 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:06:35 -0700
commit88ffd6eb9530fa8c9e51ed4ea2411795a83dc2de (patch)
tree609b48e460af8582f62fc10ffa71d28c63a24fa3 /drivers/usb
parent635cdb12e488c2985676e9468ba05a418a59f1f1 (diff)
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 <dsegal@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/gadget.c29
1 files changed, 29 insertions, 0 deletions
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);