[PATCH 81/133] [Jaunty SRU] ARM.imx51 Freescale:ENGR00111644 i.MX51 usb gadget mass storage data in failure

Brad Figg brad.figg at canonical.com
Thu Jul 9 17:49:11 BST 2009


From: Jun Li <r65092 at freescale.com>

When usb gadget MSC data in(i.MX51=>PC) in INCR8 mode, USB
Controller IC need read the completed dtd after its ACTIVE
bit to be 0. if SW free the completed dtd memory before the
read, may result in data copy failure.
This is a software workaround to avoid the issue case:
when free dtds of a usb req, postpone free the last dtd. so
the dtd before an ACTIVE dtd will always be freed in next IOC
irq.

Signed-off-by: Li Jun <r65092 at freescale.com>
Signed-off-by: Brad Figg <brad.figg at canonical.com>
---
 drivers/usb/gadget/arcotg_udc.c |   26 +++++++++++++++++++++++---
 drivers/usb/gadget/arcotg_udc.h |    6 ++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 2a5d78f..846d603 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -76,6 +76,9 @@ volatile static struct usb_sys_interface *usb_sys_regs;
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller;
 
+#ifdef POSTPONE_FREE_LAST_DTD
+static struct ep_td_struct *last_free_td;
+#endif
 static const struct usb_endpoint_descriptor
 fsl_ep0_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
@@ -172,10 +175,21 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
 	next_td = req->head;
 	for (j = 0; j < req->dtd_count; j++) {
 		curr_td = next_td;
-		if (j != req->dtd_count - 1)
+		if (j != req->dtd_count - 1) {
 			next_td = curr_td->next_td_virt;
+#ifdef POSTPONE_FREE_LAST_DTD
+			dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+		} else {
+			if (last_free_td != NULL)
+				dma_pool_free(udc->td_pool, last_free_td,
+						last_free_td->td_dma);
+			last_free_td = curr_td;
+		}
+#else
+		}
 
 		dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
+#endif
 	}
 
 	if (USE_MSC_WR(req->req.length)) {
@@ -2707,7 +2721,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 			    IO_ADDRESS(udc_controller->iram_buffer[i]);
 		}
 	}
-
+#ifdef POSTPONE_FREE_LAST_DTD
+	last_free_td = NULL;
+#endif
 	create_proc_file();
 	return 0;
 
@@ -2750,7 +2766,11 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
 	kfree(udc_controller->status_req->req.buf);
 	kfree(udc_controller->status_req);
 	kfree(udc_controller->eps);
-
+#ifdef POSTPONE_FREE_LAST_DTD
+	if (last_free_td != NULL)
+		dma_pool_free(udc_controller->td_pool, last_free_td,
+				last_free_td->td_dma);
+#endif
 	dma_pool_destroy(udc_controller->td_pool);
 	free_irq(udc_controller->irq, udc_controller);
 	iounmap(dr_regs);
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index aa57bd8..447aef8 100644
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -44,6 +44,12 @@
 #define NEED_IRAM(ep) ((g_iram_size) && \
 	((ep)->desc->bmAttributes == USB_ENDPOINT_XFER_BULK))
 
+#ifdef CONFIG_ARCH_MX51
+#define POSTPONE_FREE_LAST_DTD
+#else
+#undef POSTPONE_FREE_LAST_DTD
+#endif
+
 /* ### define USB registers here
  */
 #define USB_MAX_ENDPOINTS		8
-- 
1.6.0.4




More information about the kernel-team mailing list