LPC31 and SAMA5Dx EHCI drivers: Fix cache related problem. All buffers are now aligned with the cache line size in both starting address and in length. This cause major problems in unlucky builds where the USB host buffers where unaligned and abbutting other data. The cache flush and invalidate operations could be subverted by acceses to adjacent data or could have unexpected side effects. This bug has been in the ECHI drivers forever, but was only revealed due to unlucky memory allocations during the integration of the hub feature.
This commit is contained in:
parent
6d6fdc41d3
commit
2cb53d1931
|
@ -70,6 +70,11 @@
|
|||
# undef HAVE_AESENGINE /* No AES engine */
|
||||
#endif
|
||||
|
||||
/* Cache line sizes (in bytes)for the SAVA5Dx */
|
||||
|
||||
#define ARM_DCACHE_LINESIZE 32 /* 32 bytes (8 words) */
|
||||
#define ARM_ICACHE_LINESIZE 32 /* 32 bytes (8 words) */
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "up_arch.h"
|
||||
#include "cache.h"
|
||||
|
||||
#include "chip.h"
|
||||
#include "lpc31_internal.h"
|
||||
#include "lpc31_cgudrvr.h"
|
||||
#include "lpc31_syscreg.h"
|
||||
|
@ -96,12 +97,19 @@
|
|||
# define CONFIG_LPC31_EHCI_NQTDS (LPC31_EHCI_NRHPORT + 3)
|
||||
#endif
|
||||
|
||||
/* Buffers must be aligned to the cache line size */
|
||||
|
||||
#define DCACHE_LINEMASK (ARM_DCACHE_LINESIZE -1)
|
||||
|
||||
/* Configurable size of a request/descriptor buffers */
|
||||
|
||||
#ifndef CONFIG_LPC31_EHCI_BUFSIZE
|
||||
# define CONFIG_LPC31_EHCI_BUFSIZE 128
|
||||
#endif
|
||||
|
||||
#define LPC31_EHCI_BUFSIZE \
|
||||
((CONFIG_LPC31_EHCI_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK)
|
||||
|
||||
/* Debug options */
|
||||
|
||||
#ifndef CONFIG_DEBUG
|
||||
|
@ -4005,12 +4013,15 @@ static int lpc31_alloc(FAR struct usbhost_driver_s *drvr,
|
|||
int ret = -ENOMEM;
|
||||
DEBUGASSERT(drvr && buffer && maxlen);
|
||||
|
||||
/* There is no special requirements for transfer/descriptor buffers. */
|
||||
/* The only special requirements for transfer/descriptor buffers are that (1)
|
||||
* they be aligned to a cache line boundary and (2) they are a multiple of the
|
||||
* cache line size in length.
|
||||
*/
|
||||
|
||||
*buffer = (FAR uint8_t *)kmm_malloc(CONFIG_LPC31_EHCI_BUFSIZE);
|
||||
*buffer = (FAR uint8_t *)kmm_memalign(LPC31_EHCI_BUFSIZE, ARM_DCACHE_LINESIZE);
|
||||
if (*buffer)
|
||||
{
|
||||
*maxlen = CONFIG_LPC31_EHCI_BUFSIZE;
|
||||
*maxlen = LPC31_EHCI_BUFSIZE;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
|
@ -4082,11 +4093,14 @@ static int lpc31_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer
|
|||
{
|
||||
DEBUGASSERT(drvr && buffer && buflen > 0);
|
||||
|
||||
/* The only special requirements for I/O buffers are they might need to be user
|
||||
* accessible (depending on how the class driver implements its buffering).
|
||||
/* The only special requirements for I/O buffers are that (1) they be aligned to a
|
||||
* cache line boundary, (2) they are a multiple of the cache line size in length,
|
||||
* and (3) they might need to be user accessible (depending on how the class driver
|
||||
* implements its buffering).
|
||||
*/
|
||||
|
||||
*buffer = (FAR uint8_t *)kumm_malloc(buflen);
|
||||
buflen = (buflen + DCACHE_LINEMASK) & ~DCACHE_LINEMASK;
|
||||
*buffer = (FAR uint8_t *)kumm_memalign(buflen, ARM_DCACHE_LINESIZE);
|
||||
return *buffer ? OK : -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,5 +55,9 @@
|
|||
|
||||
#define L2CC_VBASE SAM_L2CC_VSECTION
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_SAMA5_CHIP_H */
|
||||
/* Cache line sizes (in bytes)for the SAVA5Dx */
|
||||
|
||||
#define ARMV7A_DCACHE_LINESIZE 32 /* 32 bytes (8 words) */
|
||||
#define ARMV7A_ICACHE_LINESIZE 32 /* 32 bytes (8 words) */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_SAMA5_CHIP_H */
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "up_arch.h"
|
||||
#include "cache.h"
|
||||
|
||||
#include "chip.h"
|
||||
#include "sam_periphclks.h"
|
||||
#include "sam_memories.h"
|
||||
#include "sam_usbhost.h"
|
||||
|
@ -95,12 +96,19 @@
|
|||
# define CONFIG_SAMA5_EHCI_NQTDS (SAM_EHCI_NRHPORT + 3)
|
||||
#endif
|
||||
|
||||
/* Buffers must be aligned to the cache line size */
|
||||
|
||||
#define DCACHE_LINEMASK (ARMV7A_DCACHE_LINESIZE -1)
|
||||
|
||||
/* Configurable size of a request/descriptor buffers */
|
||||
|
||||
#ifndef CONFIG_SAMA5_EHCI_BUFSIZE
|
||||
# define CONFIG_SAMA5_EHCI_BUFSIZE 128
|
||||
#endif
|
||||
|
||||
#define SAMA5_EHCI_BUFSIZE \
|
||||
((CONFIG_SAMA5_EHCI_BUFSIZE + DCACHE_LINEMASK) & ~DCACHE_LINEMASK)
|
||||
|
||||
/* Debug options */
|
||||
|
||||
#ifndef CONFIG_DEBUG
|
||||
|
@ -3832,12 +3840,15 @@ static int sam_alloc(FAR struct usbhost_driver_s *drvr,
|
|||
int ret = -ENOMEM;
|
||||
DEBUGASSERT(drvr && buffer && maxlen);
|
||||
|
||||
/* There is no special requirements for transfer/descriptor buffers. */
|
||||
/* The only special requirements for transfer/descriptor buffers are that (1)
|
||||
* they be aligned to a cache line boundary and (2) they are a multiple of the
|
||||
* cache line size in length.
|
||||
*/
|
||||
|
||||
*buffer = (FAR uint8_t *)kmm_malloc(CONFIG_SAMA5_EHCI_BUFSIZE);
|
||||
*buffer = (FAR uint8_t *)kmm_memalign(SAMA5_EHCI_BUFSIZE, ARMV7A_DCACHE_LINESIZE);
|
||||
if (*buffer)
|
||||
{
|
||||
*maxlen = CONFIG_SAMA5_EHCI_BUFSIZE;
|
||||
*maxlen = SAMA5_EHCI_BUFSIZE;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
|
@ -3909,11 +3920,14 @@ static int sam_ioalloc(FAR struct usbhost_driver_s *drvr, FAR uint8_t **buffer,
|
|||
{
|
||||
DEBUGASSERT(drvr && buffer && buflen > 0);
|
||||
|
||||
/* The only special requirements for I/O buffers are they might need to be user
|
||||
* accessible (depending on how the class driver implements its buffering).
|
||||
/* The only special requirements for I/O buffers are that (1) they be aligned to a
|
||||
* cache line boundary, (2) they are a multiple of the cache line size in length,
|
||||
* and (3) they might need to be user accessible (depending on how the class driver
|
||||
* implements its buffering).
|
||||
*/
|
||||
|
||||
*buffer = (FAR uint8_t *)kumm_malloc(buflen);
|
||||
buflen = (buflen + DCACHE_LINEMASK) & ~DCACHE_LINEMASK;
|
||||
*buffer = (FAR uint8_t *)kumm_memalign(buflen, ARMV7A_DCACHE_LINESIZE);
|
||||
return *buffer ? OK : -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue