Skip to content

Commit 20d3306

Browse files
paulburtonralfbaechle
authored andcommitted
MIPS: Support per-device DMA coherence
On some MIPS systems, a subset of devices may have DMA coherent with CPU caches. For example in systems including a MIPS I/O Coherence Unit (IOCU), some devices may be connected to that IOCU whilst others are not. Prior to this patch, we have a plat_device_is_coherent() function but no implementation which does anything besides return a global true or false, optionally chosen at runtime. For devices such as those described above this is insufficient. Fix this by tracking DMA coherence on a per-device basis with a dma_coherent field in struct dev_archdata. Setting this from arch_setup_dma_ops() takes care of devices which set the dma-coherent property via device tree, and any PCI devices beneath a bridge described in DT, automatically. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14349/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
1 parent cfa93fb commit 20d3306

File tree

7 files changed

+31
-2
lines changed

7 files changed

+31
-2
lines changed

arch/mips/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,10 @@ config DMA_MAYBE_COHERENT
10991099
select DMA_NONCOHERENT
11001100
bool
11011101

1102+
config DMA_PERDEV_COHERENT
1103+
bool
1104+
select DMA_MAYBE_COHERENT
1105+
11021106
config DMA_COHERENT
11031107
bool
11041108

arch/mips/include/asm/device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ struct dma_map_ops;
1111
struct dev_archdata {
1212
/* DMA operations on that device */
1313
struct dma_map_ops *dma_ops;
14+
15+
#ifdef CONFIG_DMA_PERDEV_COHERENT
16+
/* Non-zero if DMA is coherent with CPU caches */
17+
bool dma_coherent;
18+
#endif
1419
};
1520

1621
struct pdev_archdata {

arch/mips/include/asm/dma-coherence.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ enum coherent_io_user_state {
1515
IO_COHERENCE_DISABLED,
1616
};
1717

18-
#ifdef CONFIG_DMA_MAYBE_COHERENT
18+
#if defined(CONFIG_DMA_PERDEV_COHERENT)
19+
/* Don't provide (hw_)coherentio to avoid misuse */
20+
#elif defined(CONFIG_DMA_MAYBE_COHERENT)
1921
extern enum coherent_io_user_state coherentio;
2022
extern int hw_coherentio;
2123
#else

arch/mips/include/asm/dma-mapping.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@ static inline void dma_mark_clean(void *addr, size_t size) {}
3232
extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
3333
enum dma_data_direction direction);
3434

35+
#define arch_setup_dma_ops arch_setup_dma_ops
36+
static inline void arch_setup_dma_ops(struct device *dev, u64 dma_base,
37+
u64 size, const struct iommu_ops *iommu,
38+
bool coherent)
39+
{
40+
#ifdef CONFIG_DMA_PERDEV_COHERENT
41+
dev->archdata.dma_coherent = coherent;
42+
#endif
43+
}
44+
3545
#endif /* _ASM_DMA_MAPPING_H */

arch/mips/include/asm/mach-generic/dma-coherence.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
4949

5050
static inline int plat_device_is_coherent(struct device *dev)
5151
{
52+
#ifdef CONFIG_DMA_PERDEV_COHERENT
53+
return dev->archdata.dma_coherent;
54+
#else
5255
switch (coherentio) {
5356
default:
5457
case IO_COHERENCE_DEFAULT:
@@ -58,6 +61,7 @@ static inline int plat_device_is_coherent(struct device *dev)
5861
case IO_COHERENCE_DISABLED:
5962
return 0;
6063
}
64+
#endif
6165
}
6266

6367
#ifndef plat_post_dma_flush

arch/mips/mm/c-r4k.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,8 +1935,12 @@ void r4k_cache_init(void)
19351935
__local_flush_icache_user_range = local_r4k_flush_icache_user_range;
19361936

19371937
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
1938+
# if defined(CONFIG_DMA_PERDEV_COHERENT)
1939+
if (0) {
1940+
# else
19381941
if ((coherentio == IO_COHERENCE_ENABLED) ||
19391942
((coherentio == IO_COHERENCE_DEFAULT) && hw_coherentio)) {
1943+
# endif
19401944
_dma_cache_wback_inv = (void *)cache_noop;
19411945
_dma_cache_wback = (void *)cache_noop;
19421946
_dma_cache_inv = (void *)cache_noop;

arch/mips/mm/dma-default.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
#include <dma-coherence.h>
2626

27-
#ifdef CONFIG_DMA_MAYBE_COHERENT
27+
#if defined(CONFIG_DMA_MAYBE_COHERENT) && !defined(CONFIG_DMA_PERDEV_COHERENT)
2828
/* User defined DMA coherency from command line. */
2929
enum coherent_io_user_state coherentio = IO_COHERENCE_DEFAULT;
3030
EXPORT_SYMBOL_GPL(coherentio);

0 commit comments

Comments
 (0)