From 286afdde1640d8ea8916a0f05e811441fbbf4b9d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 25 Nov 2018 00:17:04 +0200 Subject: USB: omap_udc: use devm_request_irq() The current code fails to release the third irq on the error path (observed by reading the code), and we get also multiple WARNs with failing gadget drivers due to duplicate IRQ releases. Fix by using devm_request_irq(). Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) (limited to 'drivers/usb/gadget/udc/omap_udc.c') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 3a16431da321..1c77218c82af 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2867,8 +2867,8 @@ bad_on_1710: udc->clr_halt = UDC_RESET_EP; /* USB general purpose IRQ: ep0, state changes, dma, etc */ - status = request_irq(pdev->resource[1].start, omap_udc_irq, - 0, driver_name, udc); + status = devm_request_irq(&pdev->dev, pdev->resource[1].start, + omap_udc_irq, 0, driver_name, udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[1].start, status); @@ -2876,20 +2876,20 @@ bad_on_1710: } /* USB "non-iso" IRQ (PIO for all but ep0) */ - status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, - 0, "omap_udc pio", udc); + status = devm_request_irq(&pdev->dev, pdev->resource[2].start, + omap_udc_pio_irq, 0, "omap_udc pio", udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[2].start, status); - goto cleanup2; + goto cleanup1; } #ifdef USE_ISO - status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, - 0, "omap_udc iso", udc); + status = devm_request_irq(&pdev->dev, pdev->resource[3].start, + omap_udc_iso_irq, 0, "omap_udc iso", udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[3].start, status); - goto cleanup3; + goto cleanup1; } #endif if (cpu_is_omap16xx() || cpu_is_omap7xx()) { @@ -2902,22 +2902,11 @@ bad_on_1710: create_proc_file(); status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, omap_udc_release); - if (status) - goto cleanup4; - - return 0; + if (!status) + return 0; -cleanup4: remove_proc_file(); -#ifdef USE_ISO -cleanup3: - free_irq(pdev->resource[2].start, udc); -#endif - -cleanup2: - free_irq(pdev->resource[1].start, udc); - cleanup1: kfree(udc); udc = NULL; @@ -2961,12 +2950,6 @@ static int omap_udc_remove(struct platform_device *pdev) remove_proc_file(); -#ifdef USE_ISO - free_irq(pdev->resource[3].start, udc); -#endif - free_irq(pdev->resource[2].start, udc); - free_irq(pdev->resource[1].start, udc); - if (udc->dc_clk) { if (udc->clk_requested) omap_udc_enable_clock(0); -- cgit From 99f700366fcea1aa2fa3c49c99f371670c3c62f8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 25 Nov 2018 00:17:05 +0200 Subject: USB: omap_udc: fix crashes on probe error and module removal We currently crash if usb_add_gadget_udc_release() fails, since the udc->done is not initialized until in the remove function. Furthermore, on module removal the udc data is accessed although the release function is already triggered by usb_del_gadget_udc() early in the function. Fix by rewriting the release and remove functions, basically moving all the cleanup into the release function, and doing the completion only in the module removal case. The patch fixes omap_udc module probe with a failing gadged, and also allows the removal of omap_udc. Tested by running "modprobe omap_udc; modprobe -r omap_udc" in a loop. Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 50 +++++++++++++++------------------------ 1 file changed, 19 insertions(+), 31 deletions(-) (limited to 'drivers/usb/gadget/udc/omap_udc.c') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 1c77218c82af..240ccba44592 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2593,9 +2593,22 @@ omap_ep_setup(char *name, u8 addr, u8 type, static void omap_udc_release(struct device *dev) { - complete(udc->done); + pullup_disable(udc); + if (!IS_ERR_OR_NULL(udc->transceiver)) { + usb_put_phy(udc->transceiver); + udc->transceiver = NULL; + } + omap_writew(0, UDC_SYSCON1); + remove_proc_file(); + if (udc->dc_clk) { + if (udc->clk_requested) + omap_udc_enable_clock(0); + clk_put(udc->hhc_clk); + clk_put(udc->dc_clk); + } + if (udc->done) + complete(udc->done); kfree(udc); - udc = NULL; } static int @@ -2900,12 +2913,8 @@ bad_on_1710: } create_proc_file(); - status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, - omap_udc_release); - if (!status) - return 0; - - remove_proc_file(); + return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, + omap_udc_release); cleanup1: kfree(udc); @@ -2932,36 +2941,15 @@ static int omap_udc_remove(struct platform_device *pdev) { DECLARE_COMPLETION_ONSTACK(done); - if (!udc) - return -ENODEV; - - usb_del_gadget_udc(&udc->gadget); - if (udc->driver) - return -EBUSY; - udc->done = &done; - pullup_disable(udc); - if (!IS_ERR_OR_NULL(udc->transceiver)) { - usb_put_phy(udc->transceiver); - udc->transceiver = NULL; - } - omap_writew(0, UDC_SYSCON1); - - remove_proc_file(); + usb_del_gadget_udc(&udc->gadget); - if (udc->dc_clk) { - if (udc->clk_requested) - omap_udc_enable_clock(0); - clk_put(udc->hhc_clk); - clk_put(udc->dc_clk); - } + wait_for_completion(&done); release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); - wait_for_completion(&done); - return 0; } -- cgit From 6ca6695f576b8453fe68865e84d25946d63b10ad Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 25 Nov 2018 00:17:06 +0200 Subject: USB: omap_udc: fix omap_udc_start() on 15xx machines On OMAP 15xx machines there are no transceivers, and omap_udc_start() always fails as it forgot to adjust the default return value. Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/gadget/udc/omap_udc.c') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 240ccba44592..33250e569af8 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2041,7 +2041,7 @@ static inline int machine_without_vbus_sense(void) static int omap_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { - int status = -ENODEV; + int status; struct omap_ep *ep; unsigned long flags; @@ -2079,6 +2079,7 @@ static int omap_udc_start(struct usb_gadget *g, goto done; } } else { + status = 0; if (can_pullup(udc)) pullup_enable(udc); else -- cgit From 2c2322fbcab8102b8cadc09d66714700a2da42c2 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 25 Nov 2018 00:17:07 +0200 Subject: USB: omap_udc: fix USB gadget functionality on Palm Tungsten E On Palm TE nothing happens when you try to use gadget drivers and plug the USB cable. Fix by adding the board to the vbus sense quirk list. Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget/udc/omap_udc.c') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 33250e569af8..9b23e04c8f02 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void) { return machine_is_omap_innovator() || machine_is_omap_osk() + || machine_is_omap_palmte() || machine_is_sx1() /* No known omap7xx boards with vbus sense */ || cpu_is_omap7xx(); -- cgit From 069caf5950dfa75d0526cd89c439ff9d9d3136d8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 25 Nov 2018 00:17:08 +0200 Subject: USB: omap_udc: fix rejection of out transfers when DMA is used Commit 387f869d2579 ("usb: gadget: u_ether: conditionally align transfer size") started aligning transfer size only if requested, breaking omap_udc DMA mode. Set quirk_ep_out_aligned_size to restore the old behaviour. Fixes: 387f869d2579 ("usb: gadget: u_ether: conditionally align transfer size") Signed-off-by: Aaro Koskinen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc/omap_udc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget/udc/omap_udc.c') diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 9b23e04c8f02..fcf13ef33b31 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2642,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.max_speed = USB_SPEED_FULL; udc->gadget.name = driver_name; + udc->gadget.quirk_ep_out_aligned_size = 1; udc->transceiver = xceiv; /* ep0 is special; put it right after the SETUP buffer */ -- cgit