linux-mips
[Top] [All Lists]

[PATCH 3.11 206/208] MIPS: DMA: For BMIPS5000 cores flush region just li

To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com
Subject: [PATCH 3.11 206/208] MIPS: DMA: For BMIPS5000 cores flush region just like non-coherent R10000
From: Luis Henriques <luis.henriques@canonical.com>
Date: Thu, 19 Dec 2013 11:55:04 +0000
Cc: Jim Quinlan <jim2101024@gmail.com>, linux-mips@linux-mips.org, cernekee@gmail.com, Ralf Baechle <ralf@linux-mips.org>, Luis Henriques <luis.henriques@canonical.com>
In-reply-to: <1387454106-19326-1-git-send-email-luis.henriques@canonical.com>
List-archive: <http://www.linux-mips.org/archives/linux-mips/>
List-help: <mailto:ecartis@linux-mips.org?Subject=help>
List-id: linux-mips <linux-mips.eddie.linux-mips.org>
List-owner: <mailto:ralf@linux-mips.org>
List-post: <mailto:linux-mips@linux-mips.org>
List-software: Ecartis version 1.0.0
List-subscribe: <mailto:ecartis@linux-mips.org?subject=subscribe%20linux-mips>
List-unsubscribe: <mailto:ecartis@linux-mips.org?subject=unsubscribe%20linux-mips>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <1387454106-19326-1-git-send-email-luis.henriques@canonical.com>
Sender: linux-mips-bounce@linux-mips.org
3.11.10.2 -stable review patch.  If anyone has any objections, please let me 
know.

------------------

From: Jim Quinlan <jim2101024@gmail.com>

commit f86f55d3ad21b21b736bdeb29bee0f0937b77138 upstream.

The BMIPS5000 (Zephyr) processor utilizes instruction speculation. A
stale misprediction address in either the JTB or the CRS may trigger
a prefetch inside a region that is currently being used by a DMA engine,
which is not IO-coherent.  This prefetch will fetch a line into the
scache, and that line will soon become stale (ie wrong) during/after the
DMA.  Mayhem ensues.

In dma-default.c, the r10000 is handled as a special case in the same way
that we want to handle Zephyr.  So we generalize the exception cases into
a function, and include Zephyr as one of the processors that needs this
special care.

Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/5776/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
---
 arch/mips/mm/dma-default.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index aaccf1c..468f7f9 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -50,16 +50,20 @@ static inline struct page *dma_addr_to_page(struct device 
*dev,
 }
 
 /*
+ * The affected CPUs below in 'cpu_needs_post_dma_flush()' can
+ * speculatively fill random cachelines with stale data at any time,
+ * requiring an extra flush post-DMA.
+ *
  * Warning on the terminology - Linux calls an uncached area coherent;
  * MIPS terminology calls memory areas with hardware maintained coherency
  * coherent.
  */
-
-static inline int cpu_is_noncoherent_r10000(struct device *dev)
+static inline int cpu_needs_post_dma_flush(struct device *dev)
 {
        return !plat_device_is_coherent(dev) &&
               (current_cpu_type() == CPU_R10000 ||
-              current_cpu_type() == CPU_R12000);
+               current_cpu_type() == CPU_R12000 ||
+               current_cpu_type() == CPU_BMIPS5000);
 }
 
 static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
@@ -230,7 +234,7 @@ static inline void __dma_sync(struct page *page,
 static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
        size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
 {
-       if (cpu_is_noncoherent_r10000(dev))
+       if (cpu_needs_post_dma_flush(dev))
                __dma_sync(dma_addr_to_page(dev, dma_addr),
                           dma_addr & ~PAGE_MASK, size, direction);
 
@@ -284,7 +288,7 @@ static void mips_dma_unmap_sg(struct device *dev, struct 
scatterlist *sg,
 static void mips_dma_sync_single_for_cpu(struct device *dev,
        dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-       if (cpu_is_noncoherent_r10000(dev))
+       if (cpu_needs_post_dma_flush(dev))
                __dma_sync(dma_addr_to_page(dev, dma_handle),
                           dma_handle & ~PAGE_MASK, size, direction);
 }
@@ -305,7 +309,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
 
        /* Make sure that gcc doesn't leave the empty loop body.  */
        for (i = 0; i < nelems; i++, sg++) {
-               if (cpu_is_noncoherent_r10000(dev))
+               if (cpu_needs_post_dma_flush(dev))
                        __dma_sync(sg_page(sg), sg->offset, sg->length,
                                   direction);
        }
-- 
1.8.3.2


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH 3.11 206/208] MIPS: DMA: For BMIPS5000 cores flush region just like non-coherent R10000, Luis Henriques <=