* [PATCH 1/3] dma: use dma/cpu conversions correctly in dma_map/unmap_single
2023-03-13 10:53 [PATCH 0/3] MIPS: dma-default: fix dma_sync_single_for_* Denis Orlov
@ 2023-03-13 10:53 ` Denis Orlov
2023-03-13 10:53 ` [PATCH 2/3] MIPS: dma-default: use virtual addresses when flushing caches Denis Orlov
2023-03-13 10:53 ` [PATCH 3/3] MIPS: dma-default: do not flush caches in dma_sync_single_* excessively Denis Orlov
2 siblings, 0 replies; 4+ messages in thread
From: Denis Orlov @ 2023-03-13 10:53 UTC (permalink / raw)
To: barebox; +Cc: Denis Orlov
We should not treat dma handles as if they correspond one-to-one to the
virtual addresses in common code. So make sure that dma handles are
properly passed to the dma_sync_single_for_* functions. Otherwise, it
just doesn't make much sense, as dma_sync funcs will receive proper dma
handles when called directly, and a virtual address treated as one when
called from dma_map funcs.
Signed-off-by: Denis Orlov <denorl2009@gmail.com>
---
drivers/dma/map.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/map.c b/drivers/dma/map.c
index 114c0f7db3..fea04c38a3 100644
--- a/drivers/dma/map.c
+++ b/drivers/dma/map.c
@@ -23,17 +23,15 @@ static inline void *dma_to_cpu(struct device *dev, dma_addr_t addr)
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
- unsigned long addr = (unsigned long)ptr;
+ dma_addr_t ret = cpu_to_dma(dev, ptr);
- dma_sync_single_for_device(addr, size, dir);
+ dma_sync_single_for_device(ret, size, dir);
- return cpu_to_dma(dev, ptr);
+ return ret;
}
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
- unsigned long addr = (unsigned long)dma_to_cpu(dev, dma_addr);
-
- dma_sync_single_for_cpu(addr, size, dir);
+ dma_sync_single_for_cpu(dma_addr, size, dir);
}
--
2.30.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/3] MIPS: dma-default: use virtual addresses when flushing caches
2023-03-13 10:53 [PATCH 0/3] MIPS: dma-default: fix dma_sync_single_for_* Denis Orlov
2023-03-13 10:53 ` [PATCH 1/3] dma: use dma/cpu conversions correctly in dma_map/unmap_single Denis Orlov
@ 2023-03-13 10:53 ` Denis Orlov
2023-03-13 10:53 ` [PATCH 3/3] MIPS: dma-default: do not flush caches in dma_sync_single_* excessively Denis Orlov
2 siblings, 0 replies; 4+ messages in thread
From: Denis Orlov @ 2023-03-13 10:53 UTC (permalink / raw)
To: barebox; +Cc: Denis Orlov
Cache flushing functions expect virtual addresses, so make sure those
are properly converted from the physical ones in dma_sync_single_for_*.
QEMU doesn't care as it ignores cache instructions, but without such
change this code would result in TLB exceptions on real hardware.
Signed-off-by: Denis Orlov <denorl2009@gmail.com>
---
arch/mips/lib/dma-default.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/mips/lib/dma-default.c b/arch/mips/lib/dma-default.c
index 48176e5d28..f6c750b8ac 100644
--- a/arch/mips/lib/dma-default.c
+++ b/arch/mips/lib/dma-default.c
@@ -30,11 +30,15 @@ static inline void __dma_sync_mips(unsigned long addr, size_t size,
void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
- __dma_sync_mips(address, size, dir);
+ unsigned long virt = (unsigned long)phys_to_virt(address);
+
+ __dma_sync_mips(virt, size, dir);
}
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
- __dma_sync_mips(address, size, dir);
+ unsigned long virt = (unsigned long)phys_to_virt(address);
+
+ __dma_sync_mips(virt, size, dir);
}
--
2.30.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 3/3] MIPS: dma-default: do not flush caches in dma_sync_single_* excessively
2023-03-13 10:53 [PATCH 0/3] MIPS: dma-default: fix dma_sync_single_for_* Denis Orlov
2023-03-13 10:53 ` [PATCH 1/3] dma: use dma/cpu conversions correctly in dma_map/unmap_single Denis Orlov
2023-03-13 10:53 ` [PATCH 2/3] MIPS: dma-default: use virtual addresses when flushing caches Denis Orlov
@ 2023-03-13 10:53 ` Denis Orlov
2 siblings, 0 replies; 4+ messages in thread
From: Denis Orlov @ 2023-03-13 10:53 UTC (permalink / raw)
To: barebox; +Cc: Denis Orlov
Change the logic to be different depending on whether we are doing
synchronization for a cpu or a device. This gets rid of unnecessary
cache flushing in some cases. While at it, also simplify code a bit,
collapsing two cases with the same code in a switch statement in
dma_sync_single_for_device().
The functional change itself is taken from Linux commit
'MIPS: make dma_sync_*_for_cpu a little less overzealous'
(hash: cbf1449ba5aec9cf4c68b69f899391a8d42e9b8f).
Signed-off-by: Denis Orlov <denorl2009@gmail.com>
---
arch/mips/lib/dma-default.c | 36 +++++++++++++++++-------------------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/arch/mips/lib/dma-default.c b/arch/mips/lib/dma-default.c
index f6c750b8ac..0347d7a7db 100644
--- a/arch/mips/lib/dma-default.c
+++ b/arch/mips/lib/dma-default.c
@@ -6,39 +6,37 @@
#include <dma.h>
#include <asm/io.h>
-static inline void __dma_sync_mips(unsigned long addr, size_t size,
- enum dma_data_direction direction)
+void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
+ enum dma_data_direction dir)
{
- switch (direction) {
+ unsigned long virt = (unsigned long)phys_to_virt(address);
+
+ switch (dir) {
case DMA_TO_DEVICE:
- dma_flush_range(addr, addr + size);
break;
-
case DMA_FROM_DEVICE:
- dma_inv_range(addr, addr + size);
- break;
-
case DMA_BIDIRECTIONAL:
- dma_flush_range(addr, addr + size);
+ dma_inv_range(virt, virt + size);
break;
-
default:
BUG();
}
}
-void dma_sync_single_for_cpu(dma_addr_t address, size_t size,
- enum dma_data_direction dir)
-{
- unsigned long virt = (unsigned long)phys_to_virt(address);
-
- __dma_sync_mips(virt, size, dir);
-}
-
void dma_sync_single_for_device(dma_addr_t address, size_t size,
enum dma_data_direction dir)
{
unsigned long virt = (unsigned long)phys_to_virt(address);
- __dma_sync_mips(virt, size, dir);
+ switch (dir) {
+ case DMA_FROM_DEVICE:
+ dma_inv_range(virt, virt + size);
+ break;
+ case DMA_TO_DEVICE:
+ case DMA_BIDIRECTIONAL:
+ dma_flush_range(virt, virt + size);
+ break;
+ default:
+ BUG();
+ }
}
--
2.30.2
^ permalink raw reply [flat|nested] 4+ messages in thread