summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzhar Shaikh <azhars@codeaurora.org>2015-04-27 15:09:23 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:07:07 -0700
commit2c455f7be19ae4deb0884cef204746b386a7e199 (patch)
tree7de64aa107bbb18ebb594fc65a1acf05e3c5e819
parent1a2f71ae4f42c46341c419c41914672930d52a32 (diff)
usb: dwc3: gadget: Fix PM runtime get/put in case of remote wakeup
In case of remote wakeup interrupt, dwc3_gadget_wakeup_work() does a pm_runtime_get_sync() and dwc3_gadget_wakeup_interrupt() does not notify OTG state machine about this state change. Due to which OTG will be still in B_SUSPEND state. Now when bus suspend happens, since OTG state machine is already in B_SUSPEND state, it does not do a pm_runtime_put_autosuspend() and the count is not decremented. To fix, this do an unconditional pm_runtime_get_sync() and pm_runtime_put_noidle() in dwc3_gadget_wakeup_work() to avoid any unclocked register access. In dwc3_gadget_wakeup_interrupt() kick in SM machine in all cases and handle the remote wakeup same as host initiated resume, by clearing the B_SUSPEND bit so that OTG state machine moves to B_PERIPHERAL state. CRs-fixed: 829205 Change-Id: I270df517d5dd58fe28bf0087e0ba951c4e9e15ba Signed-off-by: Azhar Shaikh <azhars@codeaurora.org>
-rw-r--r--drivers/usb/dwc3/gadget.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f9ded176b77d..c615d5917867 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1512,11 +1512,9 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w)
dwc = container_of(w, struct dwc3, wakeup_work);
- if (atomic_read(&dwc->in_lpm)) {
- pm_runtime_get_sync(dwc->dev);
- dbg_event(0xFF, "Gdgwake gsyn",
- atomic_read(&dwc->dev->power.usage_count));
- }
+ pm_runtime_get_sync(dwc->dev);
+ dbg_event(0xFF, "Gdgwake gsyn",
+ atomic_read(&dwc->dev->power.usage_count));
ret = dwc3_gadget_wakeup_int(dwc);
@@ -1524,6 +1522,10 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w)
pr_err("Remote wakeup failed. ret = %d.\n", ret);
else
pr_debug("Remote wakeup succeeded.\n");
+
+ pm_runtime_put_noidle(dwc->dev);
+ dbg_event(0xFF, "Gdgwake put",
+ atomic_read(&dwc->dev->power.usage_count));
}
static int dwc3_gadget_wakeup_int(struct dwc3 *dwc)