aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut2013-07-10 03:16:40 +0200
committerMarek Vasut2013-07-29 23:01:32 +0200
commit8a095a68ce8e7989dec6af4011f0f41bbc554f22 (patch)
tree5953b488cc016d5233b629e45cde9cea5a044e36
parentb5cd45bfad3a25db25b40cfda9e7db80e5ee65f7 (diff)
usb: mv_udc: Improve allocation of qTD items
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>
-rw-r--r--drivers/usb/gadget/mv_udc.c25
-rw-r--r--include/usb/mv_udc.h1
2 files changed, 24 insertions, 2 deletions
diff --git a/drivers/usb/gadget/mv_udc.c b/drivers/usb/gadget/mv_udc.c
index 04787be7e01..dbdf878d93f 100644
--- a/drivers/usb/gadget/mv_udc.c
+++ b/drivers/usb/gadget/mv_udc.c
@@ -444,6 +444,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;
@@ -453,12 +454,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
@@ -477,8 +495,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 a9869f019d1..c1761b07246 100644
--- a/include/usb/mv_udc.h
+++ b/include/usb/mv_udc.h
@@ -77,6 +77,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];
};