diff options
| author | Azhar Shaikh <azhars@codeaurora.org> | 2015-04-27 15:09:23 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:07:07 -0700 |
| commit | 2c455f7be19ae4deb0884cef204746b386a7e199 (patch) | |
| tree | 7de64aa107bbb18ebb594fc65a1acf05e3c5e819 | |
| parent | 1a2f71ae4f42c46341c419c41914672930d52a32 (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.c | 12 |
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) |
