diff options
| author | Hemant Kumar <hemantk@codeaurora.org> | 2017-01-27 18:31:22 -0800 |
|---|---|---|
| committer | Hemant Kumar <hemantk@codeaurora.org> | 2017-02-01 12:26:33 -0800 |
| commit | cdc3be303e42f1eb809218ae3ac2de1f3d7ed622 (patch) | |
| tree | 80a7afb3c09ee6d2536bd15ac914cbe757a5856b /drivers/usb | |
| parent | 314869eb56763d34f91d5483b0d510267894fadd (diff) | |
usb: dwc3: Add support to LPM L1 remote wakeup for ep0 endpoints
When device controller gets an LPM request from the host during a
control transfer, it is not able to initiate remote wakeup
automatically. As a result it accepts the request, goes to L1 state,
and does not initiate wakeup to exit L1 state. Since host expects
the device to do a remote wakeup from L1 state and the device does
not initiate the wakeup, the host continues to wait and starts
enumeration again because control transfer timeout occurs. Fix this
issue by initiating remote wakeup before queuing the ep0 request
if bus is in L1 suspend state. Also add a counter which gets
incremented upon device sending remote wakeup before queuing ep0
request.
Change-Id: I307ad94d4cb40ce2bd85425f3a1c6316cded52b8
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/dwc3/core.h | 2 | ||||
| -rw-r--r-- | drivers/usb/dwc3/debugfs.c | 5 | ||||
| -rw-r--r-- | drivers/usb/dwc3/ep0.c | 14 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.c | 7 | ||||
| -rw-r--r-- | drivers/usb/dwc3/gadget.h | 8 |
5 files changed, 28 insertions, 8 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c2cdfd1a823b..e4510b057095 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1017,6 +1017,8 @@ struct dwc3 { unsigned irq_event_count[MAX_INTR_STATS]; unsigned irq_dbg_index; + unsigned long l1_remote_wakeup_cnt; + wait_queue_head_t wait_linkstate; }; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 4b4978043d50..068b03a35bd5 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -1180,9 +1180,12 @@ static int dwc3_gadget_int_events_show(struct seq_file *s, void *unused) seq_printf(s, "%d\t", dwc->bh_completion_time[i]); seq_putc(s, '\n'); - seq_printf(s, "t_pwr evt irq : %lld\t", + seq_printf(s, "t_pwr evt irq : %lld\n", ktime_to_us(dwc->t_pwr_evt_irq)); + seq_printf(s, "l1_remote_wakeup_cnt : %lu\n", + dwc->l1_remote_wakeup_cnt); + spin_unlock_irqrestore(&dwc->lock, flags); return 0; } diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2b910e09a80a..9cd87513619c 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -236,6 +236,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, unsigned long flags; int ret; + enum dwc3_link_state link_state; + u32 reg; spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { @@ -252,6 +254,18 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, goto out; } + /* if link stats is in L1 initiate remote wakeup before queuing req */ + if (dwc->speed != DWC3_DSTS_SUPERSPEED) { + link_state = dwc3_get_link_state(dwc); + /* in HS this link state is same as L1 */ + if (link_state == DWC3_LINK_STATE_U2) { + dwc->l1_remote_wakeup_cnt++; + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg |= DWC3_DCTL_ULSTCHNG_RECOVERY; + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + } + } + dwc3_trace(trace_dwc3_ep0, "queueing request %pK to %s length %d state '%s'", request, dep->name, request->length, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e2440b7efc58..88350e61f3bd 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1317,13 +1317,6 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) return 0; } -static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc) -{ - u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - return DWC3_DSTS_USBLNKST(reg); -} - static bool dwc3_gadget_is_suspended(struct dwc3 *dwc) { if (atomic_read(&dwc->in_lpm) || diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 3abd6379164e..a21962c8f513 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -84,6 +84,14 @@ static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) list_move_tail(&req->list, &dep->req_queued); } +static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + return DWC3_DSTS_USBLNKST(reg); +} + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); |
