Re: [PATCH v3] ad7877: keep dma rx buffers in seperate cache lines

From: David Woodhouse
Date: Wed May 19 2010 - 09:01:03 EST


On Tue, 2010-05-11 at 16:54 -0400, Mike Frysinger wrote:
>
> > kmalloc returns a pointer to a DMA safe buffer. There is no requirement on
> > the x86 hardware that the DMA buffers have to be cache aligned. Cachelines
> > will be invalidated as needed.
>
> so this guarantee is made by the kmalloc() API ? and for arches where
> the cacheline invalidation is handled in software rather than
> hardware, they must declare a min alignment value for kmalloc to be at
> least as big as their cache alignment ?
>
> does the phrase "DMA safe buffer" imply cache alignment ?

Not necessarily. If you have cache-coherent DMA, then there's no need to
align things. You only need cache-alignment when you have
cache-incoherent DMA and have to manage the cache in software. And in
that case, the architecture must set ARCH_KMALLOC_MINALIGN to an
appropriate value so that kmalloc() meets the guarantee.

However, your problem is kind of unrelated to that -- your problem is
actually that you're putting both a DMA buffer _and_ other stuff into
the same kmalloc'd buffer. Don't do that. Instead, allocate your DMA
buffer separately and put a _pointer_ to it into the structure.

Or if you really _must_ include it in your structure, then align to
ARCH_KMALLOC_MINALIGN bytes both before and after the DMA buffer by
adding __attribute__((__aligned__(ARCH_KMALLOC_MINALIGN))) to both the
DMA buffer _and_ the element which follows it in your struct (if any).

Using ____cacheline_aligned wastes a lot of space on the architectures
that don't need it.

Arguably, this __dma_aligned definition should go somewhere generic...

diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 0d2d7e5..ae5d56e 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -151,6 +151,11 @@ enum {
/*
* Non-touchscreen sensors only use single-ended conversions.
*/
+#ifdef ARCH_KMALLOC_MINALIGN
+#define __dma_aligned __attribute__((__aligned__(ARCH_KMALLOC_MINALIGN)))
+#else
+#define __dma_aligned
+#endif

struct ser_req {
u16 reset;
@@ -163,7 +168,7 @@ struct ser_req {
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
- u16 sample ____cacheline_aligned;
+ u16 sample __dma_aligned;
};

struct ad7877 {
@@ -203,7 +208,7 @@ struct ad7877 {
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
- u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
+ u16 conversion_data[AD7877_NR_SENSE] __dma_aligned;
};

static int gpio3;


--
David Woodhouse Open Source Technology Centre
David.Woodhouse@xxxxxxxxx Intel Corporation

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/