SAMA5 EHCI: Correct and extend pool allocation logic; Fix data toggle values

This commit is contained in:
Gregory Nutt 2013-08-28 10:03:48 -06:00
parent 556446e3a1
commit 6acb286c39
2 changed files with 57 additions and 12 deletions

View File

@ -404,6 +404,14 @@ config SAMA5_EHCI_BUFSIZE
size must be an even number of 32-bit words and must be large enough
to hangle the largest transfer via a SETUP request.
config SAMA5_EHCI_PREALLOCATE
bool "Preallocate descriptor pool"
default y
---help---
Select this option to pre-allocate EHCI queue and descriptor
structure pools in .bss. Otherwise, these pools will be
dynamically allocated using kmemalign().
config SAMA5_EHCI_REGDEBUG
bool "Enable low-level EHCI register debug"
default n

View File

@ -415,6 +415,7 @@ static struct sam_qh_s g_perhead __attribute__ ((aligned(32)));
static uint32_t g_framelist[FRAME_LIST_SIZE] __attribute__ ((aligned(4096)));
#endif
#ifdef CONFIG_SAMA5_EHCI_PREALLOCATE
/* Pools of pre-allocated data structures. These will all be linked into the
* free lists within g_ehci. These must all be aligned to 32-byte boundaries
*/
@ -429,6 +430,21 @@ static struct sam_qh_s g_qhpool[CONFIG_SAMA5_EHCI_NQHS]
static struct sam_qtd_s g_qtdpool[CONFIG_SAMA5_EHCI_NQTDS]
__attribute__ ((aligned(32)));
#else
/* Pools of dynamically data structures. These will all be linked into the
* free lists within g_ehci. These must all be aligned to 32-byte boundaries
*/
/* Queue Head (QH) pool */
static struct sam_qh_s *g_qhpool;
/* Queue Element Transfer Descriptor (qTD) pool */
static struct sam_qtd_s *g_qtdpool;
#endif
/*******************************************************************************
* Private Functions
*******************************************************************************/
@ -824,7 +840,7 @@ static struct sam_qtd_s *sam_qtd_alloc(void)
if (qtd)
{
g_ehci.qtdfree = ((struct sam_list_s *)qtd)->flink;
memset(qtd, 0, sizeof(struct sam_list_s));
memset(qtd, 0, sizeof(struct sam_qtd_s));
}
return qtd;
@ -1836,13 +1852,6 @@ static ssize_t sam_async_transfer(struct sam_rhport_s *rhport,
DEBUGASSERT(rhport && epinfo);
if (req != NULL)
{
uvdbg("req=%02x type=%02x value=%04x index=%04x\n",
req->req, req->type, sam_read16(req->value),
sam_read16(req->index));
}
/* A buffer may or may be supplied with an EP0 SETUP transfer. A buffer will
* always be present for normal endpoint data transfers.
*/
@ -1908,7 +1917,7 @@ static ssize_t sam_async_transfer(struct sam_rhport_s *rhport,
/* Get the new forward link pointer and data toggle */
flink = &qtd->hw.nqp;
toggle = 0;
toggle = QTD_TOKEN_TOGGLE;
}
/* A buffer may or may be supplied with an EP0 SETUP transfer. A buffer will
@ -3717,8 +3726,6 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
DEBUGASSERT(controller == 0);
DEBUGASSERT(((uintptr_t)&g_asynchead & 0x1f) == 0);
DEBUGASSERT(((uintptr_t)&g_qhpool & 0x1f) == 0);
DEBUGASSERT(((uintptr_t)&g_qtdpool & 0x1f) == 0);
DEBUGASSERT((sizeof(struct sam_qh_s) & 0x1f) == 0);
DEBUGASSERT((sizeof(struct sam_qtd_s) & 0x1f) == 0);
@ -3727,6 +3734,11 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
DEBUGASSERT(((uintptr_t)g_framelist & 0xfff) == 0);
#endif
#ifdef CONFIG_SAMA5_EHCI_PREALLOCATE
DEBUGASSERT(((uintptr_t)&g_qhpool & 0x1f) == 0);
DEBUGASSERT(((uintptr_t)&g_qtdpool & 0x1f) == 0);
#endif
/* SAMA5 Configuration *******************************************************/
/* For High-speed operations, the user has to perform the following:
*
@ -3827,6 +3839,18 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
sem_init(&rhport->ep0.iocsem, 0, 0);
}
#ifndef CONFIG_SAMA5_EHCI_PREALLOCATE
/* Allocate a pool of free Queue Head (QH) structures */
g_qhpool = (struct sam_qh_s *)
kmemalign(32, CONFIG_SAMA5_EHCI_NQHS * sizeof(struct sam_qh_s));
if (!g_qhpool)
{
udbg("ERROR: Failed to allocate the QH pool\n");
return NULL;
}
#endif
/* Initialize the list of free Queue Head (QH) structures */
for (i = 0; i < CONFIG_SAMA5_EHCI_NQHS; i++)
@ -3836,7 +3860,20 @@ FAR struct usbhost_connection_s *sam_ehci_initialize(int controller)
sam_qh_free(&g_qhpool[i]);
}
/* Initialize the list of free Queue Head (QH) structures */
#ifndef CONFIG_SAMA5_EHCI_PREALLOCATE
/* Allocate a pool of free Transfer Descriptor (qTD) structures */
g_qtdpool = (struct sam_qtd_s *)
kmemalign(32, CONFIG_SAMA5_EHCI_NQTDS * sizeof(struct sam_qtd_s));
if (!g_qtdpool)
{
udbg("ERROR: Failed to allocate the qTD pool\n");
kfree(g_qhpool);
return NULL;
}
#endif
/* Initialize the list of free Transfer Descriptor (qTD) structures */
for (i = 0; i < CONFIG_SAMA5_EHCI_NQTDS; i++)
{