summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-08-27 22:07:53 +0300
committerFelipe Balbi <balbi@ti.com>2011-09-09 13:02:04 +0300
commit5812b1c236774ea580b6af39411eb4f7297d7623 (patch)
treef25e68599057b95f7f0302922a17566b1e67e303 /drivers/usb/dwc3/gadget.c
parentdc137f01aca23ceb196945130a960e2a01b95890 (diff)
downloadlwn-5812b1c236774ea580b6af39411eb4f7297d7623.tar.gz
lwn-5812b1c236774ea580b6af39411eb4f7297d7623.zip
usb: dwc3: add a bounce buffer for control endpoints
This core cannot handle OUT transfers which aren't aligned to wMaxPacketSize, but that can happen at least on control endpoint with the USB Audio Class. This patch adds a bounce buffer to be used on the case of a non-aligned ep0out request is queued. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 56ccd97000a6..569473bcfb50 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1957,6 +1957,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
goto err2;
}
+ dwc->ep0_bounce = dma_alloc_coherent(dwc->dev,
+ 512, &dwc->ep0_bounce_addr, GFP_KERNEL);
+ if (!dwc->ep0_bounce) {
+ dev_err(dwc->dev, "failed to allocate ep0 bounce buffer\n");
+ ret = -ENOMEM;
+ goto err3;
+ }
+
dev_set_name(&dwc->gadget.dev, "gadget");
dwc->gadget.ops = &dwc3_gadget_ops;
@@ -1978,7 +1986,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
ret = dwc3_gadget_init_endpoints(dwc);
if (ret)
- goto err3;
+ goto err4;
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
@@ -1987,7 +1995,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
if (ret) {
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
irq, ret);
- goto err4;
+ goto err5;
}
/* Enable all but Start and End of Frame IRQs */
@@ -2006,27 +2014,31 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
if (ret) {
dev_err(dwc->dev, "failed to register gadget device\n");
put_device(&dwc->gadget.dev);
- goto err5;
+ goto err6;
}
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
- goto err6;
+ goto err7;
}
return 0;
-err6:
+err7:
device_unregister(&dwc->gadget.dev);
-err5:
+err6:
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
free_irq(irq, dwc);
-err4:
+err5:
dwc3_gadget_free_endpoints(dwc);
+err4:
+ dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
+ dwc->ep0_bounce_addr);
+
err3:
dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
dwc->setup_buf, dwc->setup_buf_addr);
@@ -2059,6 +2071,9 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dwc3_gadget_free_endpoints(dwc);
+ dma_free_coherent(dwc->dev, 512, dwc->ep0_bounce,
+ dwc->ep0_bounce_addr);
+
dma_free_coherent(dwc->dev, sizeof(*dwc->setup_buf) * 2,
dwc->setup_buf, dwc->setup_buf_addr);