common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
This is the out-of-function-scope counterpart ofALLOC_CACHE_ALIGN_BUFFER.
--- include/common.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
include/common.h +11 -0
@@ -965,6 +965,17 @@ int cpu_release(int nr, int argc, char * const argv[]); \ type *name = (type *) ALIGN((uintptr_t)__##name, ARCH_DMA_MINALIGN) +/* +* DEFINE_CACHE_ALIGN_BUFFER() is similar to ALLOC_CACHE_ALIGN_BUFFER, but it's +* purpose is to allow allocating aligned buffers outside of function scope. +* Usage of this macro shall be avoided or used with extreme care! + */ +#define DEFINE_CACHE_ALIGN_BUFFER (type, name, size) \ + static char __##name[roundup(size * sizeof(type), ARCH_DMA_MINALIGN)] \ + __aligned(ARCH_DMA_MINALIGN); \ + \ + static type *name = (type *)__##name; +/* Pull in stuff for the build system */ #ifdef DO_DEPS_ONLY # include <environment.h>
Signature · 1 line
1.7.10.4
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
From: Tom Rini <[email protected]>
The USB spec says that 32 bytes is the minimum required alignment. However on some platforms we have a larger minimum requirement for cache coherency. In those cases, use that value rather than the USB spec minimum. We add a cpp check to <usb.h> to define USB_DMA_MINALIGN and make use of it in ehci-hcd.c and musb_core.h. We cannot use MAX() here as we are not allowed to have tests inside of align(...).
[ilya.yanok]: fix size alignment, drop (incorrect) rounding when invalidating the buffer. If we got unaligned buffer from the upper layer -- that's definetely a bug so it's good to buzz about it. But we have to align the buffer length -- upper layers should take care to reserve enough space.
[marek.vasut]: introduce some crazy macro voodoo
--- drivers/usb/host/ehci-hcd.c | 81 ++++++++++++++++++++++++------------------ drivers/usb/musb/musb_core.h | 2 +- include/usb.h | 10 ++++++ 3 files changed, 57 insertions(+), 36 deletions(-)
drivers/usb/host/ehci-hcd.c +46 -35
@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, not need for volatile */volatile struct ehci_hcor *hcor;static uint16_t portreset; -static struct QH qh_list __attribute__((aligned(32))); +DEFINE_CACHE_ALIGN_BUFFER(struct QH, qh_list, 1); + +#define ALIGN_END_ADDR (type, ptr, size) \ + ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) static struct descriptor { struct usb_hub_descriptor hub;
@@ -172,13 +175,13 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) {uint32_t delta, next;uint32_t addr = (uint32_t )buf; -size_t rsz =roundup (sz,32 ); +size_t rsz =roundup (sz,USB_DMA_MINALIGN );int idx;if (sz != rsz)debug ("EHCI-HCD: Misaligned buffer size (%08x)\n" , sz); -if (addr &31 ) +if (addr !=ALIGN (addr,USB_DMA_MINALIGN ))debug ("EHCI-HCD: Misaligned buffer address (%p)\n" , buf); idx =0 ;
@@ -207,8 +210,8 @@ static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { - static struct QH qh __attribute__((aligned(32))); - static struct qTD qtd[3] __attribute__((aligned (32))); + ALLOC_CACHE_ALIGN_BUFFER(struct QH, qh, 1); + ALLOC_CACHE_ALIGN_BUFFER(struct qTD, qtd, 3);int qtd_counter =0 ;volatile struct qTD *vtd;
@@ -229,8 +232,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,le16_to_cpu (req->value),le16_to_cpu (req->value), le16_to_cpu(req->index)); -memset (&qh,0 ,sizeof (struct QH )); -memset (qtd,0 ,sizeof (qtd)); +memset (qh,0 ,sizeof (struct QH )); +memset (qtd,0 ,3 *sizeof (*qtd)); toggle =usb_gettoggle (dev,usb_pipeendpoint (pipe),usb_pipeout (pipe));
@@ -244,7 +247,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,* qh_overlay.qt_next ...... 13-10 H * - qh_overlay.qt_altnext */ - qh.qh_link =cpu_to_hc32 ((uint32_t )&qh_list |QH_LINK_TYPE_QH ); + qh->qh_link =cpu_to_hc32 ((uint32_t )qh_list |QH_LINK_TYPE_QH ); c = (usb_pipespeed (pipe) !=USB_SPEED_HIGH &&usb_pipeendpoint (pipe) ==0 ) ?1 :0 ; endpt = (8 << 28) |
@@ -255,14 +258,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, (usb_pipespeed (pipe) <<12 ) | (usb_pipeendpoint (pipe) <<8 ) | (0 <<7 ) | (usb_pipedevice (pipe) <<0 ); - qh.qh_endpt1 =cpu_to_hc32 (endpt); + qh->qh_endpt1 =cpu_to_hc32 (endpt); endpt = (1 <<30 ) | (dev->portnr <<23 ) | (dev->parent->devnum <<16 ) | (0 <<8 ) | (0 <<0 ); - qh.qh_endpt2 =cpu_to_hc32 (endpt); - qh.qh_overlay.qt_next =cpu_to_hc32 (QT_NEXT_TERMINATE ); + qh->qh_endpt2 =cpu_to_hc32 (endpt); + qh->qh_overlay.qt_next =cpu_to_hc32 (QT_NEXT_TERMINATE ); - tdp = &qh.qh_overlay.qt_next; + tdp = &qh->qh_overlay.qt_next;if (req !=NULL ) {/*
@@ -340,13 +343,13 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, tdp = &qtd[qtd_counter++].qt_next; } - qh_list.qh_link =cpu_to_hc32 ((uint32_t )&qh |QH_LINK_TYPE_QH ); + qh_list->qh_link =cpu_to_hc32 ((uint32_t )qh |QH_LINK_TYPE_QH );/* Flush dcache */ -flush_dcache_range ((uint32_t )&qh_list, - (uint32_t )&qh_list +sizeof (struct QH )); -flush_dcache_range ((uint32_t )&qh, (uint32_t )&qh +sizeof (struct QH )); -flush_dcache_range ((uint32_t )qtd, (uint32_t )qtd +sizeof (qtd)); +flush_dcache_range ((uint32_t )qh_list, + ALIGN_END_ADDR(struct QH, qh_list, 1)); + flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1)); + flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, 3)); usbsts =ehci_readl (&hcor->or_usbsts);ehci_writel (&hcor->or_usbsts, (usbsts &0x3f ));
@@ -369,12 +372,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, timeout =USB_TIMEOUT_MS (pipe); do { /* Invalidate dcache */ - invalidate_dcache_range((uint32_t)&qh_list, - (uint32_t)&qh_list + sizeof(struct QH)); - invalidate_dcache_range((uint32_t)&qh, - (uint32_t)&qh + sizeof(struct QH)); + invalidate_dcache_range((uint32_t)qh_list, + ALIGN_END_ADDR(struct QH, qh_list, 1)); + invalidate_dcache_range((uint32_t)qh, + ALIGN_END_ADDR(struct QH, qh, 1)); invalidate_dcache_range((uint32_t)qtd, - (uint32_t)qtd + sizeof(qtd)); + ALIGN_END_ADDR(struct qTD, qtd, 3)); token = hc32_to_cpu(vtd->qt_token); if (!(token & 0x80))
@@ -382,9 +385,17 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,WATCHDOG_RESET (); }while (get_timer (ts) < timeout); -/* Invalidate the memory area occupied by buffer */ -invalidate_dcache_range (((uint32_t )buffer & ~31 ), - ((uint32_t )buffer & ~31 ) +roundup (length,32 )); +/* +* Invalidate the memory area occupied by buffer +* Don't try to fix the buffer alignment, if it isn't properly +* aligned it's upper layer's fault so let invalidate_dcache_range() +* vow about it. But we have to fix the length as it's actual +* transfer length and can be unaligned. This is potentially +* dangerous operation, it's responsibility of the calling +* code to make sure enough space is reserved. +*/ +invalidate_dcache_range ((uint32_t )buffer, +ALIGN_END_ADDR (u8, buffer, length));/* Check that the TD processing happened */ if (token &0x80 ) {
@@ -403,9 +414,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, goto fail; } - qh_list.qh_link =cpu_to_hc32 ((uint32_t )&qh_list |QH_LINK_TYPE_QH ); + qh_list->qh_link =cpu_to_hc32 ((uint32_t )qh_list |QH_LINK_TYPE_QH ); - token =hc32_to_cpu (qh.qh_overlay.qt_token); + token =hc32_to_cpu (qh->qh_overlay.qt_token);if (!(token &0x80 )) {debug ("TOKEN=%#x\n" , token);switch (token &0xfc ) {
@@ -733,16 +744,16 @@ int usb_lowlevel_init(void)#endif /* Set head of reclaim list */ -memset (&qh_list,0 ,sizeof (qh_list)); - qh_list.qh_link =cpu_to_hc32 ((uint32_t )&qh_list |QH_LINK_TYPE_QH ); - qh_list.qh_endpt1 =cpu_to_hc32 ((1 <<15 ) | (USB_SPEED_HIGH <<12 )); - qh_list.qh_curtd =cpu_to_hc32 (QT_NEXT_TERMINATE ); - qh_list.qh_overlay.qt_next =cpu_to_hc32 (QT_NEXT_TERMINATE ); - qh_list.qh_overlay.qt_altnext =cpu_to_hc32 (QT_NEXT_TERMINATE ); - qh_list.qh_overlay.qt_token =cpu_to_hc32 (0x40 ); +memset (qh_list,0 ,sizeof (*qh_list)); + qh_list->qh_link =cpu_to_hc32 ((uint32_t )qh_list |QH_LINK_TYPE_QH ); + qh_list->qh_endpt1 =cpu_to_hc32 ((1 <<15 ) | (USB_SPEED_HIGH <<12 )); + qh_list->qh_curtd =cpu_to_hc32 (QT_NEXT_TERMINATE ); + qh_list->qh_overlay.qt_next =cpu_to_hc32 (QT_NEXT_TERMINATE ); + qh_list->qh_overlay.qt_altnext =cpu_to_hc32 (QT_NEXT_TERMINATE ); + qh_list->qh_overlay.qt_token =cpu_to_hc32 (0x40 );/* Set async. queue head pointer. */ -ehci_writel (&hcor->or_asynclistaddr, (uint32_t )&qh_list); +ehci_writel (&hcor->or_asynclistaddr, (uint32_t )qh_list); reg =ehci_readl (&hccr->cr_hcsparams); descriptor.hub.bNbrPorts =HCS_N_PORTS (reg);
drivers/usb/musb/musb_core.h +1 -1
@@ -145,7 +145,7 @@ struct musb_regs { struct musb_epN_regs epN; } ep[16 ]; -} __attribute__((packed, aligned(32))); +} __attribute__((packed, aligned(USB_DMA_MINALIGN)));#endif /*
include/usb.h +10 -0
@@ -29,6 +29,16 @@#include <usb_defs.h> #include <usbdescriptors.h> +/* +* The EHCI spec says that we must align to at least 32 bytes. However, +* some platforms require larger alignment. +*/ +#if ARCH_DMA_MINALIGN >32 +#define USB_DMA_MINALIGN ARCH_DMA_MINALIGN +#else +#define USB_DMA_MINALIGN 32 +#endif +/* Everything is aribtrary */ #define USB_ALTSETTINGALLOC 4#define USB_MAXALTSETTING 128/* Hard limit */
Signature · 1 line
1.7.10.4
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Hi Marek,
On Sun, Jul 8, 2012 at 7:08 AM, Marek Vasut <[email protected]> wrote:
[...]
drivers/usb/host/ehci-hcd.c +0 -0
drivers/usb/host/ehci-hcd.c
Quoted 11 lines
index 04300be..5199560 100644
drivers/usb/host/ehci-hcd.c +0
-0@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, not needfor volatile */
volatile structehci_hcor*hcor;static
uint16_tportreset;drivers/usb/host/ehci-hcd.c +1
-1-static struct QH qh_list __attribute__((aligned(32))); +DEFINE_CACHE_ALIGN_BUFFER(struct QH, qh_list, 1);
This will align on ARCH_DMA_MINALIGN, not USB_DMA_MINALIGN. In case of ARCH_DMA_MINALIGN < 32 we will loose the 32-byte alignment required by USB spec.
The same with other buffers. Otherwise looks great.
Regards, Ilya.
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Ilya Yanok,
Quoted 16 lines
Hi Marek,
On Sun, Jul 8, 2012 at 7:08 AM, Marek Vasut <[email protected]> wrote:
[...]
drivers/usb/host/ehci-hcd.c +0
-0Quoted 9 lines
index 04300be..5199560 100644
drivers/usb/host/ehci-hcd.c +0
-0@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, notneed for volatile */
volatile struct
ehci_hcor*hcor;
Quoted 8 lines
drivers/usb/host/ehci-hcd.c
Quoted 4 lines
static
uint16_tportreset;drivers/usb/host/ehci-hcd.c +1
-1-static struct QH qh_list __attribute__((aligned(32))); +DEFINE_CACHE_ALIGN_BUFFER(struct QH, qh_list, 1);This will align on
ARCH_DMA_MINALIGN, notUSB_DMA_MINALIGN. In case ofARCH_DMA_MINALIGN< 32 we will loose the 32-byte alignment required by USB spec.
That's true -- maybe we should create ALLOC_ALIGN_BUFFER() and ALLOC_CACHE_ALIGN_BUFFER() to be a special case of it ?
Quoted 3 lines
The same with other buffers. Otherwise looks great.
Regards, Ilya.
Best regards,
Marek Vasut
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Quoted 27 lines · Marek Vasut
Dear Ilya Yanok,
Quoted 16 lines
Hi Marek,
On Sun, Jul 8, 2012 at 7:08 AM, Marek Vasut <[email protected]> wrote:
[...]
drivers/usb/host/ehci-hcd.c +0
-0Quoted 9 lines
index 04300be..5199560 100644
drivers/usb/host/ehci-hcd.c +0
-0@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, notneed for volatile */
volatile struct
ehci_hcor*hcor;Quoted 8 lines
drivers/usb/host/ehci-hcd.c
Quoted 4 lines
static
uint16_tportreset;drivers/usb/host/ehci-hcd.c +1
-1-static struct QH qh_list __attribute__((aligned(32))); +DEFINE_CACHE_ALIGN_BUFFER(struct QH, qh_list, 1);This will align on
ARCH_DMA_MINALIGN, notUSB_DMA_MINALIGN. In case ofARCH_DMA_MINALIGN< 32 we will loose the 32-byte alignment required by USB spec.
Quoted 2 lines
That's true -- maybe we should create
ALLOC_ALIGN_BUFFER()andALLOC_CACHE_ALIGN_BUFFER()to be a special case of it ?
Lets think. USB says "32byte min". Do we have other buses today that apply similar constraints? If so, we should probably go about abstracting into a __ALIGN_FOO(size, what) and do a general one and a USB one that does 32 or cachline. If it's just USB that might be overkill however...
Signature · 1 line
Tom
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Tom Rini,
Quoted 28 lines · Marek Vasut
Quoted 27 lines
Dear Ilya Yanok,
Quoted 24 lines
Hi Marek,
On Sun, Jul 8, 2012 at 7:08 AM, Marek Vasut <[email protected]> wrote:
[...]
drivers/usb/host/ehci-hcd.c +0
-0drivers/usb/host/ehci-hcd.c
Quoted 13 lines
index 04300be..5199560 100644
drivers/usb/host/ehci-hcd.c +0
-0@@ -34,7 +34,10 @@ struct ehci_hccr *hccr; /* R/O registers, notneed for volatile */
volatile struct
ehci_hcor*hcor;static
uint16_tportreset;drivers/usb/host/ehci-hcd.c +1
-1-static struct QH qh_list __attribute__((aligned(32))); +DEFINE_CACHE_ALIGN_BUFFER(struct QH, qh_list, 1);This will align on
ARCH_DMA_MINALIGN, notUSB_DMA_MINALIGN. In case ofARCH_DMA_MINALIGN< 32 we will loose the 32-byte alignment required by USB spec.
Quoted 8 lines
Quoted 2 lines
That's true -- maybe we should create
ALLOC_ALIGN_BUFFER()andALLOC_CACHE_ALIGN_BUFFER()to be a special case of it ?Lets think. USB says "32byte min". Do we have other buses today that apply similar constraints? If so, we should probably go about abstracting into a
__ALIGN_FOO(size, what)and do a general one and a USB one that does 32 or cachline. If it's just USB that might be overkill however...
Let's do this, we dunno what craziness can befall us in the future. And having the macro handy won't hurt anyway.
Best regards,
Marek Vasut
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
In reply to Marek VasutHi Marek,
Quoted 9 lines · Marek Vasut
drivers/usb/host/ehci-hcd.c +4
-3-/* Invalidate the memory area occupied by buffer */ -invalidate_dcache_range (((uint32_t )buffer & ~31 ), - ((uint32_t )buffer & ~31 ) +roundup (length,32 )); +/* +* Invalidate the memory area occupied by buffer +* Don't try to fix the buffer alignment, if it isn't properly +* aligned it's upper layer's fault so let
invalidate_dcache_range()
drivers/usb/host/ehci-hcd.c ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, · line 398
Quoted 7 lines
drivers/usb/host/ehci-hcd.c +7
-0+* vow about it. But we have to fix the length as it's actual +* transfer length and can be unaligned. This is potentially +* dangerous operation, it's responsibility of the calling +* code to make sure enough space is reserved. +*/ +invalidate_dcache_range ((uint32_t )buffer, +ALIGN_END_ADDR (u8, buffer, length));
We shouldn't use ALIGN_END_ADDR here. This can lead to strange results on systems with ARCH_DMA_MINALIGN < 32.
Regards, Ilya.
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Ilya Yanok,
Quoted 19 lines
Hi Marek,
Quoted 8 lines · Marek Vasut
drivers/usb/host/ehci-hcd.c +4
-3-/* Invalidate the memory area occupied by buffer */ -invalidate_dcache_range (((uint32_t )buffer & ~31 ), - ((uint32_t )buffer & ~31 ) +roundup (length,32 )); +/* +* Invalidate the memory area occupied by buffer +* Don't try to fix the buffer alignment, if it isn't properly +* aligned it's upper layer's fault so let
invalidate_dcache_range()drivers/usb/host/ehci-hcd.c ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, · line 398
Quoted 7 lines
drivers/usb/host/ehci-hcd.c +7
-0+* vow about it. But we have to fix the length as it's actual +* transfer length and can be unaligned. This is potentially +* dangerous operation, it's responsibility of the calling +* code to make sure enough space is reserved. +*/ +invalidate_dcache_range ((uint32_t )buffer, +ALIGN_END_ADDR (u8, buffer, length));
Quoted 2 lines
We shouldn't use
ALIGN_END_ADDRhere. This can lead to strange results on systems withARCH_DMA_MINALIGN< 32.
Good point, ALIGN_END_ADDR should align it to max(32, length) ?
Quoted 1 line
Regards, Ilya.
Best regards,
Marek Vasut
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Marek,
Quoted 11 lines · Marek Vasut
Quoted 6 lines
drivers/usb/host/ehci-hcd.c ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, · line 398
Quoted 3 lines
drivers/usb/host/ehci-hcd.c +2
-0+invalidate_dcache_range ((uint32_t )buffer, +ALIGN_END_ADDR (u8, buffer, length));We shouldn't use
ALIGN_END_ADDRhere. This can lead to strange results on systems withARCH_DMA_MINALIGN< 32.Good point,
ALIGN_END_ADDRshould align it tomax(32, length)?Hm.. no, actually we should align buffer length to
ARCH_DMA_MINALIGN.
Regards, Ilya.
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
In reply to Marek VasutHi,
drivers/usb/host/ehci-hcd.c static int · line 215
Quoted 9 lines · Marek Vasut
drivers/usb/host/ehci-hcd.c +1
-2@@ -207,8 +210,8 @@ static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) { - static struct QH qh __attribute__((aligned(32))); - static struct qTD qtd[3] __attribute__((aligned (32))); + ALLOC_CACHE_ALIGN_BUFFER(struct QH, qh, 1);
Somehow this doesn't work being allocated on stack... I assumed that this was declared as static just to use __attribute__((aligned))... but it seems that current code doesn't like qh address being changed (I'm getting "Timed out on TD" messages). Any ideas? Changing it to DEFINE_... seems to help but it looks like hiding another bug.
Regards, Ilya.
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Ilya Yanok,
Quoted 11 lines
Hi,
Quoted 8 lines · Marek Vasut
(quoted diff) +0
-0@@ -207,8 +210,8 @@ static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req)
Quoted 8 lines
drivers/usb/host/ehci-hcd.c static int · line 213
Quoted 5 lines
drivers/usb/host/ehci-hcd.c +1
-2{ - static struct QH qh __attribute__((aligned(32))); - static struct qTD qtd[3] __attribute__((aligned (32))); + ALLOC_CACHE_ALIGN_BUFFER(struct QH, qh, 1);Somehow this doesn't work being allocated on stack... I assumed that this was declared as static just to use __attribute__((aligned))...
Not really ... but then, we have indeed a problem here. It was probably declared static to preserve the contents of these variables across the the calls of this function. Sigh, the USB code is really bloody :-/
Ilya, can you try pulling these out of the function?
Quoted 6 lines
but it seems
that current code doesn't like qh address being changed (I'm getting "Timed out on TD" messages). Any ideas? Changing it toDEFINE_... seems to help but it looks like hiding another bug.Regards, Ilya.
Best regards,
Marek Vasut
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Marek,
Quoted 17 lines · Marek Vasut
Quoted 8 lines
Quoted 8 lines
(quoted diff) +0
-0@@ -207,8 +210,8 @@ static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req)Quoted 8 lines
drivers/usb/host/ehci-hcd.c static int · line 213
Quoted 5 lines
drivers/usb/host/ehci-hcd.c +1
-2{ - static struct QH qh __attribute__((aligned(32))); - static struct qTD qtd[3] __attribute__((aligned (32))); + ALLOC_CACHE_ALIGN_BUFFER(struct QH, qh, 1);Somehow this doesn't work being allocated on stack... I assumed that this was declared as static just to use __attribute__((aligned))...
Quoted 6 lines
Not really ... but then, we have indeed a problem here. It was probably declared
static to preserve the contents of these variables across the the calls of this
function. Sigh, the USB code is really bloody :-/
Hm.. no, I don't think it's about contents... Look, there are memset() calls straight in the beginning of the function. It looks like it's about qh address: I tried debugging it a bit and it seems to work until qh has the same address and break when the address eventually changes.
Quoted 2 lines
Ilya, can you try pulling these out of the function?
I can but what for? Are there any differences (except for scope) declaring statics inside or outside function? As I said declaring qh static (with DEFINE_CACHE_ALIGN_BUFFER) works but...
Regards, Ilya.
PATCH 2/2 ehci-hcd.c, musb_core, usb.h: Add USB_DMA_MINALIGN define for cache alignment
Dear Ilya Yanok,
Quoted 26 lines
Dear Marek,
Quoted 17 lines · Marek Vasut
Quoted 8 lines
Quoted 8 lines
(quoted diff) +0
-0@@ -207,8 +210,8 @@ static int ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req)Quoted 8 lines
drivers/usb/host/ehci-hcd.c static int · line 213
Quoted 5 lines
drivers/usb/host/ehci-hcd.c +1
-2{ - static struct QH qh __attribute__((aligned(32))); - static struct qTD qtd[3] __attribute__((aligned (32))); + ALLOC_CACHE_ALIGN_BUFFER(struct QH, qh, 1);Somehow this doesn't work being allocated on stack... I assumed that this was declared as static just to use __attribute__((aligned))...
Quoted 5 lines
Not really ... but then, we have indeed a problem here. It was probably declared
static to preserve the contents of these variables across the the calls of this
function. Sigh, the USB code is really bloody :-/
Quoted 4 lines
Hm.. no, I don't think it's about contents... Look, there are
memset()calls straight in the beginning of the function. It looks like it's about qh address: I tried debugging it a bit and it seems to work until qh has the same address and break when the address eventually changes.
I see, stupid me. So it's only the address? And I take it the controller doesn't use those after it leaves the function, right (maybe that might be it) ?
Quoted 7 lines
Quoted 1 line
Ilya, can you try pulling these out of the function?
I can but what for? Are there any differences (except for scope) declaring statics inside or outside function? As I said declaring qh static (with
DEFINE_CACHE_ALIGN_BUFFER) works but...Regards, Ilya.
Best regards,
Marek Vasut
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
In reply to Marek VasutHi Marek,
Quoted 7 lines · Marek Vasut
This is the out-of-function-scope counterpart of
ALLOC_CACHE_ALIGN_BUFFER.(quoted diff) +2
-0+#define DEFINE_CACHE_ALIGN_BUFFER(type, name, size) \ + static char __##name[roundup(size * sizeof(type),
ARCH_DMA_MINALIGN)] \
+__aligned(ARCH_DMA_MINALIGN); \
We need linux/compiler.h (not included from common.h) for __aligned.
Regards, Ilya.
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
Dear Ilya Yanok,
Quoted 11 lines
Hi Marek,
Quoted 6 lines · Marek Vasut
This is the out-of-function-scope counterpart of
ALLOC_CACHE_ALIGN_BUFFER.(quoted diff) +2
-0+#define DEFINE_CACHE_ALIGN_BUFFER(type, name, size) \ + static char __##name[roundup(size * sizeof(type),
ARCH_DMA_MINALIGN)] \
+__aligned(ARCH_DMA_MINALIGN); \We need
linux/compiler.h(not included fromcommon.h) for__aligned.
Correct, but is it a good idea to include it in common.h ? Ilya, can you re-do this patchset and repost?
Quoted 1 line
Regards, Ilya.
Best regards,
Marek Vasut
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
In reply to Marek Vasutinclude/common.h int cpu_release(int nr, int argc, char * const argv[]); · line 977
Quoted 10 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
include/common.h +10
-0+/* +* DEFINE_CACHE_ALIGN_BUFFER() is similar to ALLOC_CACHE_ALIGN_BUFFER, but it's +* purpose is to allow allocating aligned buffers outside of function scope. +* Usage of this macro shall be avoided or used with extreme care! +*/ +#define DEFINE_CACHE_ALIGN_BUFFER (type, name, size) \ + static char __##name[roundup(size * sizeof(type), ARCH_DMA_MINALIGN)] \ + __aligned(ARCH_DMA_MINALIGN); \ + \ + static type *name = (type *)__##name;
how is this any different from doing:
static __u8 foo[1234] __aligned(ARCH_DMA_MINALIGN);
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/017e9eec/attachment.pgp>
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
Dear Mike Frysinger,
Quoted 7 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
Quoted 6 lines
+/*
+ *DEFINE_CACHE_ALIGN_BUFFER()is similar toALLOC_CACHE_ALIGN_BUFFER, but it's + * purpose is to allow allocating aligned buffers outside of function scope. + * Usage of this macro shall be avoided or used with extreme care! + */
+#defineDEFINE_CACHE_ALIGN_BUFFER(type, name, size)
\
Quoted 8 lines
include/common.h int cpu_release(int nr, int argc, char * const argv[]); · line 977
Quoted 4 lines
include/common.h +4
-0+ static char __##name[roundup(size * sizeof(type), ARCH_DMA_MINALIGN)] \ + __aligned(ARCH_DMA_MINALIGN); \ + \ + static type *name = (type *)__##name;how is this any different from doing:
static __u8 foo[1234] __aligned(ARCH_DMA_MINALIGN);-mike
Does __aligned() align both start of the buffer downwards and end of it upwards ?
Best regards,
Marek Vasut
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
Quoted 15 lines · On Friday 20 July 2012 07:31:47 Marek Vasut wrote:
Dear Mike Frysinger,
Quoted 12 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
Review
Quoted 9 lines
+/*
DEFINE_CACHE_ALIGN_BUFFER()is similar toALLOC_CACHE_ALIGN_BUFFER, but it's purpose is to allow allocating aligned buffers outside of function scope. Usage of this macro shall be avoided or used with extreme care! */(quoted diff) +4
-0+#define DEFINE_CACHE_ALIGN_BUFFER(type, name, size) + static char __##name[roundup(size * sizeof(type), ARCH_DMA_MINALIGN)] + __aligned(ARCH_DMA_MINALIGN); + static type *name = (type *)__##name;how is this any different from doing:
Quoted 1 line
static __u8 foo[1234] __aligned(ARCH_DMA_MINALIGN);
Quoted 2 lines
Does
__aligned()align both start of the buffer downwards and end of it upwards ?
it guarantees the start is aligned. i don't believe it does any tail padding.
that said, you've added just 1 consumer, but it uses in function scope, so i don't see why you had to define a new helper in the first place. the existing one would work fine shouldn't it ?
you should probably add a const to the 2nd part so gcc is more likely to optimize away the storage:
static type * const name = (type *)__##name;
otherwise older gcc versions will create a pointer to go through rather than having things directly access the buffer.
w/out const:
$ readelf -s a.out | grep foo
11: 00000000004005d0 8 OBJECT LOCAL DEFAULT 13 foo.1592
12: 0000000000402080 96 OBJECT LOCAL DEFAULT 25 __foo.1591
w/const:
$ readelf -s a.out | grep foo
11: 0000000000402080 96 OBJECT LOCAL DEFAULT 25 __foo.1591
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/83b5b67c/attachment.pgp>PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Quoted 18 lines · Mike Frysinger
Quoted 14 lines · On Friday 20 July 2012 07:31:47 Marek Vasut wrote:
Dear Mike Frysinger,
Quoted 12 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
Quoted 8 lines
+/*
DEFINE_CACHE_ALIGN_BUFFER()is similar toALLOC_CACHE_ALIGN_BUFFER, but it's purpose is to allow allocating aligned buffers outside of function scope. Usage of this macro shall be avoided or used with extreme care! */
+#defineDEFINE_CACHE_ALIGN_BUFFER(type, name, size)+ static
char __##name[roundup(size * sizeof(type),ARCH_DMA_MINALIGN)] +__aligned(ARCH_DMA_MINALIGN); +
static type *name = (type *)__##name;how is this any different from doing: static
__u8foo[1234]__aligned(ARCH_DMA_MINALIGN);Quoted 2 lines
Does
__aligned()align both start of the buffer downwards and end of it upwards ?
Quoted 6 lines
it guarantees the start is aligned. i don't believe it does any tail padding.
that said, you've added just 1 consumer, but it uses in function scope, so i don't see why you had to define a new helper in the first place. the existing one would work fine shouldn't it ?
The rough outline of the problems are:
- - We need to have buffers that are multiple of cache size, for clearing.
- - Today we know ehci-hcd had a problem. We also know other drivers / layers have problems, but they aren't as readily breakable.
That's why we put the macro in <common.h> rather than a USB header.
- --
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQIcBAEBAgAGBQJQCdKoAAoJENk4IS6UOR1WuzUP/0ndUzaq6U2/8X8E7VIhLqAV AQ+5rmJy5seJAhhvzRLbNgYv7KrLJRayMd4bj4DT8WAmAyUDo1BPvIcKNuQ8Il3M un3Kjo9+qXusfyvbs1V2wOaXL1pmwcOSQe4n+/8xKlmJ3Jh9v1AIBoXIJQqXPrcL zhaN0ilxTcLeblFWVzXSOWPAWo4ufJZ1cd43lGXxtjW890GEUCRTNXod9Bpivi2P ShycGvEcvo80mR7xGKMjZYl9Zf5OQ5QP0Xcvul7X4rjGepEuOsn941wE0zrP1I+s zXfruOklqWBckiP+aBprX2lzsaBUE33hHZidfPtvuB9rTFk735snaDcrZsL/5K25 17Bczpqqb6RXP1yb/tpc1hWkzpfCZ+eqpg2pN8bIp0P8XZ5apMTvq7L9IMG90lN2 FPwOC2VH9gnOK34Est/iTkp6QnW15r/ZayD9DMBUoxelhx38VJHR8OVyu56QXk2K 10zb6lwKQ3dE8u24ki2TybycVgPVoOq35vUjMw7TWZwiwXSBwgcfHMRukpTSdHA6 wNzw+VsurehKdkqRBeG5tOeOf0tcFrKfg1tfyDQqlBJUn9E6Usj43IXfF23DOQ11 VMcMeizuHP6oTmBk571XrgOKczCaUej1UIrLhnfpXNmFsQ7YsIi9PlQcndFiMBLC yo+rfRjqLqrPxJdrP5h4
=alD6
-----END PGP SIGNATURE-----
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
Quoted 27 lines · On Friday 20 July 2012 17:50:33 Tom Rini wrote:
Quoted 19 lines · Mike Frysinger
Quoted 15 lines · On Friday 20 July 2012 07:31:47 Marek Vasut wrote:
Dear Mike Frysinger,
Quoted 12 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
Quoted 8 lines
+/*
DEFINE_CACHE_ALIGN_BUFFER()is similar toALLOC_CACHE_ALIGN_BUFFER, but it's purpose is to allow allocating aligned buffers outside of function scope. Usage of this macro shall be avoided or used with extreme care! */
+#defineDEFINE_CACHE_ALIGN_BUFFER(type, name, size)+ static
char __##name[roundup(size * sizeof(type),ARCH_DMA_MINALIGN)] +__aligned(ARCH_DMA_MINALIGN); +
static type *name = (type *)__##name;how is this any different from doing: static
__u8foo[1234]__aligned(ARCH_DMA_MINALIGN);Quoted 2 lines
Does
__aligned()align both start of the buffer downwards and end of it upwards ?Quoted 6 lines
it guarantees the start is aligned. i don't believe it does any tail padding.
that said, you've added just 1 consumer, but it uses in function scope, so i don't see why you had to define a new helper in the first place. the existing one would work fine shouldn't it ?
Quoted 6 lines
The rough outline of the problems are:
- We need to have buffers that are multiple of cache size, for clearing.
- Today we know ehci-hcd had a problem. We also know other drivers / layers have problems, but they aren't as readily breakable.That's why we put the macro in <
common.h> rather than a USB header.
that wasn't the question. no one in the tree needs the new macro at all, regardless of what header it lives in. i guess the answer is that some code in the future (which hasn't been merged) might use it.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120721/18a27507/attachment.pgp>
PATCH 1/2 common.h: Introduce DEFINE_CACHE_ALIGN_BUFFER
Quoted 33 lines · Mike Frysinger
Quoted 32 lines · On Friday 20 July 2012 17:50:33 Tom Rini wrote:
Quoted 19 lines · Mike Frysinger
Quoted 15 lines · On Friday 20 July 2012 07:31:47 Marek Vasut wrote:
Dear Mike Frysinger,
Quoted 12 lines · On Saturday 07 July 2012 23:08:14 Marek Vasut wrote:
Quoted 8 lines
+/*
DEFINE_CACHE_ALIGN_BUFFER()is similar toALLOC_CACHE_ALIGN_BUFFER, but it's purpose is to allow allocating aligned buffers outside of function scope. Usage of this macro shall be avoided or used with extreme care! */
+#defineDEFINE_CACHE_ALIGN_BUFFER(type, name, size)+ static
char __##name[roundup(size * sizeof(type),ARCH_DMA_MINALIGN)] +__aligned(ARCH_DMA_MINALIGN); +
static type *name = (type *)__##name;how is this any different from doing: static
__u8foo[1234]__aligned(ARCH_DMA_MINALIGN);Quoted 2 lines
Does
__aligned()align both start of the buffer downwards and end of it upwards ?Quoted 6 lines
it guarantees the start is aligned. i don't believe it does any tail padding.
that said, you've added just 1 consumer, but it uses in function scope, so i don't see why you had to define a new helper in the first place. the existing one would work fine shouldn't it ?
The rough outline of the problems are:
- We need to have buffers that are multiple of cache size, for clearing.
- Today we know ehci-hcd had a problem. We also know other drivers / layers have problems, but they aren't as readily breakable.
Quoted 5 lines
Quoted 1 line
That's why we put the macro in <
common.h> rather than a USB header.that wasn't the question. no one in the tree needs the new macro at all, regardless of what header it lives in. i guess the answer is that some code in the future (which hasn't been merged) might use it.
Er, between drivers/usb/host/ehci-hcd.c and drivers/usb/eth/smsc95xx.c the three new macros are used today.
Signature · 1 line
Tom