Skip to content

Commit f86f55d

Browse files
jim2101024ralfbaechle
authored andcommitted
MIPS: DMA: For BMIPS5000 cores flush region just like non-coherent R10000
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>
1 parent 2a153f1 commit f86f55d

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

arch/mips/mm/dma-default.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,20 @@ static inline struct page *dma_addr_to_page(struct device *dev,
5050
}
5151

5252
/*
53+
* The affected CPUs below in 'cpu_needs_post_dma_flush()' can
54+
* speculatively fill random cachelines with stale data at any time,
55+
* requiring an extra flush post-DMA.
56+
*
5357
* Warning on the terminology - Linux calls an uncached area coherent;
5458
* MIPS terminology calls memory areas with hardware maintained coherency
5559
* coherent.
5660
*/
57-
58-
static inline int cpu_is_noncoherent_r10000(struct device *dev)
61+
static inline int cpu_needs_post_dma_flush(struct device *dev)
5962
{
6063
return !plat_device_is_coherent(dev) &&
6164
(current_cpu_type() == CPU_R10000 ||
62-
current_cpu_type() == CPU_R12000);
65+
current_cpu_type() == CPU_R12000 ||
66+
current_cpu_type() == CPU_BMIPS5000);
6367
}
6468

6569
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,
230234
static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
231235
size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
232236
{
233-
if (cpu_is_noncoherent_r10000(dev))
237+
if (cpu_needs_post_dma_flush(dev))
234238
__dma_sync(dma_addr_to_page(dev, dma_addr),
235239
dma_addr & ~PAGE_MASK, size, direction);
236240

@@ -284,7 +288,7 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
284288
static void mips_dma_sync_single_for_cpu(struct device *dev,
285289
dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
286290
{
287-
if (cpu_is_noncoherent_r10000(dev))
291+
if (cpu_needs_post_dma_flush(dev))
288292
__dma_sync(dma_addr_to_page(dev, dma_handle),
289293
dma_handle & ~PAGE_MASK, size, direction);
290294
}
@@ -305,7 +309,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
305309

306310
/* Make sure that gcc doesn't leave the empty loop body. */
307311
for (i = 0; i < nelems; i++, sg++) {
308-
if (cpu_is_noncoherent_r10000(dev))
312+
if (cpu_needs_post_dma_flush(dev))
309313
__dma_sync(sg_page(sg), sg->offset, sg->length,
310314
direction);
311315
}

0 commit comments

Comments
 (0)