diff mbox

[1/3] add dma_coherent_write_sync to DMA API

Message ID 1314826214-22428-2-git-send-email-msalter@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mark Salter Aug. 31, 2011, 9:30 p.m. UTC
On ARMv6/7 DMA-coherent memory is bufferable which means that CPU writes to
coherent memory may still be held in a write buffer for a significant amount
of time. This is largely mitigated by having the MMIO write functions force
a write buffer flush before doing the actual write to the MMIO register. This
forces out previous CPU writes to coherent memory for drivers which write to
a register to inform the device that something was written to memory. However,
this does not mitigate the problem for devices which poll the DMA memory for
changes written by the CPU. One such case was found by ming.lei@canonical.com
in the USB EHCI driver. The EHCI host controller relies at least partly on
polling DMA coherent memory for information from the driver.

This patch adds a dma_coherent_write_sync() function to the DMA API which
drivers can use to explicitly force out data which may otherwise be held up
in a write buffer. It is a no-op unless and architecture provides its own
version or the function and sets ARCH_HAS_DMA_COHERENT_WRITE_SYNC.

Signed-off-by: Mark Salter <msalter@redhat.com>
---
 Documentation/DMA-API-HOWTO.txt |   15 +++++++++++++++
 Documentation/DMA-API.txt       |   12 ++++++++++++
 include/linux/dma-mapping.h     |    6 ++++++
 3 files changed, 33 insertions(+), 0 deletions(-)

Comments

Josh Cartwright Sept. 1, 2011, 2:59 a.m. UTC | #1
On Wed, Aug 31, 2011 at 05:30:12PM -0400, Mark Salter wrote:
> On ARMv6/7 DMA-coherent memory is bufferable which means that CPU writes to
> coherent memory may still be held in a write buffer for a significant amount
> of time. This is largely mitigated by having the MMIO write functions force
> a write buffer flush before doing the actual write to the MMIO register. This
> forces out previous CPU writes to coherent memory for drivers which write to
> a register to inform the device that something was written to memory. However,
> this does not mitigate the problem for devices which poll the DMA memory for
> changes written by the CPU. One such case was found by ming.lei@canonical.com
> in the USB EHCI driver. The EHCI host controller relies at least partly on
> polling DMA coherent memory for information from the driver.
> 
> This patch adds a dma_coherent_write_sync() function to the DMA API which
> drivers can use to explicitly force out data which may otherwise be held up
> in a write buffer. It is a no-op unless and architecture provides its own
> version or the function and sets ARCH_HAS_DMA_COHERENT_WRITE_SYNC.
> 
> Signed-off-by: Mark Salter <msalter@redhat.com>
> ---
>  Documentation/DMA-API-HOWTO.txt |   15 +++++++++++++++
>  Documentation/DMA-API.txt       |   12 ++++++++++++
>  include/linux/dma-mapping.h     |    6 ++++++
>  3 files changed, 33 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
> index a0b6250..8c22b8b 100644
> --- a/Documentation/DMA-API-HOWTO.txt
> +++ b/Documentation/DMA-API-HOWTO.txt
> @@ -400,6 +400,21 @@ Make sure you've called dma_pool_free for all memory allocated
>  from a pool before you destroy the pool. This function may not
>  be called in interrupt context.
>  
> +Some architectures which supporting DMA coherent memory may still have write
> +buffering between the CPU and DMA memory. This buffering may delay CPU writes
> +from reaching coherent memory in a timely manner. These delays in turn can
> +lead lead to dramatic performance issues in certain cases. An architecture

'lead lead' -> 'lead'
Michał Mirosław Sept. 1, 2011, 9:57 a.m. UTC | #2
2011/8/31 Mark Salter <msalter@redhat.com>:
> On ARMv6/7 DMA-coherent memory is bufferable which means that CPU writes to
> coherent memory may still be held in a write buffer for a significant amount
> of time. This is largely mitigated by having the MMIO write functions force
> a write buffer flush before doing the actual write to the MMIO register. This
> forces out previous CPU writes to coherent memory for drivers which write to
> a register to inform the device that something was written to memory. However,
> this does not mitigate the problem for devices which poll the DMA memory for
> changes written by the CPU. One such case was found by ming.lei@canonical.com
> in the USB EHCI driver. The EHCI host controller relies at least partly on
> polling DMA coherent memory for information from the driver.
>
> This patch adds a dma_coherent_write_sync() function to the DMA API which
> drivers can use to explicitly force out data which may otherwise be held up
> in a write buffer. It is a no-op unless and architecture provides its own
> version or the function and sets ARCH_HAS_DMA_COHERENT_WRITE_SYNC.
[...]
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -418,6 +418,18 @@ void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
>        ....
>
>
> +Part Ie - Write buffering to dma-coherent memory
> +------------------------------------------------
> +
> +Some architectures supporting DMA coherent memory may have write
> +buffering between the CPU and DMA memory. This buffering may delay
> +CPU writes from reaching coherent memory in a timely manner.
> +
> +    void
> +    dma_coherent_write_sync()
> +
> +Force any outstanding coherent writes to memory.

This should be merged or referenced in part Ia.

BTW, if there's no time limit on write buffers flushing, or if write
buffers can cause reordering of the writes, then the memory accesses
need to be managed just like non-DMA-coherent memory. So what differs
then in DMA-coherent vs non-DMA-coherent mappings then?

Best Regards,
Micha? Miros?aw
Mark Salter Sept. 1, 2011, 12:36 p.m. UTC | #3
On Thu, 2011-09-01 at 11:57 +0200, Micha? Miros?aw wrote:
> BTW, if there's no time limit on write buffers flushing, or if write
> buffers can cause reordering of the writes, then the memory accesses
> need to be managed just like non-DMA-coherent memory. So what differs
> then in DMA-coherent vs non-DMA-coherent mappings then?

My understanding is that ordering is preserved, but an ARM guy should
probably verify that.

IIUC, the write buffers could hold data indefinitely. As a practical
matter other writes needing to go out to memory will force buffered
data out eventually. Again, this is my understanding which may be
faulty. My feeling is that this extended write buffering makes it
hard to call the dma memory fully coherent, but other limitations on
ARMv7 make the buffering hard to avoid.

--Mark
Catalin Marinas Sept. 6, 2011, 2:30 p.m. UTC | #4
(coming late to this thread due to holidays)

2011/9/1 Mark Salter <msalter@redhat.com>:
> On Thu, 2011-09-01 at 11:57 +0200, Micha? Miros?aw wrote:
>> BTW, if there's no time limit on write buffers flushing, or if write
>> buffers can cause reordering of the writes, then the memory accesses
>> need to be managed just like non-DMA-coherent memory. So what differs
>> then in DMA-coherent vs non-DMA-coherent mappings then?
>
> My understanding is that ordering is preserved, but an ARM guy should
> probably verify that.

On ARMv6 onwards the coherent DMA is Normal Non-cacheable memory and
this is buffered and can be reordered.
diff mbox

Patch

diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
index a0b6250..8c22b8b 100644
--- a/Documentation/DMA-API-HOWTO.txt
+++ b/Documentation/DMA-API-HOWTO.txt
@@ -400,6 +400,21 @@  Make sure you've called dma_pool_free for all memory allocated
 from a pool before you destroy the pool. This function may not
 be called in interrupt context.
 
+Some architectures which supporting DMA coherent memory may still have write
+buffering between the CPU and DMA memory. This buffering may delay CPU writes
+from reaching coherent memory in a timely manner. These delays in turn can
+lead lead to dramatic performance issues in certain cases. An architecture
+may mitigate this problem to a large degree by having a write buffer flush
+implicit in the MMIO functions used to write to device registers. This works
+for the most common cases where a driver needs to write to a register to tell
+a device that something was written to the shared coherent memory. There are
+other cases where the device polls the dma-coherent memory for data written
+by the driver. In such cases, the driver needs to explicity force write buffer
+data to memory by calling:
+
+	dma_coherent_write_sync();
+
+
 			DMA Direction
 
 The interfaces described in subsequent portions of this document
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index fe23269..44d6923 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -418,6 +418,18 @@  void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
 	....
 
 
+Part Ie - Write buffering to dma-coherent memory
+------------------------------------------------
+
+Some architectures supporting DMA coherent memory may have write
+buffering between the CPU and DMA memory. This buffering may delay
+CPU writes from reaching coherent memory in a timely manner.
+
+    void
+    dma_coherent_write_sync()
+
+Force any outstanding coherent writes to memory.
+
 Part II - Advanced dma_ usage
 -----------------------------
 
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 347fdc3..b29d65c 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -154,6 +154,12 @@  dma_mark_declared_memory_occupied(struct device *dev,
 }
 #endif
 
+#ifndef ARCH_HAS_DMA_COHERENT_WRITE_SYNC
+static inline void dma_coherent_write_sync(void)
+{
+}
+#endif
+
 /*
  * Managed DMA API
  */