Patchwork [U-Boot,14/17] usb: mv_udc: Improve allocation of qTD items

login
register
mail settings
Submitter Marek Vasut
Date July 10, 2013, 1:16 a.m.
Message ID <1373419003-10919-15-git-send-email-marex@denx.de>
Download mbox | patch
Permalink /patch/257948/
State Awaiting Upstream
Delegated to: Marek Vasut
Headers show

Comments

Marek Vasut - July 10, 2013, 1:16 a.m.
Allocate the qTD items all at once instead of allocating them
separately. Moreover, make sure each qTD is properly aligned
to 32-bytes boundary and that cache can be safely flushed over
each qTD touple.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Lei Wen <leiwen@marvell.com>
Cc: Otavio Salvador <otavio@ossystems.com.br>
Cc: Stefano Babic <sbabic@denx.de>
---
 drivers/usb/gadget/mv_udc.c |   25 +++++++++++++++++++++++--
 include/usb/mv_udc.h        |    1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

Patch

diff --git a/drivers/usb/gadget/mv_udc.c b/drivers/usb/gadget/mv_udc.c
index 68ad9f1..55dd5df 100644
--- a/drivers/usb/gadget/mv_udc.c
+++ b/drivers/usb/gadget/mv_udc.c
@@ -460,6 +460,7 @@  void udc_disconnect(void)
 static int mvudc_probe(void)
 {
 	struct ept_queue_head *head;
+	uint8_t *imem;
 	int i;
 
 	const int num = 2 * NUM_ENDPOINTS;
@@ -469,12 +470,29 @@  static int mvudc_probe(void)
 	const int eplist_raw_sz = num * sizeof(struct ept_queue_head);
 	const int eplist_sz = roundup(eplist_raw_sz, ARCH_DMA_MINALIGN);
 
+	const int ilist_align = roundup(ARCH_DMA_MINALIGN, 32);
+	const int ilist_ent_raw_sz = 2 * sizeof(struct ept_queue_item);
+	const int ilist_ent_sz = roundup(ilist_ent_raw_sz, ARCH_DMA_MINALIGN);
+	const int ilist_sz = NUM_ENDPOINTS * ilist_ent_sz;
+
 	/* The QH list must be aligned to 4096 bytes. */
 	controller.epts = memalign(eplist_align, eplist_sz);
 	if (!controller.epts)
 		return -ENOMEM;
 	memset(controller.epts, 0, eplist_sz);
 
+	/*
+	 * Each qTD item must be 32-byte aligned, each qTD touple must be
+	 * cacheline aligned. There are two qTD items for each endpoint and
+	 * only one of them is used for the endpoint at time, so we can group
+	 * them together.
+	 */
+	controller.items_mem = memalign(ilist_align, ilist_sz);
+	if (!controller.items_mem) {
+		free(controller.epts);
+		return -ENOMEM;
+	}
+
 	for (i = 0; i < 2 * NUM_ENDPOINTS; i++) {
 		/*
 		 * Configure QH for each endpoint. The structure of the QH list
@@ -493,8 +511,11 @@  static int mvudc_probe(void)
 		head->next = TERMINATE;
 		head->info = 0;
 
-		controller.items[i] = memalign(roundup(32, ARCH_DMA_MINALIGN),
-					       sizeof(struct ept_queue_item));
+		imem = controller.items_mem + ((i >> 1) * ilist_ent_sz);
+		if (i & 1)
+			imem += sizeof(struct ept_queue_item);
+
+		controller.items[i] = (struct ept_queue_item *)imem;
 	}
 
 	INIT_LIST_HEAD(&controller.gadget.ep_list);
diff --git a/include/usb/mv_udc.h b/include/usb/mv_udc.h
index 78fa81c..b58a95f 100644
--- a/include/usb/mv_udc.h
+++ b/include/usb/mv_udc.h
@@ -90,6 +90,7 @@  struct mv_drv {
 	struct ehci_ctrl		*ctrl;
 	struct ept_queue_head		*epts;
 	struct ept_queue_item		*items[2 * NUM_ENDPOINTS];
+	uint8_t				*items_mem;
 	struct mv_ep			ep[NUM_ENDPOINTS];
 };