From 6d258a4c42089229b855fd706622029decf316d6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 15 Mar 2012 16:37:18 +0200 Subject: usb: gadget: udc-core: stop UDC on device-initiated disconnect When we want to do device-initiated disconnect, let's make sure we stop the UDC in order to e.g. allow lower power states to be achieved by turning off unnecessary clocks and/or stoping PHYs. When reconnecting, call ->udc_start() again to make sure UDC is reinitialized. Cc: stable@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 56da49f31d6c..c261887e05ae 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -411,8 +411,12 @@ static ssize_t usb_udc_softconn_store(struct device *dev, struct usb_udc *udc = container_of(dev, struct usb_udc, dev); if (sysfs_streq(buf, "connect")) { + if (udc_is_newstyle(udc)) + usb_gadget_udc_start(udc->gadget, udc->driver); usb_gadget_connect(udc->gadget); } else if (sysfs_streq(buf, "disconnect")) { + if (udc_is_newstyle(udc)) + usb_gadget_udc_stop(udc->gadget, udc->driver); usb_gadget_disconnect(udc->gadget); } else { dev_err(dev, "unsupported command '%s'\n", buf); -- cgit v1.2.3 From 566ccdda07dc5898272b6fbad9c616fc44be305a Mon Sep 17 00:00:00 2001 From: Moiz Sonasath Date: Wed, 14 Mar 2012 00:44:56 -0500 Subject: usb: dwc3: ep0: Handle requests greater than wMaxPacketSize To allow ep0 out transfers of upto bounce buffer size instead of maxpacketsize, use the transfer size as multiple of ep0 maxpacket size. Cc: stable@vger.kernel.org Signed-off-by: Moiz Sonasath Signed-off-by: Partha Basak Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 25910e251c04..a40d3bb0f1c2 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -559,8 +559,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { + unsigned transfer_size = ur->length; + unsigned maxp = ep0->endpoint.maxpacket; + + transfer_size += (maxp - (transfer_size % maxp)); transferred = min_t(u32, ur->length, - ep0->endpoint.maxpacket - length); + transfer_size - length); memcpy(ur->buf, dwc->ep0_bounce, transferred); dwc->ep0_bounced = false; } else { -- cgit v1.2.3 From cd423dd3634a5232a3019eb372b144619a61cd16 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 21 Mar 2012 11:44:00 +0200 Subject: usb: dwc3: ep0: increment "actual" on bounced ep0 case due to a HW limitation we have a bounce buffer for ep0 out transfers which are not aligned with MaxPacketSize. On such case we were not increment r->actual as we should. This patch fixes that mistake. Cc: stable@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index a40d3bb0f1c2..da43131be0e7 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -569,9 +569,10 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, dwc->ep0_bounced = false; } else { transferred = ur->length - length; - ur->actual += transferred; } + ur->actual += transferred; + if ((epnum & 1) && ur->actual < ur->length) { /* for some reason we did not get everything out */ -- cgit v1.2.3 From ecb07797ffc1c2aaa2e58d1ba1b5deea44ea5b9e Mon Sep 17 00:00:00 2001 From: Gerard Cauvy Date: Fri, 16 Mar 2012 16:20:10 +0200 Subject: usb: dwc3: ep0: add a default case for SetFeature command Without this default case returning an error, thus replying with a stall, we would fail USB30CV TD 9.11 Bad Feature test case. Cc: stable@vger.kernel.org Signed-off-by: Gerard Cauvy Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index da43131be0e7..3584a169886f 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -353,6 +353,9 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, dwc->test_mode_nr = wIndex >> 8; dwc->test_mode = true; + break; + default: + return -EINVAL; } break; -- cgit v1.2.3 From afb76df140823c57738598a876cd1d6568cd57c7 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 23 Dec 2011 18:37:18 +0200 Subject: usb: musb: fix oops on omap2430 module unload This change prevents runtime suspend and resume actual execution, if omap2430 controller driver is loaded after musb-hdrc, and therefore the controller isn't initialized properly. The problem is reproducible with 3.1.y and 3.2 kernels. Kernel configuration of musb: % cat .config | egrep 'MUSB|GADGET' CONFIG_USB_MUSB_HDRC=y # CONFIG_USB_MUSB_TUSB6010 is not set CONFIG_USB_MUSB_OMAP2PLUS=m # CONFIG_USB_MUSB_AM35X is not set CONFIG_MUSB_PIO_ONLY=y CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 CONFIG_USB_GADGET_MUSB_HDRC=m CONFIG_USB_GADGET_DUALSPEED=y CONFIG_USB_GADGETFS=m # CONFIG_USB_MIDI_GADGET is not set Fixes the following oops on module unloading: Unable to handle kernel NULL pointer dereference at virtual address 00000220 ----8<---- [] (omap2430_runtime_resume+0x24/0x54 [omap2430]) from [] (pm_generic_runtime_resume+0x3c/0x50) [] (pm_generic_runtime_resume+0x3c/0x50) from [] (_od_runtime_resume+0x28/0x2c) [] (_od_runtime_resume+0x28/0x2c) from [] (__rpm_callback+0x60/0xa0) [] (__rpm_callback+0x60/0xa0) from [] (rpm_resume+0x3fc/0x6e4) [] (rpm_resume+0x3fc/0x6e4) from [] (__pm_runtime_resume+0x5c/0x90) [] (__pm_runtime_resume+0x5c/0x90) from [] (__device_release_driver+0x2c/0xd0) [] (__device_release_driver+0x2c/0xd0) from [] (driver_detach+0xe8/0xf4) [] (driver_detach+0xe8/0xf4) from [] (bus_remove_driver+0xa0/0x104) [] (bus_remove_driver+0xa0/0x104) from [] (driver_unregister+0x60/0x80) [] (driver_unregister+0x60/0x80) from [] (platform_driver_unregister+0x1c/0x20) [] (platform_driver_unregister+0x1c/0x20) from [] (omap2430_exit+0x14/0x1c [omap2430]) [] (omap2430_exit+0x14/0x1c [omap2430]) from [] (sys_delete_module+0x1f4/0x264) [] (sys_delete_module+0x1f4/0x264) from [] (ret_fast_syscall+0x0/0x30) Signed-off-by: Vladimir Zapolskiy Cc: Greg Kroah-Hartman Cc: stable@vger.kernel.org # 3.1 Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 2ae0bb309994..11b571ec22f2 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -491,11 +491,13 @@ static int omap2430_runtime_suspend(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - musb->context.otg_interfsel = musb_readl(musb->mregs, - OTG_INTERFSEL); + if (musb) { + musb->context.otg_interfsel = musb_readl(musb->mregs, + OTG_INTERFSEL); - omap2430_low_level_exit(musb); - usb_phy_set_suspend(musb->xceiv, 1); + omap2430_low_level_exit(musb); + usb_phy_set_suspend(musb->xceiv, 1); + } return 0; } @@ -505,11 +507,13 @@ static int omap2430_runtime_resume(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); - omap2430_low_level_init(musb); - musb_writel(musb->mregs, OTG_INTERFSEL, - musb->context.otg_interfsel); + if (musb) { + omap2430_low_level_init(musb); + musb_writel(musb->mregs, OTG_INTERFSEL, + musb->context.otg_interfsel); - usb_phy_set_suspend(musb->xceiv, 0); + usb_phy_set_suspend(musb->xceiv, 0); + } return 0; } -- cgit v1.2.3 From c04352a590538123f8c93bd87ef1d4bb9e3a64c7 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sat, 4 Feb 2012 19:43:51 +0200 Subject: usb: musb: fix some runtime_pm issues When runtime_pm was originally added, it was done in rather confusing way: omap2430_musb_init() (called from musb_init_controller) would do runtime_pm_get_sync() and musb_init_controller() itself would do runtime_pm_put to balance it out. This is not only confusing but also wrong if non-omap2430 glue layer is used. This confusion resulted in commit 772aed45b604 "usb: musb: fix pm_runtime mismatch", that removed runtime_pm_put() from musb_init_controller as that looked unbalanced, and also happened to fix unrelated isp1704_charger crash. However this broke runtime PM functionality (musb is now always powered, even without gadget active). Avoid these confusing runtime pm dependences by making musb_init_controller() and omap2430_musb_init() do their own runtime get/put pairs; also cover error paths. Remove unneeded runtime_pm_put in omap2430_remove too. isp1704_charger crash that motivated 772aed45b604 will be fixed by following patch. Cc: Felipe Contreras Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 9 ++++++++- drivers/usb/musb/omap2430.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0f8b82918a40..239214626ec5 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1904,7 +1904,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (!musb->isr) { status = -ENODEV; - goto fail3; + goto fail2; } if (!musb->xceiv->io_ops) { @@ -1912,6 +1912,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->xceiv->io_ops = &musb_ulpi_access; } + pm_runtime_get_sync(musb->controller); + #ifndef CONFIG_MUSB_PIO_ONLY if (use_dma && dev->dma_mask) { struct dma_controller *c; @@ -2023,6 +2025,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) goto fail5; #endif + pm_runtime_put(musb->controller); + dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n", ({char *s; switch (musb->board_mode) { @@ -2047,6 +2051,9 @@ fail4: musb_gadget_cleanup(musb); fail3: + pm_runtime_put_sync(musb->controller); + +fail2: if (musb->irq_wake) device_init_wakeup(dev, 0); musb_platform_exit(musb); diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 11b571ec22f2..3dfd122266f4 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -333,6 +333,7 @@ static int omap2430_musb_init(struct musb *musb) setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); + pm_runtime_put_noidle(musb->controller); return 0; err1: @@ -478,7 +479,6 @@ static int __devexit omap2430_remove(struct platform_device *pdev) platform_device_del(glue->musb); platform_device_put(glue->musb); - pm_runtime_put(&pdev->dev); kfree(glue); return 0; -- cgit v1.2.3 From f79a60b8785409f5a77767780315ce6d3ea04a44 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 29 Feb 2012 20:19:46 +0800 Subject: usb: fsl_udc_core: prime status stage once data stage has primed - For Control Read transfer, the ACK handshake on an IN transaction may be corrupted, so the device may not receive the ACK for data stage, the complete irq will not occur at this situation. Therefore, we need to move prime status stage from complete irq routine to the place where the data stage has just primed, or the host will never get ACK for status stage. The above issue has been described at USB2.0 spec chapter 8.5.3.3. - After adding prime status stage just after prime the data stage, there is a potential problem when the status dTD is added before the data stage has primed by hardware. The reason is the device's dTD descriptor has NO direction bit, if data stage (IN) prime hasn't finished, the status stage(OUT) dTD will be added at data stage dTD's Next dTD Pointer, so when the data stage transfer has finished, the status dTD will be primed as IN by hardware, then the host will never receive ACK from the device side for status stage. - Delete below code at fsl_ep_queue: /* Update ep0 state */ if ((ep_index(ep) == 0)) udc->ep0_state = DATA_STATE_XMIT; the udc->ep0_state will be updated again after udc->driver->setup finishes. It is tested at i.mx51 bbg board with g_mass_storage, g_ether, g_serial. Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 5f94e79cd6b9..55abfb6bd612 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -730,7 +730,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) : (1 << (ep_index(ep))); /* check if the pipe is empty */ - if (!(list_empty(&ep->queue))) { + if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) { /* Add td to the end */ struct fsl_req *lastreq; lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); @@ -918,10 +918,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -ENOMEM; } - /* Update ep0 state */ - if ((ep_index(ep) == 0)) - udc->ep0_state = DATA_STATE_XMIT; - /* irq handler advances the queue */ if (req != NULL) list_add_tail(&req->queue, &ep->queue); @@ -1279,7 +1275,8 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) udc->ep0_dir = USB_DIR_OUT; ep = &udc->eps[0]; - udc->ep0_state = WAIT_FOR_OUT_STATUS; + if (udc->ep0_state != DATA_STATE_XMIT) + udc->ep0_state = WAIT_FOR_OUT_STATUS; req->ep = ep; req->req.length = 0; @@ -1384,6 +1381,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, list_add_tail(&req->queue, &ep->queue); udc->ep0_state = DATA_STATE_XMIT; + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); + return; stall: ep0stall(udc); @@ -1492,6 +1492,14 @@ static void setup_received_irq(struct fsl_udc *udc, spin_lock(&udc->lock); udc->ep0_state = (setup->bRequestType & USB_DIR_IN) ? DATA_STATE_XMIT : DATA_STATE_RECV; + /* + * If the data stage is IN, send status prime immediately. + * See 2.0 Spec chapter 8.5.3.3 for detail. + */ + if (udc->ep0_state == DATA_STATE_XMIT) + if (ep0_prime_status(udc, EP_DIR_OUT)) + ep0stall(udc); + } else { /* No data phase, IN status from gadget */ udc->ep0_dir = USB_DIR_IN; @@ -1520,9 +1528,8 @@ static void ep0_req_complete(struct fsl_udc *udc, struct fsl_ep *ep0, switch (udc->ep0_state) { case DATA_STATE_XMIT: - /* receive status phase */ - if (ep0_prime_status(udc, EP_DIR_OUT)) - ep0stall(udc); + /* already primed at setup_received_irq */ + udc->ep0_state = WAIT_FOR_OUT_STATUS; break; case DATA_STATE_RECV: /* send status phase */ -- cgit v1.2.3 From f7a83fe19336125d7eb26488788dc66c03f2c08e Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 6 Mar 2012 14:05:49 +0900 Subject: usb: s3c-hsotg: Fix TX FIFOs allocation According to documentation, TX FIFO_number index starts from 1. For IN endpoint FIFO 0 we use GNPTXFSIZ register for programming the size and memory start address. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 69295ba9d99a..e3fe5fd795f0 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -340,7 +340,7 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) /* currently we allocate TX FIFOs for all possible endpoints, * and assume that they are all the same size. */ - for (ep = 0; ep <= 15; ep++) { + for (ep = 1; ep <= 15; ep++) { val = addr; val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT; addr += size; -- cgit v1.2.3 From 659ad60cb9128345d0a6b9093dda9b0e366b7937 Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 6 Mar 2012 14:07:29 +0900 Subject: usb: s3c-hsotg: Fix maximum patcket size setting for EP0 MPS field of DOEPCTL0 is read only. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index e3fe5fd795f0..03de169ab365 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1696,10 +1696,12 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, reg |= mpsval; writel(reg, regs + S3C_DIEPCTL(ep)); - reg = readl(regs + S3C_DOEPCTL(ep)); - reg &= ~S3C_DxEPCTL_MPS_MASK; - reg |= mpsval; - writel(reg, regs + S3C_DOEPCTL(ep)); + if (ep) { + reg = readl(regs + S3C_DOEPCTL(ep)); + reg &= ~S3C_DxEPCTL_MPS_MASK; + reg |= mpsval; + writel(reg, regs + S3C_DOEPCTL(ep)); + } return; -- cgit v1.2.3 From 70fa030ffb652ace81dd5bcab01255b49723caec Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 6 Mar 2012 14:08:29 +0900 Subject: usb: s3c-hsotg: Avoid TxFIFO corruption in DMA mode Writing to TxFIFO relates only to Slave mode and leads to TxFIFO corruption in DMA mode. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 03de169ab365..8db23660b5e2 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1921,7 +1921,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, ints & S3C_DIEPMSK_TxFIFOEmpty) { dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); - s3c_hsotg_trytx(hsotg, hs_ep); + if (!using_dma(hsotg)) + s3c_hsotg_trytx(hsotg, hs_ep); } } } -- cgit v1.2.3 From db1d8ba36551bf55222c7961d9e9a1195a612fde Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 6 Mar 2012 14:09:19 +0900 Subject: usb: s3c-hsotg: Fix big buffers transfer in DMA mode DMA address register shouldn't be updated manually if transfer size requires multiple packets. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 8db23660b5e2..105b206cd844 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -741,7 +741,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, /* write size / packets */ writel(epsize, hsotg->regs + epsize_reg); - if (using_dma(hsotg)) { + if (using_dma(hsotg) && !continuing) { unsigned int dma_reg; /* write DMA address to control register, buffer already -- cgit v1.2.3 From 64b6c8a7019acc38cc6b37f8e72c1e915593b1bb Mon Sep 17 00:00:00 2001 From: Anton Tikhomirov Date: Tue, 6 Mar 2012 17:05:15 +0900 Subject: usb: dwc3: Free event buffers array Array should be freed together with event buffers, since it was allocated dynamically. Signed-off-by: Anton Tikhomirov Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7bd815a507e8..99b58d84553a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -206,11 +206,11 @@ static void dwc3_free_event_buffers(struct dwc3 *dwc) for (i = 0; i < dwc->num_event_buffers; i++) { evt = dwc->ev_buffs[i]; - if (evt) { + if (evt) dwc3_free_one_event_buffer(dwc, evt); - dwc->ev_buffs[i] = NULL; - } } + + kfree(dwc->ev_buffs); } /** -- cgit v1.2.3 From e2190a97c6d493eef1f180b9dadfd5ffd4706051 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 12 Mar 2012 12:55:41 +0100 Subject: usb: gadget: FunctionFS: clear FFS_FL_BOUND flag on unbind (bugfix) clear FFS_FL_BOUND flag on unbind (bugfix) Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 1cbba70836bc..d187ae73262b 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1382,6 +1382,7 @@ static void functionfs_unbind(struct ffs_data *ffs) ffs->ep0req = NULL; ffs->gadget = NULL; ffs_data_put(ffs); + clear_bit(FFS_FL_BOUND, &ffs->flags); } } -- cgit v1.2.3 From 8545e6031a719675da9f3d21f1c8ce143dac7fe5 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 12 Mar 2012 12:55:42 +0100 Subject: usb: gadget: FunctionFS: make module init & exit __init & __exit make module init & exit __init & __exit Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/g_ffs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 331cd6729d3c..a85eaf40b948 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -161,7 +161,7 @@ static struct usb_composite_driver gfs_driver = { static struct ffs_data *gfs_ffs_data; static unsigned long gfs_registered; -static int gfs_init(void) +static int __init gfs_init(void) { ENTER(); @@ -169,7 +169,7 @@ static int gfs_init(void) } module_init(gfs_init); -static void gfs_exit(void) +static void __exit gfs_exit(void) { ENTER(); -- cgit v1.2.3 From 692933b2ccfce02400dc8360a97acde2846e8541 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Wed, 14 Mar 2012 17:33:35 +0530 Subject: usb: musb: fix bug in musb_cleanup_urb Control transfers with data expected from device to host will use usb_rcvctrlpipe() for urb->pipe so for such urbs 'is_in' will be set causing control urb to fall into the first "if" condition in musb_cleanup_urb(). Fixed by adding logic to check for non control endpoints. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 79cb0af779fa..ef8d744800ac 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2098,7 +2098,7 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh) } /* turn off DMA requests, discard state, stop polling ... */ - if (is_in) { + if (ep->epnum && is_in) { /* giveback saves bulk toggle */ csr = musb_h_flush_rxfifo(ep, 0); -- cgit v1.2.3 From bf070bc14178f1458e7eccd76316ac24f76f1890 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Wed, 21 Mar 2012 16:35:52 +0200 Subject: usb: musb: wake the device before ulpi transfers musb can be suspended at the time some other driver wants to do ulpi transfers using usb_phy_io_* functions, and that can cause data abort, as it happened with isp1704_charger: http://article.gmane.org/gmane.linux.kernel/1226122 Add pm_runtime to ulpi functions to rectify this. This also adds io_dev to usb_phy so that pm_runtime_* functions can be used. Cc: Felipe Contreras Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 239214626ec5..66aaccf04490 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -137,6 +137,9 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) int i = 0; u8 r; u8 power; + int ret; + + pm_runtime_get_sync(phy->io_dev); /* Make sure the transceiver is not in low power mode */ power = musb_readb(addr, MUSB_POWER); @@ -154,15 +157,22 @@ static int musb_ulpi_read(struct usb_phy *phy, u32 offset) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) & MUSB_ULPI_REG_CMPLT)) { i++; - if (i == 10000) - return -ETIMEDOUT; + if (i == 10000) { + ret = -ETIMEDOUT; + goto out; + } } r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r &= ~MUSB_ULPI_REG_CMPLT; musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - return musb_readb(addr, MUSB_ULPI_REG_DATA); + ret = musb_readb(addr, MUSB_ULPI_REG_DATA); + +out: + pm_runtime_put(phy->io_dev); + + return ret; } static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) @@ -171,6 +181,9 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) int i = 0; u8 r = 0; u8 power; + int ret = 0; + + pm_runtime_get_sync(phy->io_dev); /* Make sure the transceiver is not in low power mode */ power = musb_readb(addr, MUSB_POWER); @@ -184,15 +197,20 @@ static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data) while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL) & MUSB_ULPI_REG_CMPLT)) { i++; - if (i == 10000) - return -ETIMEDOUT; + if (i == 10000) { + ret = -ETIMEDOUT; + goto out; + } } r = musb_readb(addr, MUSB_ULPI_REG_CONTROL); r &= ~MUSB_ULPI_REG_CMPLT; musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r); - return 0; +out: + pm_runtime_put(phy->io_dev); + + return ret; } #else #define musb_ulpi_read NULL @@ -1908,6 +1926,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } if (!musb->xceiv->io_ops) { + musb->xceiv->io_dev = musb->controller; musb->xceiv->io_priv = musb->mregs; musb->xceiv->io_ops = &musb_ulpi_access; } -- cgit v1.2.3 From 3006dc8c627d738693e910c159630e4368c9e86c Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 21 Mar 2012 21:30:20 +0530 Subject: usb: musb: omap: fix crash when musb glue (omap) gets initialized pm_runtime_enable is being called after omap2430_musb_init. Hence pm_runtime_get_sync in omap2430_musb_init does not have any effect (does not enable clocks) resulting in a crash during register access. It is fixed here. Cc: stable@vger.kernel.org # v3.0, v3.1, v3.2, v3.3 Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 3dfd122266f4..0fb4ce84d17e 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -453,14 +453,14 @@ static int __devinit omap2430_probe(struct platform_device *pdev) goto err2; } + pm_runtime_enable(&pdev->dev); + ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); goto err2; } - pm_runtime_enable(&pdev->dev); - return 0; err2: -- cgit v1.2.3 From 8ae8090c82eb407267001f75b3d256b3bd4ae691 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 21 Mar 2012 21:34:30 +0530 Subject: usb: gadget: udc-core: fix asymmetric calls in remove_driver During modprobe of gadget driver, pullup is called after udc_start. In order to make the exit path symmetric when removing a gadget driver, call pullup before ->udc_stop. This is needed to avoid issues with PM where udc_stop disables the module completely (put IP in reset state, cut functional and interface clocks, and so on), which prevents us from accessing the IP's address space, thus creating the possibility of an abort exception when we try to access IP's address space after clocks are off. Cc: stable@vger.kernel.org Signed-off-by: Partha Basak Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index c261887e05ae..2fa9865babed 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -264,8 +264,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) if (udc_is_newstyle(udc)) { udc->driver->disconnect(udc->gadget); udc->driver->unbind(udc->gadget); - usb_gadget_udc_stop(udc->gadget, udc->driver); usb_gadget_disconnect(udc->gadget); + usb_gadget_udc_stop(udc->gadget, udc->driver); } else { usb_gadget_stop(udc->gadget, udc->driver); } -- cgit v1.2.3 From ad579699c4f0274bf522a9252ff9b20c72197e48 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Thu, 22 Mar 2012 12:48:06 +0530 Subject: usb: musb: omap: fix the error check for pm_runtime_get_sync pm_runtime_get_sync returns a signed integer. In case of errors it returns a negative value. This patch fixes the error check by making it signed instead of unsigned thus preventing register access if get_sync_fails. Also passes the error cause to the debug message. Cc: stable@vger.kernel.org Cc: Kishon Vijay Abraham I Signed-off-by: Shubhrajyoti D Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 0fb4ce84d17e..c7785e81254c 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -282,7 +282,8 @@ static void musb_otg_notifier_work(struct work_struct *data_notifier_work) static int omap2430_musb_init(struct musb *musb) { - u32 l, status = 0; + u32 l; + int status = 0; struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; @@ -301,7 +302,7 @@ static int omap2430_musb_init(struct musb *musb) status = pm_runtime_get_sync(dev); if (status < 0) { - dev_err(dev, "pm_runtime_get_sync FAILED"); + dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status); goto err1; } -- cgit v1.2.3 From f135617224b4a1113b26b8ee5877e94f38e40d1e Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Fri, 10 Feb 2012 09:54:51 +0100 Subject: usb: gadget: rndis: fix Missing req->context assignment It is crucial to assign each req->context value to struct rndis. The problem happens for multi function gadget (g_multi) when multiple functions are calling common usb_composite_dev control request. It might happen that *_setup method from one usb function will alter some fields of this common request issued by other USB function. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_rndis.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 7b1cf18df5e3..52343654f5df 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -500,6 +500,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) if (buf) { memcpy(req->buf, buf, n); req->complete = rndis_response_complete; + req->context = rndis; rndis_free_response(rndis->config, buf); value = n; } -- cgit v1.2.3 From 6190c79df861d2c78a7448fe6d4260e5fa53b9b9 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 23 Mar 2012 22:23:13 +0530 Subject: usb: gadget: uvc: Remove non-required locking from 'uvc_queue_next_buffer' routine This patch removes the non-required spinlock acquire/release calls on 'queue->irqlock' from 'uvc_queue_next_buffer' routine. This routine is called from 'video->encode' function (which translates to either 'uvc_video_encode_bulk' or 'uvc_video_encode_isoc') in 'uvc_video.c'. As, the 'video->encode' routines are called with 'queue->irqlock' already held, so acquiring a 'queue->irqlock' again in 'uvc_queue_next_buffer' routine causes a spin lock recursion. Signed-off-by: Bhupesh Sharma Acked-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc_queue.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index d776adb2da67..0cdf89d32a15 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -543,11 +543,11 @@ done: return ret; } +/* called with queue->irqlock held.. */ static struct uvc_buffer * uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; - unsigned long flags; if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && buf->buf.length != buf->buf.bytesused) { @@ -556,14 +556,12 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) return buf; } - spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); if (!list_empty(&queue->irqqueue)) nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); else nextbuf = NULL; - spin_unlock_irqrestore(&queue->irqlock, flags); buf->buf.sequence = queue->sequence++; do_gettimeofday(&buf->buf.timestamp); -- cgit v1.2.3 From 92b0abf80c5c5f0e0d71d1309688a330fd74731b Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Wed, 28 Mar 2012 09:30:50 +0200 Subject: usb: gadget: eliminate NULL pointer dereference (bugfix) usb: gadget: eliminate NULL pointer dereference (bugfix) This patch fixes a bug which causes NULL pointer dereference in ffs_ep0_ioctl. The bug happens when the FunctionFS is not bound (either has not been bound yet or has been bound and then unbound) and can be reproduced with running the following commands: $ insmod g_ffs.ko $ mount -t functionfs func /dev/usbgadget $ ./null where null.c is: #include #include int main(void) { int fd = open("/dev/usbgadget/ep0", O_RDWR); ioctl(fd, FUNCTIONFS_CLEAR_HALT); return 0; } Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Cc: stable@vger.kernel.org Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_fs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index d187ae73262b..f52cb1ae45d9 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -712,7 +712,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) if (code == FUNCTIONFS_INTERFACE_REVMAP) { struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; - } else if (gadget->ops->ioctl) { + } else if (gadget && gadget->ops->ioctl) { ret = gadget->ops->ioctl(gadget, code, value); } else { ret = -ENOTTY; -- cgit v1.2.3