RE: [PATCH v2] usb: fsl_udc: errata - postpone freeing current dTD

From
Chen Peter-B29397 <hidden>
Date
2012-05-21 07:26:07
Reply to
Christoph Fritz, 2012-05-21
=20
=20
USB controller may access a wrong address for the dTD (endpoint transfer
descriptor) and then hang. This happens a lot when doing tests with
g_ether module and iperf, a tool for measuring maximum TCP and UDP
bandwidth.
=20
This hardware bug is explained in detail by errata number 2858 for i.MX23=
:
http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf
=20
quoted hunk ↗ jump to hunk
All (?) SOCs with an IP from chipidea suffer from this problem.
mv_udc_core fixes this bug by commit daec765.  There still may be
unfixed drivers.
=20
Signed-off-by: Christoph Fritz <redacted>
Signed-off-by: Christian Hemp <redacted>
---
 drivers/usb/gadget/fsl_udc_core.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)
=20
diff --git a/drivers/usb/gadget/fsl_udc_core.c
b/drivers/usb/gadget/fsl_udc_core.c
index 55abfb6..72f2139 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -65,6 +65,8 @@ static struct usb_sys_interface *usb_sys_regs;
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller =3D NULL;
=20
+static struct ep_td_struct *last_free_td;
+
 static const struct usb_endpoint_descriptor
 fsl_ep0_desc =3D {
 	.bLength =3D		USB_DT_ENDPOINT_SIZE,
@@ -180,8 +182,13 @@ static void done(struct fsl_ep *ep, struct fsl_req
*req, int status)
 		curr_td =3D next_td;
 		if (j !=3D req->dtd_count - 1) {
 			next_td =3D curr_td->next_td_virt;
+			dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+		} else {
+			if (last_free_td !=3D NULL)
+				dma_pool_free(udc->td_pool, last_free_td,
+						last_free_td->td_dma);
+			last_free_td =3D curr_td;
 		}
-		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
 	}
=20
 	if (req->mapped) {
@@ -2579,6 +2586,8 @@ static int __init fsl_udc_probe(struct
platform_device *pdev)
 		goto err_unregister;
 	}
=20
+	last_free_td =3D NULL;
+
 	ret =3D usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
 	if (ret)
 		goto err_del_udc;
@@ -2633,6 +2642,10 @@ static int __exit fsl_udc_remove(struct
platform_device *pdev)
 	kfree(udc_controller->status_req);
 	kfree(udc_controller->eps);
=20
+	if (last_free_td !=3D NULL)
+		dma_pool_free(udc_controller->td_pool, last_free_td,
+				last_free_td->td_dma);
+
 	dma_pool_destroy(udc_controller->td_pool);
 	free_irq(udc_controller->irq, udc_controller);
 	iounmap(dr_regs);
Reviewed-by: Peter Chen <redacted>
--
1.7.2.5
=20
=20
Thread (42 messages) 42 messages, 7 authors, last reply 2012-10-22
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help