From d7c3eeffbc55ad462e6447902ffa752c7e9d6aae Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 23 Jan 2019 22:31:36 +0800 Subject: usb: gadget: Remove dead branch code 'num' is a u8 variable, it never greater than 255, So the if branch is dead code and can be removed. Signed-off-by: YueHaibing Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/uvc_configfs.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index bc1e2af566c3..8fe85cb4e87e 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -1570,10 +1570,6 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \ if (ret) \ goto end; \ \ - if (num > 255) { \ - ret = -EINVAL; \ - goto end; \ - } \ u->desc.aname = num; \ ret = len; \ end: \ @@ -1767,10 +1763,6 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \ if (ret) \ goto end; \ \ - if (num > 255) { \ - ret = -EINVAL; \ - goto end; \ - } \ u->desc.aname = num; \ ret = len; \ end: \ -- cgit v1.2.3 From b266d6e496a8c61a2d120960678b1bd97803a0ad Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Mon, 21 Jan 2019 14:32:46 -0700 Subject: dt-bindings: usb: Add support for msm8998 msm8998 USB has a dwc3 controller just like the existing sdm845 support. Signed-off-by: Jeffrey Hugo Reviewed-by: Bjorn Andersson Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/qcom,dwc3.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt index 95afdcf3c337..cb695aa3fba4 100644 --- a/Documentation/devicetree/bindings/usb/qcom,dwc3.txt +++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.txt @@ -4,6 +4,7 @@ Required properties: - compatible: Compatible list, contains "qcom,dwc3" "qcom,msm8996-dwc3" for msm8996 SOC. + "qcom,msm8998-dwc3" for msm8998 SOC. "qcom,sdm845-dwc3" for sdm845 SOC. - reg: Offset and length of register set for QSCRATCH wrapper - power-domains: specifies a phandle to PM domain provider node -- cgit v1.2.3 From 54c9da1bcec44d234a2c6f55c2935d0980a50286 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Mon, 21 Jan 2019 14:33:08 -0700 Subject: usb: dwc3: qcom: Add support for MSM8998 Add a MSM8998 specific DT compatible so that we can properly bind to the device and enable the USB controller. Reviewed-by: Andy Gross Reviewed-by: Bjorn Andersson Signed-off-by: Jeffrey Hugo Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-qcom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index a6d0203e40b6..184df4daa590 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -595,6 +595,7 @@ static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { static const struct of_device_id dwc3_qcom_of_match[] = { { .compatible = "qcom,dwc3" }, { .compatible = "qcom,msm8996-dwc3" }, + { .compatible = "qcom,msm8998-dwc3" }, { .compatible = "qcom,sdm845-dwc3" }, { } }; -- cgit v1.2.3 From 1c1a3ddae9782ba748f5ceb775ed13ef554e8994 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 17 Jan 2019 16:24:15 +0900 Subject: usb: renesas_usbhs: replace udelay() with usleep_range() According to Documentation/timers/timers-howto.txt, a driver should use usleep_range() instead of udelay() on NON-ATOMIC CONTEXT if "SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms)". Since the .hardware_init() and .power_ctrl() will run on NON-ATOMIC CONTEXT, this patch replaces udelay() with usleep_range(). Reviewed-by: Simon Horman Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/rcar3.c | 2 +- drivers/usb/renesas_usbhs/rza.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/rcar3.c b/drivers/usb/renesas_usbhs/rcar3.c index aa3820448286..5e730e9b40ef 100644 --- a/drivers/usb/renesas_usbhs/rcar3.c +++ b/drivers/usb/renesas_usbhs/rcar3.c @@ -59,7 +59,7 @@ static int usbhs_rcar3_power_ctrl(struct platform_device *pdev, if (enable) { usbhs_bset(priv, LPSTS, LPSTS_SUSPM, LPSTS_SUSPM); /* The controller on R-Car Gen3 needs to wait up to 45 usec */ - udelay(45); + usleep_range(45, 90); } else { usbhs_bset(priv, LPSTS, LPSTS_SUSPM, 0); } diff --git a/drivers/usb/renesas_usbhs/rza.c b/drivers/usb/renesas_usbhs/rza.c index 5b287257ec11..8c739bd24acd 100644 --- a/drivers/usb/renesas_usbhs/rza.c +++ b/drivers/usb/renesas_usbhs/rza.c @@ -35,7 +35,7 @@ static int usbhs_rza1_hardware_init(struct platform_device *pdev) /* Enable USB PLL (NOTE: ch0 controls both ch0 and ch1) */ usbhs_bset(priv, SYSCFG, UPLLE, UPLLE); - udelay(1000); + usleep_range(1000, 2000); usbhs_bset(priv, SUSPMODE, SUSPM, SUSPM); return 0; -- cgit v1.2.3 From 169e3b68cadb5775daca009ced4faf01ffd97dcf Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 10 Jan 2019 17:04:28 +0200 Subject: usb: dwc3: gadget: Fix OTG events when gadget driver isn't loaded On v3.10a in dual-role mode, if port is in device mode and gadget driver isn't loaded, the OTG event interrupts don't come through. It seems that if the core is configured to be OTG2.0 only, then we can't leave the DCFG.DEVSPD at Super-speed (default) if we expect OTG to work properly. It must be set to High-speed. Fix this issue by configuring DCFG.DEVSPD to the supported maximum speed at gadget init. Device tree still needs to provide correct supported maximum speed for this to work. This issue wasn't present on v2.40a but is seen on v3.10a. It doesn't cause any side effects on v2.40a. Signed-off-by: Roger Quadros Signed-off-by: Sekhar Nori Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index bed2ff42780b..d478d46847b6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3339,6 +3339,8 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err4; } + dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed); + return 0; err4: -- cgit v1.2.3 From d26c05781e08472861dcad4764d4f1585051638c Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 10 Jan 2019 17:04:29 +0200 Subject: dt-bindings: usb: keystone-usb: Add ti,am654-dwc3 support The AM654 SoC from TI contains a DWC3 controller. Add support for it. Reviewed-by: Rob Herring Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/keystone-usb.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/keystone-usb.txt b/Documentation/devicetree/bindings/usb/keystone-usb.txt index f96e09f784cc..77df82e36138 100644 --- a/Documentation/devicetree/bindings/usb/keystone-usb.txt +++ b/Documentation/devicetree/bindings/usb/keystone-usb.txt @@ -3,7 +3,9 @@ TI Keystone Soc USB Controller DWC3 GLUE Required properties: - - compatible: should be "ti,keystone-dwc3". + - compatible: should be + "ti,keystone-dwc3" for Keystone 2 SoCs + "ti,am654-dwc3" for AM654 SoC - #address-cells, #size-cells : should be '1' if the device has sub-nodes with 'reg' property. - reg : Address and length of the register set for the USB subsystem on @@ -21,7 +23,7 @@ SoCs only: - clock-names: Must be "usb". -The following are mandatory properties for Keystone 2 66AK2G SoCs only: +The following are mandatory properties for 66AK2G and AM654: - power-domains: Should contain a phandle to a PM domain provider node and an args specifier containing the USB device id -- cgit v1.2.3 From eca6b49430c69742e511eb99516e86557d99ae70 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Thu, 10 Jan 2019 17:04:30 +0200 Subject: usb: dwc3: keystone: Add support for ti,am654-dwc3 The AM654 SoC contains a DWC3 controller with TI specific wrapper. Add support for that. Unlike the Keystone 2 case, for AM654 We don't need to process any IRQs for basic USB operation. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 6 +++--- drivers/usb/dwc3/dwc3-keystone.c | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 1a0404fda596..34d9ce20532c 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -86,11 +86,11 @@ config USB_DWC3_HAPS platform, please say 'Y' or 'M' here. config USB_DWC3_KEYSTONE - tristate "Texas Instruments Keystone2 Platforms" - depends on ARCH_KEYSTONE || COMPILE_TEST + tristate "Texas Instruments Keystone2/AM654 Platforms" + depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST default USB_DWC3 help - Support of USB2/3 functionality in TI Keystone2 platforms. + Support of USB2/3 functionality in TI Keystone2 and AM654 platforms. Say 'Y' or 'M' here if you have one such device config USB_DWC3_OF_SIMPLE diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c index 193a9a88222a..cbee5fb9b9fb 100644 --- a/drivers/usb/dwc3/dwc3-keystone.c +++ b/drivers/usb/dwc3/dwc3-keystone.c @@ -106,6 +106,10 @@ static int kdwc3_probe(struct platform_device *pdev) goto err_irq; } + /* IRQ processing not required currently for AM65 */ + if (of_device_is_compatible(node, "ti,am654-dwc3")) + goto skip_irq; + irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "missing irq\n"); @@ -123,6 +127,7 @@ static int kdwc3_probe(struct platform_device *pdev) kdwc3_enable_irqs(kdwc); +skip_irq: error = of_platform_populate(node, NULL, NULL, dev); if (error) { dev_err(&pdev->dev, "failed to create dwc3 core\n"); @@ -152,8 +157,11 @@ static int kdwc3_remove_core(struct device *dev, void *c) static int kdwc3_remove(struct platform_device *pdev) { struct dwc3_keystone *kdwc = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + if (!of_device_is_compatible(node, "ti,am654-dwc3")) + kdwc3_disable_irqs(kdwc); - kdwc3_disable_irqs(kdwc); device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core); pm_runtime_put_sync(kdwc->dev); pm_runtime_disable(kdwc->dev); @@ -165,6 +173,7 @@ static int kdwc3_remove(struct platform_device *pdev) static const struct of_device_id kdwc3_of_match[] = { { .compatible = "ti,keystone-dwc3", }, + { .compatible = "ti,am654-dwc3" }, {}, }; MODULE_DEVICE_TABLE(of, kdwc3_of_match); -- cgit v1.2.3 From 4d8cd61609200dbeb179649e90235d8ab6d66ef5 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Fri, 4 Jan 2019 22:44:43 +0100 Subject: usb: gadget: aspeed: fix typo Fix spelling mistake: "lenght" -> "length" Signed-off-by: Matteo Croce Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/aspeed-vhub/epn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 4a28e3fbeb0b..83340f4fdc6e 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -120,7 +120,7 @@ static void ast_vhub_epn_handle_ack(struct ast_vhub_ep *ep) /* No current DMA ongoing */ req->active = false; - /* Grab lenght out of HW */ + /* Grab length out of HW */ len = VHUB_EP_DMA_TX_SIZE(stat); /* If not using DMA, copy data out if needed */ -- cgit v1.2.3 From 488e3b5fcd1d5c838b0b845a9d99b545ce46d84e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 30 Dec 2018 16:53:08 +0100 Subject: usb: gadget: udc: reduce indentation Delete tab aligning a statement with the right hand side of a preceding assignment rather than the left hand side. Found with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/snps_udc_core.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c index d4da47f4f6f4..3fcded31405a 100644 --- a/drivers/usb/gadget/udc/snps_udc_core.c +++ b/drivers/usb/gadget/udc/snps_udc_core.c @@ -947,15 +947,14 @@ static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp) UDC_DMA_STP_STS_BS_HOST_READY, UDC_DMA_STP_STS_BS); - - /* clear NAK by writing CNAK */ - if (ep->naking) { - tmp = readl(&ep->regs->ctl); - tmp |= AMD_BIT(UDC_EPCTL_CNAK); - writel(tmp, &ep->regs->ctl); - ep->naking = 0; - UDC_QUEUE_CNAK(ep, ep->num); - } + /* clear NAK by writing CNAK */ + if (ep->naking) { + tmp = readl(&ep->regs->ctl); + tmp |= AMD_BIT(UDC_EPCTL_CNAK); + writel(tmp, &ep->regs->ctl); + ep->naking = 0; + UDC_QUEUE_CNAK(ep, ep->num); + } } -- cgit v1.2.3 From 35ed6229c0f0d079f28b22b60b0af3114f9226fb Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 13 Dec 2018 20:22:18 +0000 Subject: usb: gadget: udc: renesas_usb3: Add bindings for r8a774c0 Document RZ/G2E (R8A774C0) SoC bindings. Reviewed-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Yoshihiro Shimoda Signed-off-by: Fabrizio Castro Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/renesas_usb3.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/usb/renesas_usb3.txt b/Documentation/devicetree/bindings/usb/renesas_usb3.txt index d366555166d0..35039e720515 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usb3.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usb3.txt @@ -3,6 +3,7 @@ Renesas Electronics USB3.0 Peripheral driver Required properties: - compatible: Must contain one of the following: - "renesas,r8a774a1-usb3-peri" + - "renesas,r8a774c0-usb3-peri" - "renesas,r8a7795-usb3-peri" - "renesas,r8a7796-usb3-peri" - "renesas,r8a77965-usb3-peri" -- cgit v1.2.3 From 539cf1039165ac59d217d916bc8f88bde8be73bd Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 13 Dec 2018 20:21:03 +0000 Subject: dt-bindings: usb: renesas_usbhs: Add r8a774c0 support Document RZ/G2E (R8A774C0) SoC bindings. Reviewed-by: Rob Herring Reviewed-by: Simon Horman Reviewed-by: Yoshihiro Shimoda Signed-off-by: Fabrizio Castro Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/renesas_usbhs.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt index 90719f501852..d93b6a1504f2 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt @@ -7,6 +7,7 @@ Required properties: - "renesas,usbhs-r8a7744" for r8a7744 (RZ/G1N) compatible device - "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device - "renesas,usbhs-r8a774a1" for r8a774a1 (RZ/G2M) compatible device + - "renesas,usbhs-r8a774c0" for r8a774c0 (RZ/G2E) compatible device - "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device - "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device - "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device -- cgit v1.2.3 From 8b4c62aef6f611dcfcf0ce27731f0e439be17b05 Mon Sep 17 00:00:00 2001 From: Michał Mirosław Date: Sun, 16 Dec 2018 21:23:47 +0100 Subject: usb: gadget: u_serial: process RX in workqueue instead of tasklet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch RX processing from tasklet to (delayed) work queue. This allows receiver more room to process incoming data and prevents flood of "ttyGS0: RX not scheduled?" messages on HS receive on slow CPU. A side effect is 2.4MB/s zmodem transfer speed (up from 1.8MB/s) on my test board. Signed-off-by: Michał Mirosław Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/u_serial.c | 35 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index 29436f75bbe0..65f634ec7fc2 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include #include "u_serial.h" @@ -110,7 +110,7 @@ struct gs_port { int read_allocated; struct list_head read_queue; unsigned n_read; - struct tasklet_struct push; + struct delayed_work push; struct list_head write_pool; int write_started; @@ -352,9 +352,10 @@ __acquires(&port->port_lock) * So QUEUE_SIZE packets plus however many the FIFO holds (usually two) * can be buffered before the TTY layer's buffers (currently 64 KB). */ -static void gs_rx_push(unsigned long _port) +static void gs_rx_push(struct work_struct *work) { - struct gs_port *port = (void *)_port; + struct delayed_work *w = to_delayed_work(work); + struct gs_port *port = container_of(w, struct gs_port, push); struct tty_struct *tty; struct list_head *queue = &port->read_queue; bool disconnect = false; @@ -429,21 +430,13 @@ static void gs_rx_push(unsigned long _port) /* We want our data queue to become empty ASAP, keeping data * in the tty and ldisc (not here). If we couldn't push any - * this time around, there may be trouble unless there's an - * implicit tty_unthrottle() call on its way... + * this time around, RX may be starved, so wait until next jiffy. * - * REVISIT we should probably add a timer to keep the tasklet - * from starving ... but it's not clear that case ever happens. + * We may leave non-empty queue only when there is a tty, and + * either it is throttled or there is no more room in flip buffer. */ - if (!list_empty(queue) && tty) { - if (!tty_throttled(tty)) { - if (do_push) - tasklet_schedule(&port->push); - else - pr_warn("ttyGS%d: RX not scheduled?\n", - port->port_num); - } - } + if (!list_empty(queue) && !tty_throttled(tty)) + schedule_delayed_work(&port->push, 1); /* If we're still connected, refill the USB RX queue. */ if (!disconnect && port->port_usb) @@ -459,7 +452,7 @@ static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) /* Queue all received data until the tty layer is ready for it. */ spin_lock(&port->port_lock); list_add_tail(&req->list, &port->read_queue); - tasklet_schedule(&port->push); + schedule_delayed_work(&port->push, 0); spin_unlock(&port->port_lock); } @@ -854,8 +847,8 @@ static void gs_unthrottle(struct tty_struct *tty) * rts/cts, or other handshaking with the host, but if the * read queue backs up enough we'll be NAKing OUT packets. */ - tasklet_schedule(&port->push); pr_vdebug("ttyGS%d: unthrottle\n", port->port_num); + schedule_delayed_work(&port->push, 0); } spin_unlock_irqrestore(&port->port_lock, flags); } @@ -1159,7 +1152,7 @@ gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) init_waitqueue_head(&port->drain_wait); init_waitqueue_head(&port->close_wait); - tasklet_init(&port->push, gs_rx_push, (unsigned long) port); + INIT_DELAYED_WORK(&port->push, gs_rx_push); INIT_LIST_HEAD(&port->read_pool); INIT_LIST_HEAD(&port->read_queue); @@ -1186,7 +1179,7 @@ static int gs_closed(struct gs_port *port) static void gserial_free_port(struct gs_port *port) { - tasklet_kill(&port->push); + cancel_delayed_work_sync(&port->push); /* wait for old opens to finish */ wait_event(port->close_wait, gs_closed(port)); WARN_ON(port->port_usb != NULL); -- cgit v1.2.3 From e49107d8acfee263b2bd8831d4833c4ead152784 Mon Sep 17 00:00:00 2001 From: Paul Elder Date: Mon, 17 Dec 2018 01:03:40 -0500 Subject: usb: gadget: uvc: add uvcg_warn macro We only have uvcg_dbg, uvcg_info, and uvcg_err, so add uvcg_warn macro to print gadget device name and function name along with format. Signed-off-by: Paul Elder Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/uvc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 099d650082e5..1473d25ff17a 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -56,6 +56,8 @@ extern unsigned int uvc_gadget_trace_param; dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) #define uvcg_info(f, fmt, args...) \ dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) +#define uvcg_warn(f, fmt, args...) \ + dev_warn(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) #define uvcg_err(f, fmt, args...) \ dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) -- cgit v1.2.3 From 546970fdab1da5fead4f0f5c8cbf4b1c68213707 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 13 Dec 2018 20:23:55 +0000 Subject: usb: gadget: udc: renesas_usb3: add support for r8a774c0 RZ/G2E USB 3.0 implementation is like the one found on R-Car E3, therefore add the same quirk. Reviewed-by: Simon Horman Reviewed-by: Yoshihiro Shimoda Signed-off-by: Fabrizio Castro Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/renesas_usb3.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 6e34f9594159..7dc248546fd4 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -2629,6 +2629,10 @@ static const struct of_device_id usb3_of_match[] = { MODULE_DEVICE_TABLE(of, usb3_of_match); static const struct soc_device_attribute renesas_usb3_quirks_match[] = { + { + .soc_id = "r8a774c0", + .data = &renesas_usb3_priv_r8a77990, + }, { .soc_id = "r8a7795", .revision = "ES1.*", .data = &renesas_usb3_priv_r8a7795_es1, -- cgit v1.2.3 From a3af5e3ad3f11a0001317da9e9fb78b371c5f603 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Jan 2019 12:57:09 +0200 Subject: usb: dwc3: gadget: add dwc3_request status tracking This patch starts tracking dwc3_request status. A following patch will build on top of this to prevent a request from being queued twice. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 9 +++++++++ drivers/usb/dwc3/gadget.c | 3 +++ drivers/usb/dwc3/gadget.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index df876418cb78..5c3ee741541f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -863,6 +863,7 @@ struct dwc3_hwparams { * @num_pending_sgs: counter to pending sgs * @num_queued_sgs: counter to the number of sgs which already got queued * @remaining: amount of data remaining + * @status: internal dwc3 request status tracking * @epnum: endpoint number to which this request refers * @trb: pointer to struct dwc3_trb * @trb_dma: DMA address of @trb @@ -883,6 +884,14 @@ struct dwc3_request { unsigned num_pending_sgs; unsigned int num_queued_sgs; unsigned remaining; + + unsigned int status; +#define DWC3_REQUEST_STATUS_QUEUED 0 +#define DWC3_REQUEST_STATUS_STARTED 1 +#define DWC3_REQUEST_STATUS_CANCELLED 2 +#define DWC3_REQUEST_STATUS_COMPLETED 3 +#define DWC3_REQUEST_STATUS_UNKNOWN -1 + u8 epnum; struct dwc3_trb *trb; dma_addr_t trb_dma; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d478d46847b6..9fde48656044 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -209,6 +209,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3 *dwc = dep->dwc; dwc3_gadget_del_and_unmap_request(dep, req, status); + req->status = DWC3_REQUEST_STATUS_COMPLETED; spin_unlock(&dwc->lock); usb_gadget_giveback_request(&dep->endpoint, &req->request); @@ -847,6 +848,7 @@ static struct usb_request *dwc3_gadget_ep_alloc_request(struct usb_ep *ep, req->direction = dep->direction; req->epnum = dep->number; req->dep = dep; + req->status = DWC3_REQUEST_STATUS_UNKNOWN; trace_dwc3_alloc_request(req); @@ -1443,6 +1445,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) trace_dwc3_ep_queue(req); list_add_tail(&req->list, &dep->pending_list); + req->status = DWC3_REQUEST_STATUS_QUEUED; /* * NOTICE: Isochronous endpoints should NEVER be prestarted. We must diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 023a473648eb..6aebe8c0eae1 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -76,6 +76,7 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) struct dwc3_ep *dep = req->dep; req->started = true; + req->status = DWC3_REQUEST_STATUS_STARTED; list_move_tail(&req->list, &dep->started_list); } @@ -91,6 +92,7 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req) struct dwc3_ep *dep = req->dep; req->started = false; + req->status = DWC3_REQUEST_STATUS_CANCELLED; list_move_tail(&req->list, &dep->cancelled_list); } -- cgit v1.2.3 From b2b6d601365a1acb90b87c85197d797447bc9a2c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Jan 2019 12:58:52 +0200 Subject: usb: dwc3: gadget: prevent dwc3_request from being queued twice Queueing the same request twice can introduce hard-to-debug problems. At least one function driver - Android's f_mtp.c - is known to cause this problem. While that function is out-of-tree, this is a problem that's easy enough to avoid. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9fde48656044..064d5161c483 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1437,6 +1437,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) &req->request, req->dep->name)) return -EINVAL; + if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED, + "%s: request %pK already in flight\n", + dep->name, &req->request)) + return -EINVAL; + pm_runtime_get(dwc->dev); req->request.actual = 0; -- cgit v1.2.3 From 7c3d7dc89e57a1d43acea935882dd8713c9e639f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 11 Jan 2019 13:03:27 +0200 Subject: usb: dwc3: gadget: remove req->started flag Now that we have req->status, we don't need this extra flag anymore. It's safe to remove it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 -- drivers/usb/dwc3/gadget.c | 1 - drivers/usb/dwc3/gadget.h | 2 -- 3 files changed, 5 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5c3ee741541f..96794c301a6b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -872,7 +872,6 @@ struct dwc3_hwparams { * or unaligned OUT) * @direction: IN or OUT direction flag * @mapped: true when request has been dma-mapped - * @started: request is started */ struct dwc3_request { struct usb_request request; @@ -901,7 +900,6 @@ struct dwc3_request { unsigned needs_extra_trb:1; unsigned direction:1; unsigned mapped:1; - unsigned started:1; }; /* diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 064d5161c483..189605df6bd2 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -174,7 +174,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep, { struct dwc3 *dwc = dep->dwc; - req->started = false; list_del(&req->list); req->remaining = 0; req->needs_extra_trb = false; diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 6aebe8c0eae1..3ed738e86ea7 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -75,7 +75,6 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) { struct dwc3_ep *dep = req->dep; - req->started = true; req->status = DWC3_REQUEST_STATUS_STARTED; list_move_tail(&req->list, &dep->started_list); } @@ -91,7 +90,6 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req) { struct dwc3_ep *dep = req->dep; - req->started = false; req->status = DWC3_REQUEST_STATUS_CANCELLED; list_move_tail(&req->list, &dep->cancelled_list); } -- cgit v1.2.3 From acbfa6c26f21a18830ee064b588c92334305b6af Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 Jan 2019 12:58:27 +0200 Subject: usb: dwc3: gadget: clear DWC3_EP_TRANSFER_STARTED on cmd complete We must wait until End Transfer completes in order to clear DWC3_EP_TRANSFER_STARTED, otherwise we may confuse the driver. This patch is in preparation to fix a rare race condition that happens upon Disconnect Interrupt. Tested-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 189605df6bd2..f9b44302199a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -384,19 +384,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd, trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status); - if (ret == 0) { - switch (DWC3_DEPCMD_CMD(cmd)) { - case DWC3_DEPCMD_STARTTRANSFER: - dep->flags |= DWC3_EP_TRANSFER_STARTED; - dwc3_gadget_ep_get_transfer_index(dep); - break; - case DWC3_DEPCMD_ENDTRANSFER: - dep->flags &= ~DWC3_EP_TRANSFER_STARTED; - break; - default: - /* nothing */ - break; - } + if (ret == 0 && DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) { + dep->flags |= DWC3_EP_TRANSFER_STARTED; + dwc3_gadget_ep_get_transfer_index(dep); } if (saved_config) { @@ -2578,7 +2568,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, cmd = DEPEVT_PARAMETER_CMD(event->parameters); if (cmd == DWC3_DEPCMD_ENDTRANSFER) { - dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + dep->flags &= ~(DWC3_EP_END_TRANSFER_PENDING | + DWC3_EP_TRANSFER_STARTED); dwc3_gadget_ep_cleanup_cancelled_requests(dep); } break; -- cgit v1.2.3 From 974a1368c33ebb09c94c9ec1b523908cc7ca068f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 Jan 2019 13:00:03 +0200 Subject: usb: dwc3: gadget: don't use resource_index as a flag We have a proper flag for testing that we have a valid transfer in flight, let's use that instead. This patch is in preparation to fix a rare race condition that happens upon Disconnect Interrupt. Tested-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f9b44302199a..eaeea8ff5191 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2626,8 +2626,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) u32 cmd; int ret; - if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || - !dep->resource_index) + if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) + || !(dep->flags & DWC3_EP_TRANSFER_STARTED)) return; /* -- cgit v1.2.3 From 9f45581f5eec6786c6eded2b3c85345d82a910c9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 Jan 2019 13:01:16 +0200 Subject: usb: dwc3: gadget: early giveback if End Transfer already completed There is a rare race condition that may happen during a Disconnect Interrupt if we have a started request that happens to be dequeued *after* completion of End Transfer command. If that happens, that request will be left waiting for completion of an End Transfer command that will never happen. If End Transfer command has already completed before, we are safe to giveback the request straight away. Tested-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index eaeea8ff5191..b82a8885747d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1550,7 +1550,10 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, goto out0; dwc3_gadget_move_cancelled_request(req); - goto out0; + if (dep->flags & DWC3_EP_TRANSFER_STARTED) + goto out0; + else + goto out1; } dev_err(dwc->dev, "request %pK was not queued to %s\n", request, ep->name); @@ -1558,6 +1561,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, goto out0; } +out1: dwc3_gadget_giveback(dep, req, -ECONNRESET); out0: -- cgit v1.2.3 From 3aec99154db3a95572bb92aa470589585e37df06 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 21 Jan 2019 13:08:44 +0200 Subject: usb: dwc3: gadget: remove DWC3_EP_END_TRANSFER_PENDING Now that we modified the code to fix a race condition, it's clear that DWC3_EP_END_TRANSFER_PENDING is unnecessary, considering that DWC3_EP_TRANSFER_STARTED will remain set until End Transfer completes. Tested-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - drivers/usb/dwc3/gadget.c | 15 +++++---------- drivers/usb/dwc3/trace.h | 3 +-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 96794c301a6b..1528d395b156 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -692,7 +692,6 @@ struct dwc3_ep { #define DWC3_EP_WEDGE BIT(2) #define DWC3_EP_TRANSFER_STARTED BIT(3) #define DWC3_EP_PENDING_REQUEST BIT(5) -#define DWC3_EP_END_TRANSFER_PENDING BIT(7) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN BIT(31) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b82a8885747d..8425b6dab875 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -632,7 +632,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; - dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); @@ -738,7 +737,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->stream_capable = false; dep->type = 0; - dep->flags &= DWC3_EP_END_TRANSFER_PENDING; + dep->flags = 0; /* Clear out the ep descriptors for non-ep0 */ if (dep->number > 1) { @@ -2548,7 +2547,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dep = dwc->eps[epnum]; if (!(dep->flags & DWC3_EP_ENABLED)) { - if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) return; /* Handle only EPCMDCMPLT when EP disabled */ @@ -2572,8 +2571,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, cmd = DEPEVT_PARAMETER_CMD(event->parameters); if (cmd == DWC3_DEPCMD_ENDTRANSFER) { - dep->flags &= ~(DWC3_EP_END_TRANSFER_PENDING | - DWC3_EP_TRANSFER_STARTED); + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; dwc3_gadget_ep_cleanup_cancelled_requests(dep); } break; @@ -2630,8 +2628,7 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) u32 cmd; int ret; - if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) - || !(dep->flags & DWC3_EP_TRANSFER_STARTED)) + if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) return; /* @@ -2674,10 +2671,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) WARN_ON_ONCE(ret); dep->resource_index = 0; - if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { - dep->flags |= DWC3_EP_END_TRANSFER_PENDING; + if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) udelay(100); - } } static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index e97a00593dda..3a2f2c319c9a 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -305,7 +305,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, __entry->trb_enqueue = dep->trb_enqueue; __entry->trb_dequeue = dep->trb_dequeue; ), - TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c:%c", + TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c:%c", __get_str(name), __entry->maxpacket, __entry->maxpacket_limit, __entry->max_streams, __entry->maxburst, __entry->trb_enqueue, @@ -315,7 +315,6 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w', __entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b', __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p', - __entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e', __entry->direction ? '<' : '>' ) ); -- cgit v1.2.3 From 7790b3556fccc555ae422f1576e97bf34c8ab8b6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Feb 2019 15:43:38 +0200 Subject: usb: dwc3: trace: pass trace buffer size to decoding functions Instead of assuming that our buffer is big enough, let's pass the buffer size around so printing functions can make sure they won't overflow the buffer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 142 +++++++++++++++++++++++++---------------------- drivers/usb/dwc3/trace.h | 7 ++- 2 files changed, 80 insertions(+), 69 deletions(-) diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 4f75ab3505b7..e925a6b73005 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -193,65 +193,69 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) * dwc3_gadget_event_string - returns event name * @event: the event code */ -static inline const char * -dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event) +static inline const char *dwc3_gadget_event_string(char *str, size_t size, + const struct dwc3_event_devt *event) { enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK; switch (event->type) { case DWC3_DEVICE_EVENT_DISCONNECT: - sprintf(str, "Disconnect: [%s]", + snprintf(str, size, "Disconnect: [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_RESET: - sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state)); + snprintf(str, size, "Reset [%s]", + dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_CONNECT_DONE: - sprintf(str, "Connection Done [%s]", + snprintf(str, size, "Connection Done [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: - sprintf(str, "Link Change [%s]", + snprintf(str, size, "Link Change [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_WAKEUP: - sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state)); + snprintf(str, size, "WakeUp [%s]", + dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_EOPF: - sprintf(str, "End-Of-Frame [%s]", + snprintf(str, size, "End-Of-Frame [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_SOF: - sprintf(str, "Start-Of-Frame [%s]", + snprintf(str, size, "Start-Of-Frame [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_ERRATIC_ERROR: - sprintf(str, "Erratic Error [%s]", + snprintf(str, size, "Erratic Error [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_CMD_CMPL: - sprintf(str, "Command Complete [%s]", + snprintf(str, size, "Command Complete [%s]", dwc3_gadget_link_string(state)); break; case DWC3_DEVICE_EVENT_OVERFLOW: - sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state)); + snprintf(str, size, "Overflow [%s]", + dwc3_gadget_link_string(state)); break; default: - sprintf(str, "UNKNOWN"); + snprintf(str, size, "UNKNOWN"); } return str; } -static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str) +static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str, + size_t size) { switch (t & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: - sprintf(str, "Get Interface Status(Intf = %d, Length = %d)", - i, l); + snprintf(str, size, "Get Interface Status(Intf = %d, Length = %d)", + i, l); break; case USB_RECIP_ENDPOINT: - sprintf(str, "Get Endpoint Status(ep%d%s)", + snprintf(str, size, "Get Endpoint Status(ep%d%s)", i & ~USB_DIR_IN, i & USB_DIR_IN ? "in" : "out"); break; @@ -259,11 +263,11 @@ static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str) } static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v, - __u16 i, char *str) + __u16 i, char *str, size_t size) { switch (t & USB_RECIP_MASK) { case USB_RECIP_DEVICE: - sprintf(str, "%s Device Feature(%s%s)", + snprintf(str, size, "%s Device Feature(%s%s)", b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", ({char *s; switch (v) { @@ -311,13 +315,13 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v, } s; }) : ""); break; case USB_RECIP_INTERFACE: - sprintf(str, "%s Interface Feature(%s)", + snprintf(str, size, "%s Interface Feature(%s)", b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", v == USB_INTRF_FUNC_SUSPEND ? "Function Suspend" : "UNKNOWN"); break; case USB_RECIP_ENDPOINT: - sprintf(str, "%s Endpoint Feature(%s ep%d%s)", + snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)", b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set", v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN", i & ~USB_DIR_IN, @@ -326,15 +330,15 @@ static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v, } } -static inline void dwc3_decode_set_address(__u16 v, char *str) +static inline void dwc3_decode_set_address(__u16 v, char *str, size_t size) { - sprintf(str, "Set Address(Addr = %02x)", v); + snprintf(str, size, "Set Address(Addr = %02x)", v); } static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v, - __u16 i, __u16 l, char *str) + __u16 i, __u16 l, char *str, size_t size) { - sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)", + snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)", b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set", ({ char *s; switch (v >> 8) { @@ -393,87 +397,92 @@ static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v, } -static inline void dwc3_decode_get_configuration(__u16 l, char *str) +static inline void dwc3_decode_get_configuration(__u16 l, char *str, + size_t size) { - sprintf(str, "Get Configuration(Length = %d)", l); + snprintf(str, size, "Get Configuration(Length = %d)", l); } -static inline void dwc3_decode_set_configuration(__u8 v, char *str) +static inline void dwc3_decode_set_configuration(__u8 v, char *str, size_t size) { - sprintf(str, "Set Configuration(Config = %d)", v); + snprintf(str, size, "Set Configuration(Config = %d)", v); } -static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str) +static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str, + size_t size) { - sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l); + snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", i, l); } -static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str) +static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str, size_t size) { - sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v); + snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v); } -static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str) +static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str, + size_t size) { - sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l); + snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", i, l); } -static inline void dwc3_decode_set_sel(__u16 l, char *str) +static inline void dwc3_decode_set_sel(__u16 l, char *str, size_t size) { - sprintf(str, "Set SEL(Length = %d)", l); + snprintf(str, size, "Set SEL(Length = %d)", l); } -static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str) +static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str, size_t size) { - sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v); + snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", v); } /** * dwc3_decode_ctrl - returns a string represetion of ctrl request */ -static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType, - __u8 bRequest, __u16 wValue, __u16 wIndex, __u16 wLength) +static inline const char *dwc3_decode_ctrl(char *str, size_t size, + __u8 bRequestType, __u8 bRequest, __u16 wValue, __u16 wIndex, + __u16 wLength) { switch (bRequest) { case USB_REQ_GET_STATUS: - dwc3_decode_get_status(bRequestType, wIndex, wLength, str); + dwc3_decode_get_status(bRequestType, wIndex, wLength, str, + size); break; case USB_REQ_CLEAR_FEATURE: case USB_REQ_SET_FEATURE: dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue, - wIndex, str); + wIndex, str, size); break; case USB_REQ_SET_ADDRESS: - dwc3_decode_set_address(wValue, str); + dwc3_decode_set_address(wValue, str, size); break; case USB_REQ_GET_DESCRIPTOR: case USB_REQ_SET_DESCRIPTOR: dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue, - wIndex, wLength, str); + wIndex, wLength, str, size); break; case USB_REQ_GET_CONFIGURATION: - dwc3_decode_get_configuration(wLength, str); + dwc3_decode_get_configuration(wLength, str, size); break; case USB_REQ_SET_CONFIGURATION: - dwc3_decode_set_configuration(wValue, str); + dwc3_decode_set_configuration(wValue, str, size); break; case USB_REQ_GET_INTERFACE: - dwc3_decode_get_intf(wIndex, wLength, str); + dwc3_decode_get_intf(wIndex, wLength, str, size); break; case USB_REQ_SET_INTERFACE: - dwc3_decode_set_intf(wValue, wIndex, str); + dwc3_decode_set_intf(wValue, wIndex, str, size); break; case USB_REQ_SYNCH_FRAME: - dwc3_decode_synch_frame(wIndex, wLength, str); + dwc3_decode_synch_frame(wIndex, wLength, str, size); break; case USB_REQ_SET_SEL: - dwc3_decode_set_sel(wLength, str); + dwc3_decode_set_sel(wLength, str, size); break; case USB_REQ_SET_ISOCH_DELAY: - dwc3_decode_set_isoch_delay(wValue, str); + dwc3_decode_set_isoch_delay(wValue, str, size); break; default: - sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x", + snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", bRequestType, bRequest, cpu_to_le16(wValue) & 0xff, cpu_to_le16(wValue) >> 8, @@ -490,16 +499,15 @@ static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType, * dwc3_ep_event_string - returns event name * @event: then event code */ -static inline const char * -dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, - u32 ep0state) +static inline const char *dwc3_ep_event_string(char *str, size_t size, + const struct dwc3_event_depevt *event, u32 ep0state) { u8 epnum = event->endpoint_number; size_t len; int status; int ret; - ret = sprintf(str, "ep%d%s: ", epnum >> 1, + ret = snprintf(str, size, "ep%d%s: ", epnum >> 1, (epnum & 1) ? "in" : "out"); if (ret < 0) return "UNKNOWN"; @@ -509,7 +517,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, switch (event->endpoint_event) { case DWC3_DEPEVT_XFERCOMPLETE: len = strlen(str); - sprintf(str + len, "Transfer Complete (%c%c%c)", + snprintf(str + len, size - len, "Transfer Complete (%c%c%c)", status & DEPEVT_STATUS_SHORT ? 'S' : 's', status & DEPEVT_STATUS_IOC ? 'I' : 'i', status & DEPEVT_STATUS_LST ? 'L' : 'l'); @@ -517,12 +525,13 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, len = strlen(str); if (epnum <= 1) - sprintf(str + len, " [%s]", dwc3_ep0_state_string(ep0state)); + snprintf(str + len, size - len, " [%s]", + dwc3_ep0_state_string(ep0state)); break; case DWC3_DEPEVT_XFERINPROGRESS: len = strlen(str); - sprintf(str + len, "Transfer In Progress [%d] (%c%c%c)", + snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)", event->parameters, status & DEPEVT_STATUS_SHORT ? 'S' : 's', status & DEPEVT_STATUS_IOC ? 'I' : 'i', @@ -531,7 +540,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, case DWC3_DEPEVT_XFERNOTREADY: len = strlen(str); - sprintf(str + len, "Transfer Not Ready [%d]%s", + snprintf(str + len, size - len, "Transfer Not Ready [%d]%s", event->parameters, status & DEPEVT_STATUS_TRANSFER_ACTIVE ? " (Active)" : " (Not Active)"); @@ -557,7 +566,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, switch (status) { case DEPEVT_STREAMEVT_FOUND: - sprintf(str + ret, " Stream %d Found", + snprintf(str + ret, size - ret, " Stream %d Found", event->parameters); break; case DEPEVT_STREAMEVT_NOTFOUND: @@ -571,7 +580,7 @@ dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event, strcat(str, "Endpoint Command Complete"); break; default: - sprintf(str, "UNKNOWN"); + snprintf(str, size, "UNKNOWN"); } return str; @@ -611,14 +620,15 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) } } -static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state) +static inline const char *dwc3_decode_event(char *str, size_t size, u32 event, + u32 ep0state) { const union dwc3_event evt = (union dwc3_event) event; if (evt.type.is_devspec) - return dwc3_gadget_event_string(str, &evt.devt); + return dwc3_gadget_event_string(str, size, &evt.devt); else - return dwc3_ep_event_string(str, &evt.depevt, ep0state); + return dwc3_ep_event_string(str, size, &evt.depevt, ep0state); } static inline const char *dwc3_ep_cmd_status_string(int status) diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index 3a2f2c319c9a..818a63da1a44 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h @@ -59,8 +59,8 @@ DECLARE_EVENT_CLASS(dwc3_log_event, __entry->ep0state = dwc->ep0state; ), TP_printk("event (%08x): %s", __entry->event, - dwc3_decode_event(__get_str(str), __entry->event, - __entry->ep0state)) + dwc3_decode_event(__get_str(str), DWC3_MSG_MAX, + __entry->event, __entry->ep0state)) ); DEFINE_EVENT(dwc3_log_event, dwc3_event, @@ -86,7 +86,8 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, __entry->wIndex = le16_to_cpu(ctrl->wIndex); __entry->wLength = le16_to_cpu(ctrl->wLength); ), - TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType, + TP_printk("%s", dwc3_decode_ctrl(__get_str(str), DWC3_MSG_MAX, + __entry->bRequestType, __entry->bRequest, __entry->wValue, __entry->wIndex, __entry->wLength) ) -- cgit v1.2.3 From 1381a5113caf764f090b912b478663275e7b999e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 5 Feb 2019 09:00:14 +0200 Subject: usb: dwc3: debug: purge usage of strcat Now that buffer size is always passed around, we don't need to rely on strcat anymore. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debug.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index e925a6b73005..6759a7efd8d5 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -545,21 +545,25 @@ static inline const char *dwc3_ep_event_string(char *str, size_t size, status & DEPEVT_STATUS_TRANSFER_ACTIVE ? " (Active)" : " (Not Active)"); + len = strlen(str); + /* Control Endpoints */ if (epnum <= 1) { int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status); switch (phase) { case DEPEVT_STATUS_CONTROL_DATA: - strcat(str, " [Data Phase]"); + snprintf(str + ret, size - ret, + " [Data Phase]"); break; case DEPEVT_STATUS_CONTROL_STATUS: - strcat(str, " [Status Phase]"); + snprintf(str + ret, size - ret, + " [Status Phase]"); } } break; case DWC3_DEPEVT_RXTXFIFOEVT: - strcat(str, "FIFO"); + snprintf(str + ret, size - ret, "FIFO"); break; case DWC3_DEPEVT_STREAMEVT: status = event->status; @@ -571,13 +575,13 @@ static inline const char *dwc3_ep_event_string(char *str, size_t size, break; case DEPEVT_STREAMEVT_NOTFOUND: default: - strcat(str, " Stream Not Found"); + snprintf(str + ret, size - ret, " Stream Not Found"); break; } break; case DWC3_DEPEVT_EPCMDCMPLT: - strcat(str, "Endpoint Command Complete"); + snprintf(str + ret, size - ret, "Endpoint Command Complete"); break; default: snprintf(str, size, "UNKNOWN"); -- cgit v1.2.3 From 1e19a520a9258f3c7286826e7172e56bf6da86dc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 5 Feb 2019 14:33:02 -0500 Subject: USB: gadget: Improve kerneldoc for usb_ep_dequeue() Commit bf594c1070f5 ("USB: gadget: Document that certain ep operations can be called in interrupt context") documented that usb_ep_dequeue() may be called in a non-process context. It follows that the routine must not sleep or wait for events. However, the routine's existing kerneldoc seems to imply that it will wait until the request being cancelled has fully completed. This is not so, and thus the comment needs to be improved. Misunderstanding this point may very well have been responsible for a bug recently uncovered in the f_fs function. The updated comment explicitly says that the routine may return before the request's completion handler is called. Signed-off-by: Alan Stern CC: John Stultz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 87d6b12779f2..7cf34beb50df 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -281,10 +281,10 @@ EXPORT_SYMBOL_GPL(usb_ep_queue); * @ep:the endpoint associated with the request * @req:the request being canceled * - * If the request is still active on the endpoint, it is dequeued and its - * completion routine is called (with status -ECONNRESET); else a negative - * error code is returned. This is guaranteed to happen before the call to - * usb_ep_dequeue() returns. + * If the request is still active on the endpoint, it is dequeued and + * eventually its completion routine is called (with status -ECONNRESET); + * else a negative error code is returned. This routine is asynchronous, + * that is, it may return before the completion routine runs. * * Note that some hardware can't clear out write fifos (to unlink the request * at the head of the queue) except as part of disconnecting from usb. Such -- cgit v1.2.3 From 836bcab50624d728abeab3766f356d54c48ea1b1 Mon Sep 17 00:00:00 2001 From: Guido Kiener Date: Mon, 4 Feb 2019 19:04:20 +0100 Subject: udc: net2280: Fix net2280_disable A reset e.g. calling ep_reset_338x() can happen while endpoints are enabled. The ep_reset_338x() sets ep->desc = NULL to mark endpoint being invalid. A subsequent call of net2280_disable will fail and return -EINVAL to parent function usb_ep_disable(), which will fail, too, and do not set the member ep->enabled = false. See: https://elixir.bootlin.com/linux/v5.0-rc5/source/drivers/usb/gadget/udc/core.c#L139 This fix ignores dp->desc and allows net2280_disable() to succeed. Subsequent calls to usb_ep_enable()/usb_ep_disable() succeeds. Acked-by: Alan Stern Signed-off-by: Guido Kiener Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/net2280.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index e7dae5379e04..7154f00dea40 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -516,8 +516,8 @@ static int net2280_disable(struct usb_ep *_ep) unsigned long flags; ep = container_of(_ep, struct net2280_ep, ep); - if (!_ep || !ep->desc || _ep->name == ep0name) { - pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep); + if (!_ep || _ep->name == ep0name) { + pr_err("%s: Invalid ep=%p\n", __func__, _ep); return -EINVAL; } spin_lock_irqsave(&ep->dev->lock, flags); -- cgit v1.2.3 From 97311c8f8b6e26d5ba6508f0df430ad80fc59327 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Thu, 31 Jan 2019 18:28:07 +0400 Subject: usb: dwc2: Fix EP TxFIFO number setting In case when some EP IN is frequently reused, i.e. enabled/disabled by function driver. It is required to clear TxFIFO number field in DIEPCTL register before setting new number. Otherwise there is probability to have same TxFIFO number for different EP's because of OR operator. Signed-off-by: Minas Harutyunyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 55ef3cc2701b..e15d8a462085 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -4005,6 +4005,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, ret = -ENOMEM; goto error1; } + epctrl &= ~(DXEPCTL_TXFNUM_LIMIT << DXEPCTL_TXFNUM_SHIFT); hsotg->fifo_map |= 1 << fifo_index; epctrl |= DXEPCTL_TXFNUM(fifo_index); hs_ep->fifo_index = fifo_index; -- cgit v1.2.3 From 1ff767bfa54a97f4289cd0dad22d404b53a6d8e3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 22 Jan 2019 14:26:54 +0000 Subject: usb: gadget: fix various indentation issues There are a bunch of various indentation issues, clean these up. Signed-off-by: Colin Ian King Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uac1.c | 8 +++---- drivers/usb/gadget/legacy/inode.c | 40 ++++++++++++++++---------------- drivers/usb/gadget/udc/aspeed-vhub/hub.c | 2 +- drivers/usb/gadget/udc/bdc/bdc_cmd.c | 4 ++-- drivers/usb/gadget/udc/net2280.c | 2 +- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 2746a926a8d9..fe42ffccb020 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -459,10 +459,10 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } else if (intf == uac1->as_in_intf) { uac1->as_in_alt = alt; - if (alt) - ret = u_audio_start_playback(&uac1->g_audio); - else - u_audio_stop_playback(&uac1->g_audio); + if (alt) + ret = u_audio_start_playback(&uac1->g_audio); + else + u_audio_stop_playback(&uac1->g_audio); } else { dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); return -EINVAL; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 37ca0e669bd8..249277d0e53f 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1218,27 +1218,27 @@ ep0_poll (struct file *fd, poll_table *wait) if (dev->state <= STATE_DEV_OPENED) return DEFAULT_POLLMASK; - poll_wait(fd, &dev->wait, wait); - - spin_lock_irq (&dev->lock); - - /* report fd mode change before acting on it */ - if (dev->setup_abort) { - dev->setup_abort = 0; - mask = EPOLLHUP; - goto out; - } - - if (dev->state == STATE_DEV_SETUP) { - if (dev->setup_in || dev->setup_can_stall) - mask = EPOLLOUT; - } else { - if (dev->ev_next != 0) - mask = EPOLLIN; - } + poll_wait(fd, &dev->wait, wait); + + spin_lock_irq(&dev->lock); + + /* report fd mode change before acting on it */ + if (dev->setup_abort) { + dev->setup_abort = 0; + mask = EPOLLHUP; + goto out; + } + + if (dev->state == STATE_DEV_SETUP) { + if (dev->setup_in || dev->setup_can_stall) + mask = EPOLLOUT; + } else { + if (dev->ev_next != 0) + mask = EPOLLIN; + } out: - spin_unlock_irq(&dev->lock); - return mask; + spin_unlock_irq(&dev->lock); + return mask; } static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) diff --git a/drivers/usb/gadget/udc/aspeed-vhub/hub.c b/drivers/usb/gadget/udc/aspeed-vhub/hub.c index 35ba0e55a2e9..7c040f56100e 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c @@ -295,7 +295,7 @@ static int ast_vhub_rep_desc(struct ast_vhub_ep *ep, dsize = AST_VHUB_HUB_DESC_SIZE; memcpy(ep->buf, &ast_vhub_hub_desc, dsize); BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc)); - BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); + BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET); break; default: return std_req_stall; diff --git a/drivers/usb/gadget/udc/bdc/bdc_cmd.c b/drivers/usb/gadget/udc/bdc/bdc_cmd.c index 6305bf2c8b59..44c2a5eef785 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_cmd.c +++ b/drivers/usb/gadget/udc/bdc/bdc_cmd.c @@ -311,8 +311,8 @@ int bdc_ep_clear_stall(struct bdc *bdc, int epnum) /* if the endpoint it not stallled */ if (!(ep->flags & BDC_EP_STALL)) { ret = bdc_ep_set_stall(bdc, epnum); - if (ret) - return ret; + if (ret) + return ret; } } /* Preserve the seq number for ep0 only */ diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 7154f00dea40..f63f82450bf4 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -2279,7 +2279,7 @@ static void usb_reinit_338x(struct net2280 *dev) * - It is safe to set for all connection speeds; all chip revisions. * - R-M-W to leave other bits undisturbed. * - Reference PLX TT-7372 - */ + */ val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit); val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW); writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit); -- cgit v1.2.3 From 10209abe87f5ebfd482a00323f5236d6094d0865 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 21 Jan 2019 14:44:47 +0100 Subject: usb: dwc2: gadget: Add scatter-gather mode This patch adds support for transferring requests, which are non-contiguous in physical memory, i.e. the data buffer is described by a scatter-list. This allows transferring large requests without relying on error-prone contiguous buffer allocations. This way of allocating requests is already implemented in functionfs and TCM USB functions and automatically used if UDC driver advertises scatter-gather suppport. Signed-off-by: Andrzej Pietrasiewicz [mszyprow: fixed null pointer issue, rewrote commit message] Signed-off-by: Marek Szyprowski Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 113 +++++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index e15d8a462085..6812a8a3a98b 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -768,22 +768,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) return desc_size; } -/* - * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain. - * @hs_ep: The endpoint - * @dma_buff: DMA address to use - * @len: Length of the transfer - * - * This function will iterate over descriptor chain and fill its entries - * with corresponding information based on transfer data. - */ -static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, +static void dwc2_gadget_fill_nonisoc_xfer_ddma_one(struct dwc2_hsotg_ep *hs_ep, + struct dwc2_dma_desc **desc, dma_addr_t dma_buff, - unsigned int len) + unsigned int len, + bool true_last) { - struct dwc2_hsotg *hsotg = hs_ep->parent; int dir_in = hs_ep->dir_in; - struct dwc2_dma_desc *desc = hs_ep->desc_list; u32 mps = hs_ep->ep.maxpacket; u32 maxsize = 0; u32 offset = 0; @@ -798,39 +789,77 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, hs_ep->desc_count = 1; for (i = 0; i < hs_ep->desc_count; ++i) { - desc->status = 0; - desc->status |= (DEV_DMA_BUFF_STS_HBUSY + (*desc)->status = 0; + (*desc)->status |= (DEV_DMA_BUFF_STS_HBUSY << DEV_DMA_BUFF_STS_SHIFT); if (len > maxsize) { if (!hs_ep->index && !dir_in) - desc->status |= (DEV_DMA_L | DEV_DMA_IOC); + (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC); - desc->status |= (maxsize << - DEV_DMA_NBYTES_SHIFT & mask); - desc->buf = dma_buff + offset; + (*desc)->status |= + maxsize << DEV_DMA_NBYTES_SHIFT & mask; + (*desc)->buf = dma_buff + offset; len -= maxsize; offset += maxsize; } else { - desc->status |= (DEV_DMA_L | DEV_DMA_IOC); + if (true_last) + (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC); if (dir_in) - desc->status |= (len % mps) ? DEV_DMA_SHORT : - ((hs_ep->send_zlp) ? DEV_DMA_SHORT : 0); - if (len > maxsize) - dev_err(hsotg->dev, "wrong len %d\n", len); + (*desc)->status |= (len % mps) ? DEV_DMA_SHORT : + ((hs_ep->send_zlp && true_last) ? + DEV_DMA_SHORT : 0); - desc->status |= + (*desc)->status |= len << DEV_DMA_NBYTES_SHIFT & mask; - desc->buf = dma_buff + offset; + (*desc)->buf = dma_buff + offset; } - desc->status &= ~DEV_DMA_BUFF_STS_MASK; - desc->status |= (DEV_DMA_BUFF_STS_HREADY + (*desc)->status &= ~DEV_DMA_BUFF_STS_MASK; + (*desc)->status |= (DEV_DMA_BUFF_STS_HREADY << DEV_DMA_BUFF_STS_SHIFT); - desc++; + (*desc)++; + } +} + +/* + * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain. + * @hs_ep: The endpoint + * @ureq: Request to transfer + * @offset: offset in bytes + * @len: Length of the transfer + * + * This function will iterate over descriptor chain and fill its entries + * with corresponding information based on transfer data. + */ +static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, + struct usb_request *ureq, + unsigned int offset, + unsigned int len) +{ + struct dwc2_dma_desc *desc = hs_ep->desc_list; + struct scatterlist *sg; + int i; + u8 desc_count = 0; + + /* non-DMA sg buffer */ + if (!ureq->num_sgs) { + dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc, + ureq->dma + offset, len, true); + return; } + + /* DMA sg buffer */ + for_each_sg(ureq->sg, sg, ureq->num_sgs, i) { + dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &desc, + sg_dma_address(sg) + sg->offset, sg_dma_len(sg), + sg_is_last(sg)); + desc_count += hs_ep->desc_count; + } + + hs_ep->desc_count = desc_count; } /* @@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) hs_ep->next_desc = 0; list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) { - ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, + dma_addr_t dma_addr = hs_req->req.dma; + + if (hs_req->req.num_sgs) { + WARN_ON(hs_req->req.num_sgs > 1); + dma_addr = sg_dma_address(hs_req->req.sg); + } + ret = dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr, hs_req->req.length); if (ret) break; @@ -1100,7 +1135,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, offset = ureq->actual; /* Fill DDMA chain entries */ - dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq->dma + offset, + dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, ureq, offset, length); /* write descriptor chain address to control register */ @@ -1399,7 +1434,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, */ if (using_desc_dma(hs) && hs_ep->isochronous) { if (hs_ep->target_frame != TARGET_FRAME_INITIAL) { - dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, + dma_addr_t dma_addr = hs_req->req.dma; + + if (hs_req->req.num_sgs) { + WARN_ON(hs_req->req.num_sgs > 1); + dma_addr = sg_dma_address(hs_req->req.sg); + } + dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr, hs_req->req.length); } return 0; @@ -1987,13 +2028,12 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n", index); if (using_desc_dma(hsotg)) { - /* Not specific buffer needed for ep0 ZLP */ - dma_addr_t dma = hs_ep->desc_list_dma; - if (!index) dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep); - dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0); + /* Not specific buffer needed for ep0 ZLP */ + dwc2_gadget_fill_nonisoc_xfer_ddma_one(hs_ep, &hs_ep->desc_list, + hs_ep->desc_list_dma, 0, true); } else { dwc2_writel(hsotg, DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(0), @@ -4386,6 +4426,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); + gadget->sg_supported = using_desc_dma(hsotg); dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); return 0; -- cgit v1.2.3 From 44a9d1b9a6bb41b5dba3d6d345421385b0843e4d Mon Sep 17 00:00:00 2001 From: liangshengjun Date: Mon, 24 Dec 2018 02:36:28 +0000 Subject: usb: gadget: function: sync f_uac1 ac header baInterfaceNr f_uac1 audio control header descriptor default set baInterfaceNr[]={1,2}, but usb gadget make a configuration descriptor with more interfaces combination, it can not confirm f_uac1 function linked first. So always keep baInterfaceNr[]={1,2} is correct, and it is necessary to sync baInterfaceNr[] with usb_interface_id() value. Signed-off-by: Liang Shengjun Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_uac1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index fe42ffccb020..00d346965f7a 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -568,6 +568,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) goto fail; as_out_interface_alt_0_desc.bInterfaceNumber = status; as_out_interface_alt_1_desc.bInterfaceNumber = status; + ac_header_desc.baInterfaceNr[0] = status; uac1->as_out_intf = status; uac1->as_out_alt = 0; @@ -576,6 +577,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f) goto fail; as_in_interface_alt_0_desc.bInterfaceNumber = status; as_in_interface_alt_1_desc.bInterfaceNumber = status; + ac_header_desc.baInterfaceNr[1] = status; uac1->as_in_intf = status; uac1->as_in_alt = 0; -- cgit v1.2.3 From dffe2d7fc45017d7afdb6fc226ff34a537cc285c Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 31 Jan 2019 15:53:39 +0100 Subject: usb: gadget: move non-super speed code out of usb_ep_autoconfig_ss() The moved code refers to non-super speed endpoints only. This patch also makes the comment stress the fact, that autoconfigured descriptor might need some adjustments. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/epautoconf.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 71b15c65b90f..1eb4fa2e623f 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -67,9 +67,6 @@ struct usb_ep *usb_ep_autoconfig_ss( ) { struct usb_ep *ep; - u8 type; - - type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if (gadget->ops->match_ep) { ep = gadget->ops->match_ep(gadget, desc, ep_comp); @@ -109,16 +106,6 @@ found_ep: desc->bEndpointAddress |= gadget->out_epnum; } - /* report (variable) full speed bulk maxpacket */ - if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) { - int size = ep->maxpacket_limit; - - /* min() doesn't work on bitfields with gcc-3.5 */ - if (size > 64) - size = 64; - desc->wMaxPacketSize = cpu_to_le16(size); - } - ep->address = desc->bEndpointAddress; ep->desc = NULL; ep->comp_desc = NULL; @@ -152,9 +139,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); * * On success, this returns an claimed usb_ep, and modifies the endpoint * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value - * is initialized as if the endpoint were used at full speed. To prevent - * the endpoint from being returned by a later autoconfig call, claims it - * by assigning ep->claimed to true. + * is initialized as if the endpoint were used at full speed. Because of + * that the users must consider adjusting the autoconfigured descriptor. + * To prevent the endpoint from being returned by a later autoconfig call, + * claims it by assigning ep->claimed to true. * * On failure, this returns a null endpoint descriptor. */ @@ -163,7 +151,26 @@ struct usb_ep *usb_ep_autoconfig( struct usb_endpoint_descriptor *desc ) { - return usb_ep_autoconfig_ss(gadget, desc, NULL); + struct usb_ep *ep; + u8 type; + + ep = usb_ep_autoconfig_ss(gadget, desc, NULL); + if (!ep) + return NULL; + + type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + /* report (variable) full speed bulk maxpacket */ + if (type == USB_ENDPOINT_XFER_BULK) { + int size = ep->maxpacket_limit; + + /* min() doesn't work on bitfields with gcc-3.5 */ + if (size > 64) + size = 64; + desc->wMaxPacketSize = cpu_to_le16(size); + } + + return ep; } EXPORT_SYMBOL_GPL(usb_ep_autoconfig); -- cgit v1.2.3 From bdcc03cef0fd8abc6eaeec6ac47e54ae8f8c625f Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 31 Jan 2019 15:53:40 +0100 Subject: usb: gadget: f_fs: preserve wMaxPacketSize across usb_ep_autoconfig() call usb_ep_autoconfig() treats the passed descriptor as if it were an fs descriptor. In particular, for bulk endpoints, it clips wMaxPacketSize to 64. This patch preserves the original value. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 1e5430438703..66a2c165b4b7 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2843,12 +2843,18 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, struct usb_request *req; struct usb_ep *ep; u8 bEndpointAddress; + u16 wMaxPacketSize; /* * We back up bEndpointAddress because autoconfig overwrites * it with physical endpoint address. */ bEndpointAddress = ds->bEndpointAddress; + /* + * We back up wMaxPacketSize because autoconfig treats + * endpoint descriptors as if they were full speed. + */ + wMaxPacketSize = ds->wMaxPacketSize; pr_vdebug("autoconfig\n"); ep = usb_ep_autoconfig(func->gadget, ds); if (unlikely(!ep)) @@ -2869,6 +2875,11 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, */ if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) ds->bEndpointAddress = bEndpointAddress; + /* + * Restore wMaxPacketSize which was potentially + * overwritten by autoconfig. + */ + ds->wMaxPacketSize = wMaxPacketSize; } ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); -- cgit v1.2.3 From 9c7ebc99b382a158fd2594adbfc204e526b16e08 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Wed, 6 Feb 2019 10:49:26 -0800 Subject: usb: dwc3: haps: Workaround matching VID PID i.MX6QP and i.MX7D platform use a PCIe controller with the same VID and PID as this USB controller. The system may incorrectly match this driver to that PCIe controller. To workaround this, specifically use class type USB with PCI device ID to prevent incorrect driver matching. Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-haps.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-haps.c b/drivers/usb/dwc3/dwc3-haps.c index 02d57d98ef9b..3cecbf169452 100644 --- a/drivers/usb/dwc3/dwc3-haps.c +++ b/drivers/usb/dwc3/dwc3-haps.c @@ -106,6 +106,15 @@ static const struct pci_device_id dwc3_haps_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), + /* + * i.MX6QP and i.MX7D platform use a PCIe controller with the + * same VID and PID as this USB controller. The system may + * incorrectly match this driver to that PCIe controller. To + * workaround this, specifically use class type USB to prevent + * incorrect driver matching. + */ + .class = (PCI_CLASS_SERIAL_USB << 8), + .class_mask = 0xffff00, }, { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, -- cgit v1.2.3 From 54f64d5c983f939901dacc8cfc0983727c5c742e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 5 Feb 2019 10:24:40 -0800 Subject: usb: f_fs: Avoid crash due to out-of-scope stack ptr access Since the 5.0 merge window opened, I've been seeing frequent crashes on suspend and reboot with the trace: [ 36.911170] Unable to handle kernel paging request at virtual address ffffff801153d660 [ 36.912769] Unable to handle kernel paging request at virtual address ffffff800004b564 ... [ 36.950666] Call trace: [ 36.950670] queued_spin_lock_slowpath+0x1cc/0x2c8 [ 36.950681] _raw_spin_lock_irqsave+0x64/0x78 [ 36.950692] complete+0x28/0x70 [ 36.950703] ffs_epfile_io_complete+0x3c/0x50 [ 36.950713] usb_gadget_giveback_request+0x34/0x108 [ 36.950721] dwc3_gadget_giveback+0x50/0x68 [ 36.950723] dwc3_thread_interrupt+0x358/0x1488 [ 36.950731] irq_thread_fn+0x30/0x88 [ 36.950734] irq_thread+0x114/0x1b0 [ 36.950739] kthread+0x104/0x130 [ 36.950747] ret_from_fork+0x10/0x1c I isolated this down to in ffs_epfile_io(): https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/gadget/function/f_fs.c#n1065 Where the completion done is setup on the stack: DECLARE_COMPLETION_ONSTACK(done); Then later we setup a request and queue it, and wait for it: if (unlikely(wait_for_completion_interruptible(&done))) { /* * To avoid race condition with ffs_epfile_io_complete, * dequeue the request first then check * status. usb_ep_dequeue API should guarantee no race * condition with req->complete callback. */ usb_ep_dequeue(ep->ep, req); interrupted = ep->status < 0; } The problem is, that we end up being interrupted, dequeue the request, and exit. But then the irq triggers and we try calling complete() on the context pointer which points to now random stack space, which results in the panic. Alan Stern pointed out there is a bug here, in that the snippet above "assumes that usb_ep_dequeue() waits until the request has been completed." And that: wait_for_completion(&done); Is needed right after the usb_ep_dequeue(). Thus this patch implements that change. With it I no longer see the crashes on suspend or reboot. This issue seems to have been uncovered by behavioral changes in the dwc3 driver in commit fec9095bdef4e ("usb: dwc3: gadget: remove wait_end_transfer"). Cc: Alan Stern Cc: Felipe Balbi Cc: Zeng Tao Cc: Jack Pham Cc: Thinh Nguyen Cc: Chen Yu Cc: Jerry Zhang Cc: Lars-Peter Clausen Cc: Vincent Pelletier Cc: Andrzej Pietrasiewicz Cc: Greg Kroah-Hartman Cc: Linux USB List Suggested-by: Alan Stern Signed-off-by: John Stultz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_fs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 66a2c165b4b7..20413c276c61 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1082,6 +1082,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * condition with req->complete callback. */ usb_ep_dequeue(ep->ep, req); + wait_for_completion(&done); interrupted = ep->status < 0; } -- cgit v1.2.3 From 1b4a3b517157aab6ef86b79b87a38c7fafae0f43 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 13 Dec 2018 14:24:57 +0100 Subject: usb: gadget: Change Andrzej Pietrasiewicz's e-mail address My @samusung.com address is going to cease existing soon, so change it to an address which can actually be used to contact me. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/u_ecm.h | 2 +- drivers/usb/gadget/function/u_eem.h | 2 +- drivers/usb/gadget/function/u_ether_configfs.h | 2 +- drivers/usb/gadget/function/u_fs.h | 2 +- drivers/usb/gadget/function/u_gether.h | 2 +- drivers/usb/gadget/function/u_hid.h | 2 +- drivers/usb/gadget/function/u_midi.h | 2 +- drivers/usb/gadget/function/u_ncm.h | 2 +- drivers/usb/gadget/function/u_printer.h | 2 +- drivers/usb/gadget/function/u_rndis.h | 2 +- drivers/usb/gadget/function/u_uac2.h | 2 +- drivers/usb/gadget/function/u_uvc.h | 2 +- drivers/usb/gadget/function/uvc_configfs.c | 2 +- drivers/usb/gadget/function/uvc_configfs.h | 2 +- drivers/usb/gadget/function/uvc_v4l2.h | 2 +- drivers/usb/gadget/function/uvc_video.h | 2 +- drivers/usb/gadget/u_f.c | 2 +- drivers/usb/gadget/u_f.h | 2 +- drivers/usb/gadget/u_os_desc.h | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/usb/gadget/function/u_ecm.h b/drivers/usb/gadget/function/u_ecm.h index 050aa672ee7f..098ece573a5e 100644 --- a/drivers/usb/gadget/function/u_ecm.h +++ b/drivers/usb/gadget/function/u_ecm.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_ECM_H diff --git a/drivers/usb/gadget/function/u_eem.h b/drivers/usb/gadget/function/u_eem.h index de3828d3e8f0..921386a375cf 100644 --- a/drivers/usb/gadget/function/u_eem.h +++ b/drivers/usb/gadget/function/u_eem.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_EEM_H diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index cd33cee4d78b..d8b92485b727 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef __U_ETHER_CONFIGFS_H diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index c3aba4dfa958..f9b0cf67360d 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_FFS_H diff --git a/drivers/usb/gadget/function/u_gether.h b/drivers/usb/gadget/function/u_gether.h index 5b7e2eb90336..ce4f07626f96 100644 --- a/drivers/usb/gadget/function/u_gether.h +++ b/drivers/usb/gadget/function/u_gether.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_GETHER_H diff --git a/drivers/usb/gadget/function/u_hid.h b/drivers/usb/gadget/function/u_hid.h index 2f5ca4bfa7ff..1594bfa312eb 100644 --- a/drivers/usb/gadget/function/u_hid.h +++ b/drivers/usb/gadget/function/u_hid.h @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_HID_H diff --git a/drivers/usb/gadget/function/u_midi.h b/drivers/usb/gadget/function/u_midi.h index 5599aa5fc977..29bf006c0a13 100644 --- a/drivers/usb/gadget/function/u_midi.h +++ b/drivers/usb/gadget/function/u_midi.h @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_MIDI_H diff --git a/drivers/usb/gadget/function/u_ncm.h b/drivers/usb/gadget/function/u_ncm.h index 67324f983343..d483e45c0f77 100644 --- a/drivers/usb/gadget/function/u_ncm.h +++ b/drivers/usb/gadget/function/u_ncm.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_NCM_H diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h index 6088ff744194..78797764f478 100644 --- a/drivers/usb/gadget/function/u_printer.h +++ b/drivers/usb/gadget/function/u_printer.h @@ -7,7 +7,7 @@ * Copyright (c) 2015 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_PRINTER_H diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h index d65fb4ebac3c..1e148b76f339 100644 --- a/drivers/usb/gadget/function/u_rndis.h +++ b/drivers/usb/gadget/function/u_rndis.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_RNDIS_H diff --git a/drivers/usb/gadget/function/u_uac2.h b/drivers/usb/gadget/function/u_uac2.h index 8362ee572e1e..82048791eb6e 100644 --- a/drivers/usb/gadget/function/u_uac2.h +++ b/drivers/usb/gadget/function/u_uac2.h @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_UAC2_H diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 5242d489e20a..16da49a2fcf2 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -7,7 +7,7 @@ * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef U_UVC_H diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 8fe85cb4e87e..00fb58e50a15 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #include diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h index 8549c0b27b9d..341391dbc81f 100644 --- a/drivers/usb/gadget/function/uvc_configfs.h +++ b/drivers/usb/gadget/function/uvc_configfs.h @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef UVC_CONFIGFS_H #define UVC_CONFIGFS_H diff --git a/drivers/usb/gadget/function/uvc_v4l2.h b/drivers/usb/gadget/function/uvc_v4l2.h index a75e9c397446..452d71059b3f 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.h +++ b/drivers/usb/gadget/function/uvc_v4l2.h @@ -7,7 +7,7 @@ * * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef __UVC_V4L2_H__ diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h index 278dc52c7604..dff12103f696 100644 --- a/drivers/usb/gadget/function/uvc_video.h +++ b/drivers/usb/gadget/function/uvc_video.h @@ -7,7 +7,7 @@ * * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef __UVC_VIDEO_H__ #define __UVC_VIDEO_H__ diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c index dbaa46eee853..6aea1ecb3999 100644 --- a/drivers/usb/gadget/u_f.c +++ b/drivers/usb/gadget/u_f.c @@ -5,7 +5,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #include "u_f.h" diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h index 09f90447fed5..eaa13fd3dc7f 100644 --- a/drivers/usb/gadget/u_f.h +++ b/drivers/usb/gadget/u_f.h @@ -7,7 +7,7 @@ * Copyright (c) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef __U_F_H__ diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h index 8acd21779ac8..5d7d35c8cc31 100644 --- a/drivers/usb/gadget/u_os_desc.h +++ b/drivers/usb/gadget/u_os_desc.h @@ -7,7 +7,7 @@ * Copyright (c) 2014 Samsung Electronics Co., Ltd. * http://www.samsung.com * - * Author: Andrzej Pietrasiewicz + * Author: Andrzej Pietrasiewicz */ #ifndef __U_OS_DESC_H__ -- cgit v1.2.3 From 8c7ffa5ebd4e56ac0a7dcc70fa6da94171d8985d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 1 Feb 2019 09:47:55 +0100 Subject: fotg210-udc: remove a bogus dma_sync_single_for_device call dma_map_single already transfers ownership to the device. Signed-off-by: Christoph Hellwig Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fotg210-udc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index bc6abaea907d..fe9cf415f2f1 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -356,10 +356,6 @@ static void fotg210_start_dma(struct fotg210_ep *ep, return; } - dma_sync_single_for_device(NULL, d, length, - ep->dir_in ? DMA_TO_DEVICE : - DMA_FROM_DEVICE); - fotg210_enable_dma(ep, d, length); /* check if dma is done */ -- cgit v1.2.3 From e26bdb013150b055f9a5a8c1e6026528ee383ba4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 1 Feb 2019 09:47:56 +0100 Subject: fotg210-udc: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Signed-off-by: Christoph Hellwig Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/fotg210-udc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index fe9cf415f2f1..cec49294bac6 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -326,6 +326,7 @@ dma_reset: static void fotg210_start_dma(struct fotg210_ep *ep, struct fotg210_request *req) { + struct device *dev = &ep->fotg210->gadget.dev; dma_addr_t d; u8 *buffer; u32 length; @@ -348,10 +349,10 @@ static void fotg210_start_dma(struct fotg210_ep *ep, length = req->req.length; } - d = dma_map_single(NULL, buffer, length, + d = dma_map_single(dev, buffer, length, ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (dma_mapping_error(NULL, d)) { + if (dma_mapping_error(dev, d)) { pr_err("dma_mapping_error\n"); return; } @@ -366,7 +367,7 @@ static void fotg210_start_dma(struct fotg210_ep *ep, /* update actual transfer length */ req->req.actual += length; - dma_unmap_single(NULL, d, length, DMA_TO_DEVICE); + dma_unmap_single(dev, d, length, DMA_TO_DEVICE); } static void fotg210_ep0_queue(struct fotg210_ep *ep, -- cgit v1.2.3 From c5353b225df9b2d0cf881873eef6f680e43c9aa2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 13 Feb 2019 13:00:54 +0200 Subject: usb: dwc3: gadget: don't enable interrupt when disabling endpoint Since we're disabling the endpoint anyway, we don't worry about getting endpoint command completion interrupt. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8425b6dab875..b63aa1874727 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -687,12 +687,13 @@ out: return 0; } -static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force); +static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, + bool interrupt); static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) { struct dwc3_request *req; - dwc3_stop_active_transfer(dep, true); + dwc3_stop_active_transfer(dep, true, false); /* - giveback all requests to gadget driver */ while (!list_empty(&dep->started_list)) { @@ -1350,7 +1351,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep) * to wait for the next XferNotReady to test the command again */ if (cmd_status == 0) { - dwc3_stop_active_transfer(dep, true); + dwc3_stop_active_transfer(dep, true, true); return 0; } } @@ -1543,7 +1544,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, } if (r == req) { /* wait until it is processed */ - dwc3_stop_active_transfer(dep, true); + dwc3_stop_active_transfer(dep, true, true); if (!r->trb) goto out0; @@ -2500,7 +2501,7 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); if (stop) { - dwc3_stop_active_transfer(dep, true); + dwc3_stop_active_transfer(dep, true, true); dep->flags = DWC3_EP_ENABLED; } @@ -2621,7 +2622,8 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) } } -static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) +static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, + bool interrupt) { struct dwc3 *dwc = dep->dwc; struct dwc3_gadget_ep_cmd_params params; @@ -2664,7 +2666,7 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force) cmd = DWC3_DEPCMD_ENDTRANSFER; cmd |= force ? DWC3_DEPCMD_HIPRI_FORCERM : 0; - cmd |= DWC3_DEPCMD_CMDIOC; + cmd |= interrupt ? DWC3_DEPCMD_CMDIOC : 0; cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); memset(¶ms, 0, sizeof(params)); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); -- cgit v1.2.3 From c7152763f02e05567da27462b2277a554e507c89 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 12 Feb 2019 19:39:27 -0800 Subject: usb: dwc3: Reset num_trbs after skipping Currently req->num_trbs is not reset after the TRBs are skipped and processed from the cancelled list. The gadget driver may reuse the request with an invalid req->num_trbs, and DWC3 will incorrectly skip trbs. To fix this, simply reset req->num_trbs to 0 after skipping through all of them. Fixes: c3acd5901414 ("usb: dwc3: gadget: use num_trbs when skipping TRBs on ->dequeue()") Signed-off-by: Thinh Nguyen Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b63aa1874727..f2d7b744def3 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1503,6 +1503,8 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r trb->ctrl &= ~DWC3_TRB_CTRL_HWO; dwc3_ep_inc_deq(dep); } + + req->num_trbs = 0; } static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) -- cgit v1.2.3 From 0d1ec194721f844a6b20f7f4854332adcebc6fb9 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Tue, 12 Feb 2019 08:57:27 +0000 Subject: usb: misc: usbtest: add super-speed isoc support The calculation of packet number within microframe is different between high-speed and super-speed endpoint, we add support for super-speed in this patch. Cc: Pawel Laszczak Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/misc/usbtest.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index c7f82310e73e..98ada1a3425c 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -347,6 +347,14 @@ static unsigned get_maxpacket(struct usb_device *udev, int pipe) return le16_to_cpup(&ep->desc.wMaxPacketSize); } +static int ss_isoc_get_packet_num(struct usb_device *udev, int pipe) +{ + struct usb_host_endpoint *ep = usb_pipe_endpoint(udev, pipe); + + return USB_SS_MULT(ep->ss_ep_comp.bmAttributes) + * (1 + ep->ss_ep_comp.bMaxBurst); +} + static void simple_fill_buf(struct urb *urb) { unsigned i; @@ -1976,8 +1984,13 @@ static struct urb *iso_alloc_urb( if (bytes < 0 || !desc) return NULL; + maxp = usb_endpoint_maxp(desc); - maxp *= usb_endpoint_maxp_mult(desc); + if (udev->speed >= USB_SPEED_SUPER) + maxp *= ss_isoc_get_packet_num(udev, pipe); + else + maxp *= usb_endpoint_maxp_mult(desc); + packets = DIV_ROUND_UP(bytes, maxp); urb = usb_alloc_urb(packets, GFP_KERNEL); @@ -2065,17 +2078,24 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param, packets *= param->iterations; if (context.is_iso) { + int transaction_num; + + if (udev->speed >= USB_SPEED_SUPER) + transaction_num = ss_isoc_get_packet_num(udev, pipe); + else + transaction_num = usb_endpoint_maxp_mult(desc); + dev_info(&dev->intf->dev, "iso period %d %sframes, wMaxPacket %d, transactions: %d\n", 1 << (desc->bInterval - 1), - (udev->speed == USB_SPEED_HIGH) ? "micro" : "", + (udev->speed >= USB_SPEED_HIGH) ? "micro" : "", usb_endpoint_maxp(desc), - usb_endpoint_maxp_mult(desc)); + transaction_num); dev_info(&dev->intf->dev, "total %lu msec (%lu packets)\n", (packets * (1 << (desc->bInterval - 1))) - / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), + / ((udev->speed >= USB_SPEED_HIGH) ? 8 : 1), packets); } -- cgit v1.2.3 From 5895d311d28f2605e2f71c1a3e043ed38f3ac9d2 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Mon, 11 Feb 2019 10:04:26 -0500 Subject: usb: phy: twl6030-usb: fix possible use-after-free on remove In remove(), use cancel_delayed_work_sync() to cancel the delayed work. Otherwise there's a chance that this work will continue to run until after the device has been removed. This issue was detected with the help of Coccinelle. Cc: Tony Lindgren Cc: Bin Liu Fixes: b6a619a883c3 ("usb: phy: Check initial state for twl6030") Signed-off-by: Sven Van Asbroeck Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl6030-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 183550b63faa..dade34d70419 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -400,7 +400,7 @@ static int twl6030_usb_remove(struct platform_device *pdev) { struct twl6030_usb *twl = platform_get_drvdata(pdev); - cancel_delayed_work(&twl->get_status_work); + cancel_delayed_work_sync(&twl->get_status_work); twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, -- cgit v1.2.3