diff options
author | Linus Torvalds | 2018-04-05 02:55:35 +0200 |
---|---|---|
committer | Linus Torvalds | 2018-04-05 02:55:35 +0200 |
commit | ac9053d2dcb9e8c3fa35ce458dfca8fddc141680 (patch) | |
tree | 3ffa30d58dac22ee0a80e2dd32f41b71da91132b /drivers/usb/dwc3/gadget.c | |
parent | Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (diff) | |
parent | Revert "USB: serial: ftdi_sio: add Id for Physik Instrumente E-870" (diff) | |
download | kernel-qcow2-linux-ac9053d2dcb9e8c3fa35ce458dfca8fddc141680.tar.gz kernel-qcow2-linux-ac9053d2dcb9e8c3fa35ce458dfca8fddc141680.tar.xz kernel-qcow2-linux-ac9053d2dcb9e8c3fa35ce458dfca8fddc141680.zip |
Merge tag 'usb-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH:
"Here is the big set of USB and PHY driver patches for 4.17-rc1.
Lots of USB typeC work happened this round, with code moving from the
staging directory into the "real" part of the kernel, as well as new
infrastructure being added to be able to handle the different types of
"roles" that typeC requires.
There is also the normal huge set of USB gadget controller and driver
updates, along with XHCI changes, and a raft of other tiny fixes all
over the USB tree. And the PHY driver updates are merged in here as
well as they interacted with the USB drivers in some places.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (250 commits)
Revert "USB: serial: ftdi_sio: add Id for Physik Instrumente E-870"
usb: musb: gadget: misplaced out of bounds check
usb: chipidea: imx: Fix ULPI on imx53
usb: chipidea: imx: Cleanup ci_hdrc_imx_platform_flag
usb: chipidea: usbmisc: small clean up
usb: chipidea: usbmisc: evdo can be set e/o reset
usb: chipidea: usbmisc: evdo is only specific to OTG port
USB: serial: ftdi_sio: add Id for Physik Instrumente E-870
usb: dwc3: gadget: never call ->complete() from ->ep_queue()
usb: gadget: udc: core: update usb_ep_queue() documentation
usb: host: Remove the deprecated ATH79 USB host config options
usb: roles: Fix return value check in intel_xhci_usb_probe()
USB: gadget: f_midi: fixing a possible double-free in f_midi
usb: core: Add USB_QUIRK_DELAY_CTRL_MSG to usbcore quirks
usb: core: Copy parameter string correctly and remove superfluous null check
USB: announce bcdDevice as well as idVendor, idProduct.
USB:fix USB3 devices behind USB3 hubs not resuming at hibernate thaw
usb: hub: Reduce warning to notice on power loss
USB: serial: ftdi_sio: add support for Harman FirmwareHubEmulator
USB: serial: cp210x: add ELDAT Easywave RX09 id
...
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 82 |
1 files changed, 58 insertions, 24 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2bda4eb1e9ac..8796a5ee9bb9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -166,18 +166,8 @@ static void dwc3_ep_inc_deq(struct dwc3_ep *dep) dwc3_ep_inc_trb(&dep->trb_dequeue); } -/** - * dwc3_gadget_giveback - call struct usb_request's ->complete callback - * @dep: The endpoint to whom the request belongs to - * @req: The request we're giving back - * @status: completion code for the request - * - * Must be called with controller's lock held and interrupts disabled. This - * function will unmap @req and call its ->complete() callback to notify upper - * layers that it has completed. - */ -void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, - int status) +void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, + struct dwc3_request *req, int status) { struct dwc3 *dwc = dep->dwc; @@ -190,18 +180,35 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, if (req->trb) usb_gadget_unmap_request_by_dev(dwc->sysdev, - &req->request, req->direction); + &req->request, req->direction); req->trb = NULL; - trace_dwc3_gadget_giveback(req); + if (dep->number > 1) + pm_runtime_put(dwc->dev); +} + +/** + * dwc3_gadget_giveback - call struct usb_request's ->complete callback + * @dep: The endpoint to whom the request belongs to + * @req: The request we're giving back + * @status: completion code for the request + * + * Must be called with controller's lock held and interrupts disabled. This + * function will unmap @req and call its ->complete() callback to notify upper + * layers that it has completed. + */ +void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, + int status) +{ + struct dwc3 *dwc = dep->dwc; + + dwc3_gadget_del_and_unmap_request(dep, req, status); + spin_unlock(&dwc->lock); usb_gadget_giveback_request(&dep->endpoint, &req->request); spin_lock(&dwc->lock); - - if (dep->number > 1) - pm_runtime_put(dwc->dev); } /** @@ -1227,7 +1234,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) if (req->trb) memset(req->trb, 0, sizeof(struct dwc3_trb)); dep->queued_requests--; - dwc3_gadget_giveback(dep, req, ret); + dwc3_gadget_del_and_unmap_request(dep, req, ret); return ret; } @@ -1858,7 +1865,11 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) * bursts of data without going through any sort of endpoint throttling. */ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); - reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; + if (dwc3_is_usb31(dwc)) + reg &= ~DWC31_GRXTHRCFG_PKTCNTSEL; + else + reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; + dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); dwc3_gadget_setup_nump(dwc); @@ -1950,6 +1961,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; int epnum; + u32 tmo_eps = 0; spin_lock_irqsave(&dwc->lock, flags); @@ -1960,6 +1972,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { struct dwc3_ep *dep = dwc->eps[epnum]; + int ret; if (!dep) continue; @@ -1967,9 +1980,24 @@ static int dwc3_gadget_stop(struct usb_gadget *g) if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) continue; - wait_event_lock_irq(dep->wait_end_transfer, - !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), - dwc->lock); + ret = wait_event_interruptible_lock_irq_timeout(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock, msecs_to_jiffies(5)); + + if (ret <= 0) { + /* Timed out or interrupted! There's nothing much + * we can do so we just log here and print which + * endpoints timed out at the end. + */ + tmo_eps |= 1 << epnum; + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; + } + } + + if (tmo_eps) { + dev_err(dwc->dev, + "end transfer timed out on endpoints 0x%x [bitmap]\n", + tmo_eps); } out: @@ -2023,7 +2051,10 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g, reg |= DWC3_DCFG_SUPERSPEED; break; case USB_SPEED_SUPER_PLUS: - reg |= DWC3_DCFG_SUPERSPEED_PLUS; + if (dwc3_is_usb31(dwc)) + reg |= DWC3_DCFG_SUPERSPEED_PLUS; + else + reg |= DWC3_DCFG_SUPERSPEED; break; default: dev_err(dwc->dev, "invalid speed (%d)\n", speed); @@ -2101,7 +2132,10 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) mdwidth /= 8; size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num)); - size = DWC3_GTXFIFOSIZ_TXFDEF(size); + if (dwc3_is_usb31(dwc)) + size = DWC31_GTXFIFOSIZ_TXFDEF(size); + else + size = DWC3_GTXFIFOSIZ_TXFDEF(size); /* FIFO Depth is in MDWDITH bytes. Multiply */ size *= mdwidth; |