Renamed patches to keep their original numbering from codelinaro.org Fixed minor bugs and added support for the qca-nss-drv-l2tpv2 module
380 lines
11 KiB
Diff
380 lines
11 KiB
Diff
From da352a66ee871ddba0e1970f029ca17d5b4fd99b Mon Sep 17 00:00:00 2001
|
|
From: Suman Ghosh <quic_sumaghos@quicinc.com>
|
|
Date: Sat, 4 Sep 2021 01:09:20 +0530
|
|
Subject: [PATCH 095/500] arm/arm64: Add new APIs to perform dma cache
|
|
maintenance operation without dsb.
|
|
|
|
Change-Id: I511657af343c8dc668ab7280362b3cdd57579360
|
|
Signed-off-by: Suman Ghosh <quic_sumaghos@quicinc.com>
|
|
Signed-off-by: Tushar Ganatra <quic_tganatra@quicinc.com>
|
|
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
|
|
Signed-off-by: Tushar Ganatra <quic_tganatra@quicinc.com>
|
|
---
|
|
arch/arm/include/asm/cacheflush.h | 11 ++++
|
|
arch/arm/include/asm/glue-cache.h | 3 +
|
|
arch/arm/mm/cache-v7.S | 98 +++++++++++++++++++++++++++--
|
|
arch/arm/mm/proc-syms.c | 3 +
|
|
arch/arm64/include/asm/assembler.h | 39 ++++++++++++
|
|
arch/arm64/include/asm/cacheflush.h | 9 +++
|
|
arch/arm64/mm/cache.S | 58 +++++++++++++++++
|
|
arch/arm64/mm/flush.c | 24 +++++++
|
|
8 files changed, 239 insertions(+), 6 deletions(-)
|
|
|
|
--- a/arch/arm/include/asm/cacheflush.h
|
|
+++ b/arch/arm/include/asm/cacheflush.h
|
|
@@ -130,6 +130,10 @@ struct cpu_cache_fns {
|
|
void (*dma_inv_range)(const void *, const void *);
|
|
void (*dma_clean_range)(const void *, const void *);
|
|
void (*dma_flush_range)(const void *, const void *);
|
|
+
|
|
+ void (*dma_inv_range_no_dsb)(const void *, const void *);
|
|
+ void (*dma_clean_range_no_dsb)(const void *, const void *);
|
|
+ void (*dma_flush_range_no_dsb)(const void *, const void *);
|
|
} __no_randomize_layout;
|
|
|
|
/*
|
|
@@ -158,6 +162,10 @@ extern struct cpu_cache_fns cpu_cache;
|
|
#define dmac_clean_range cpu_cache.dma_clean_range
|
|
#define dmac_flush_range cpu_cache.dma_flush_range
|
|
|
|
+#define dmac_inv_range_no_dsb cpu_cache.dma_inv_range_no_dsb
|
|
+#define dmac_clean_range_no_dsb cpu_cache.dma_clean_range_no_dsb
|
|
+#define dmac_flush_range_no_dsb cpu_cache.dma_flush_range_no_dsb
|
|
+
|
|
#else
|
|
|
|
extern void __cpuc_flush_icache_all(void);
|
|
@@ -178,6 +186,9 @@ extern void __cpuc_flush_dcache_area(voi
|
|
extern void dmac_inv_range(const void *, const void *);
|
|
extern void dmac_clean_range(const void *, const void *);
|
|
extern void dmac_flush_range(const void *, const void *);
|
|
+extern void dmac_inv_range_no_dsb(const void *, const void *);
|
|
+extern void dmac_clean_range_no_dsb(const void *, const void *);
|
|
+extern void dmac_flush_range_no_dsb(const void *, const void *);
|
|
|
|
#endif
|
|
|
|
--- a/arch/arm/include/asm/glue-cache.h
|
|
+++ b/arch/arm/include/asm/glue-cache.h
|
|
@@ -156,8 +156,11 @@ static inline void nop_dma_unmap_area(co
|
|
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
|
|
|
|
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
|
|
+#define dmac_flush_range_no_dsb __glue(_CACHE,_dma_flush_range_no_dsb)
|
|
#define dmac_inv_range __glue(_CACHE, _dma_inv_range)
|
|
+#define dmac_inv_range_no_dsb __glue(_CACHE, _dma_inv_range_no_dsb)
|
|
#define dmac_clean_range __glue(_CACHE, _dma_clean_range)
|
|
+#define dmac_clean_range_no_dsb __glue(_CACHE, _dma_clean_range_no_dsb)
|
|
#endif
|
|
|
|
#endif
|
|
--- a/arch/arm/mm/cache-v7.S
|
|
+++ b/arch/arm/mm/cache-v7.S
|
|
@@ -387,6 +387,42 @@ ENTRY(v7_dma_inv_range)
|
|
ENDPROC(v7_dma_inv_range)
|
|
|
|
/*
|
|
+ * v7_dma_inv_range_no_dsb(start,end)
|
|
+ *
|
|
+ * Invalidate the data cache within the specified region; we will
|
|
+ * be performing a DMA operation in this region and we want to
|
|
+ * purge old data in the cache. This API does not do
|
|
+ * "data synchronization barrier". The caller is responsible to
|
|
+ * do dsb after the transaction.
|
|
+ *
|
|
+ * - start - virtual start address of region
|
|
+ * - end - virtual end address of region
|
|
+ */
|
|
+ENTRY(v7_dma_inv_range_no_dsb)
|
|
+ dcache_line_size r2, r3
|
|
+ sub r3, r2, #1
|
|
+ tst r0, r3
|
|
+ bic r0, r0, r3
|
|
+#ifdef CONFIG_ARM_ERRATA_764369
|
|
+ ALT_SMP(W(dsb))
|
|
+ ALT_UP(W(nop))
|
|
+#endif
|
|
+ mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
|
+ addne r0, r0, r2
|
|
+
|
|
+ tst r1, r3
|
|
+ bic r1, r1, r3
|
|
+ mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line
|
|
+ cmp r0, r1
|
|
+1:
|
|
+ mcrlo p15, 0, r0, c7, c6, 1 @ invalidate D / U line
|
|
+ addlo r0, r0, r2
|
|
+ cmplo r0, r1
|
|
+ blo 1b
|
|
+ ret lr
|
|
+ENDPROC(v7_dma_inv_range_no_dsb)
|
|
+
|
|
+/*
|
|
* v7_dma_clean_range(start,end)
|
|
* - start - virtual start address of region
|
|
* - end - virtual end address of region
|
|
@@ -409,12 +445,16 @@ ENTRY(v7_dma_clean_range)
|
|
ENDPROC(v7_dma_clean_range)
|
|
|
|
/*
|
|
- * v7_dma_flush_range(start,end)
|
|
+ * v7_dma_clean_range_no_dsb(start,end)
|
|
+ *
|
|
+ * This API does not do "data synchronization barrier".
|
|
+ * The caller is responsible to do dsb after the transaction.
|
|
+ *
|
|
* - start - virtual start address of region
|
|
* - end - virtual end address of region
|
|
*/
|
|
-ENTRY(v7_dma_flush_range)
|
|
- dcache_line_size r2, r3
|
|
+ENTRY(v7_dma_clean_range_no_dsb)
|
|
+ dcache_line_size r2, r3
|
|
sub r3, r2, #1
|
|
bic r0, r0, r3
|
|
#ifdef CONFIG_ARM_ERRATA_764369
|
|
@@ -422,6 +462,27 @@ ENTRY(v7_dma_flush_range)
|
|
ALT_UP(W(nop))
|
|
#endif
|
|
1:
|
|
+ mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
|
|
+ add r0, r0, r2
|
|
+ cmp r0, r1
|
|
+ blo 1b
|
|
+ ret lr
|
|
+ENDPROC(v7_dma_clean_range_no_dsb)
|
|
+
|
|
+/*
|
|
+ * v7_dma_flush_range(start,end)
|
|
+ * - start - virtual start address of region
|
|
+ * - end - virtual end address of region
|
|
+ */
|
|
+ENTRY(v7_dma_flush_range)
|
|
+ dcache_line_size r2, r3
|
|
+ sub r3, r2, #1
|
|
+ bic r0, r0, r3
|
|
+#ifdef CONFIG_ARM_ERRATA_764369
|
|
+ ALT_SMP(W(dsb))
|
|
+ ALT_UP(W(nop))
|
|
+#endif
|
|
+1:
|
|
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
|
add r0, r0, r2
|
|
cmp r0, r1
|
|
@@ -431,10 +492,35 @@ ENTRY(v7_dma_flush_range)
|
|
ENDPROC(v7_dma_flush_range)
|
|
|
|
/*
|
|
+ * v7_dma_flush_range_no_dsb(start,end)
|
|
+ *
|
|
+ * This API does not do "data synchronization barrier".
|
|
+ * The caller is responsible to do dsb after the transaction.
|
|
+ *
|
|
+ * - start - virtual start address of region
|
|
+ * - end - virtual end address of region
|
|
+ */
|
|
+ENTRY(v7_dma_flush_range_no_dsb)
|
|
+ dcache_line_size r2, r3
|
|
+ sub r3, r2, #1
|
|
+ bic r0, r0, r3
|
|
+#ifdef CONFIG_ARM_ERRATA_764369
|
|
+ ALT_SMP(W(dsb))
|
|
+ ALT_UP(W(nop))
|
|
+#endif
|
|
+1:
|
|
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
|
+ add r0, r0, r2
|
|
+ cmp r0, r1
|
|
+ blo 1b
|
|
+ ret lr
|
|
+ENDPROC(v7_dma_flush_range_no_dsb)
|
|
+
|
|
+/*
|
|
* dma_map_area(start, size, dir)
|
|
- * - start - kernel virtual start address
|
|
- * - size - size of region
|
|
- * - dir - DMA direction
|
|
+ * - start - kernel virtual start address
|
|
+ * - size - size of region
|
|
+ * - dir - DMA direction
|
|
*/
|
|
ENTRY(v7_dma_map_area)
|
|
add r1, r1, r0
|
|
--- a/arch/arm/mm/proc-syms.c
|
|
+++ b/arch/arm/mm/proc-syms.c
|
|
@@ -28,8 +28,11 @@ EXPORT_SYMBOL(__cpuc_flush_user_range);
|
|
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
|
|
EXPORT_SYMBOL(__cpuc_flush_dcache_area);
|
|
EXPORT_SYMBOL(dmac_inv_range);
|
|
+EXPORT_SYMBOL(dmac_inv_range_no_dsb);
|
|
EXPORT_SYMBOL(dmac_clean_range);
|
|
+EXPORT_SYMBOL(dmac_clean_range_no_dsb);
|
|
EXPORT_SYMBOL(dmac_flush_range);
|
|
+EXPORT_SYMBOL(dmac_flush_range_no_dsb);
|
|
#else
|
|
EXPORT_SYMBOL(cpu_cache);
|
|
#endif
|
|
--- a/arch/arm64/include/asm/assembler.h
|
|
+++ b/arch/arm64/include/asm/assembler.h
|
|
@@ -428,6 +428,45 @@ alternative_endif
|
|
|
|
/*
|
|
* Macro to perform a data cache maintenance for the interval
|
|
+ * [kaddr, kaddr + size)
|
|
+ * This macro does not do "data synchronization barrier". Caller should
|
|
+ * do "dsb" after transaction.
|
|
+ *
|
|
+ * op: operation passed to dc instruction
|
|
+ * kaddr: starting virtual address of the region
|
|
+ * size: size of the region
|
|
+ * Corrupts: kaddr, size, tmp1, tmp2
|
|
+ */
|
|
+ .macro dcache_by_line_op_no_dsb op, kaddr, size, tmp1, tmp2
|
|
+ dcache_line_size \tmp1, \tmp2
|
|
+ add \size, \kaddr, \size
|
|
+ sub \tmp2, \tmp1, #1
|
|
+ bic \kaddr, \kaddr, \tmp2
|
|
+9998:
|
|
+ .ifc \op, cvau
|
|
+ __dcache_op_workaround_clean_cache \op, \kaddr
|
|
+ .else
|
|
+ .ifc \op, cvac
|
|
+ __dcache_op_workaround_clean_cache \op, \kaddr
|
|
+ .else
|
|
+ .ifc \op, cvap
|
|
+ sys 3, c7, c12, 1, \kaddr // dc cvap
|
|
+ .else
|
|
+ .ifc \op, cvadp
|
|
+ sys 3, c7, c13, 1, \kaddr // dc cvadp
|
|
+ .else
|
|
+ dc \op, \kaddr
|
|
+ .endif
|
|
+ .endif
|
|
+ .endif
|
|
+ .endif
|
|
+ add \kaddr, \kaddr, \tmp1
|
|
+ cmp \kaddr, \size
|
|
+ b.lo 9998b
|
|
+ .endm
|
|
+
|
|
+/*
|
|
+ * Macro to perform a data cache maintenance for the interval
|
|
* [start, end)
|
|
*
|
|
* op: operation passed to dc instruction
|
|
--- a/arch/arm64/include/asm/cacheflush.h
|
|
+++ b/arch/arm64/include/asm/cacheflush.h
|
|
@@ -79,6 +79,15 @@ extern void dcache_clean_pou(unsigned lo
|
|
extern long caches_clean_inval_user_pou(unsigned long start, unsigned long end);
|
|
extern void sync_icache_aliases(unsigned long start, unsigned long end);
|
|
|
|
+extern void dmac_inv_range(const void *start, const void *end);
|
|
+extern void __dma_flush_area_no_dsb(const void *start, size_t size);
|
|
+extern void __dma_inv_area_no_dsb(const void *start, size_t size);
|
|
+extern void __dma_clean_area_no_dsb(const void *start, size_t size);
|
|
+
|
|
+extern void dmac_flush_range_no_dsb(const void *start, const void *end);
|
|
+extern void dmac_inv_range_no_dsb(const void *start, const void *end);
|
|
+extern void dmac_clean_range_no_dsb(const void *start, const void *end);
|
|
+
|
|
static inline void flush_icache_range(unsigned long start, unsigned long end)
|
|
{
|
|
caches_clean_inval_pou(start, end);
|
|
--- a/arch/arm64/mm/cache.S
|
|
+++ b/arch/arm64/mm/cache.S
|
|
@@ -164,6 +164,64 @@ SYM_FUNC_END(__pi_dcache_inval_poc)
|
|
SYM_FUNC_ALIAS(dcache_inval_poc, __pi_dcache_inval_poc)
|
|
|
|
/*
|
|
+ * __dma_inv_area_no_dsb(start, size)
|
|
+ *
|
|
+ * This macro does not do "data synchronization barrier". Caller should
|
|
+ * do "dsb" after transaction.
|
|
+ *
|
|
+ * start - virtual start address of region
|
|
+ * size - size in question
|
|
+ */
|
|
+SYM_FUNC_START(__dma_inv_area_no_dsb)
|
|
+ add x1, x1, x0
|
|
+ dcache_line_size x2, x3
|
|
+ sub x3, x2, #1
|
|
+ tst x1, x3 // end cache line aligned?
|
|
+ bic x1, x1, x3
|
|
+ b.eq 1f
|
|
+ dc civac, x1 // clean & invalidate D / U line
|
|
+1: tst x0, x3 // start cache line aligned?
|
|
+ bic x0, x0, x3
|
|
+ b.eq 2f
|
|
+ dc civac, x0 // clean & invalidate D / U line
|
|
+ b 3f
|
|
+2: dc ivac, x0 // invalidate D / U line
|
|
+3: add x0, x0, x2
|
|
+ cmp x0, x1
|
|
+ b.lo 2b
|
|
+ ret
|
|
+SYM_FUNC_END(__dma_inv_area_no_dsb)
|
|
+
|
|
+/*
|
|
+ * __dma_clean_area_no_dsb(start, size)
|
|
+ *
|
|
+ * his macro does not do "data synchronization barrier". Caller should
|
|
+ * o "dsb" after transaction.
|
|
+ *
|
|
+ * start - virtual start address of region
|
|
+ * size - size in question
|
|
+ */
|
|
+SYM_FUNC_START(__dma_clean_area_no_dsb)
|
|
+ dcache_by_line_op_no_dsb cvac, x0, x1, x2, x3
|
|
+ ret
|
|
+SYM_FUNC_END(__dma_clean_area_no_dsb)
|
|
+
|
|
+/*
|
|
+ * __dma_flush_area_no_dsb(start, size)
|
|
+ *
|
|
+ * clean & invalidate D / U line
|
|
+ * his macro does not do "data synchronization barrier". Caller should
|
|
+ * o "dsb" after transaction.
|
|
+ *
|
|
+ * start - virtual start address of region
|
|
+ * size - size in question
|
|
+ */
|
|
+SYM_FUNC_START(__dma_flush_area_no_dsb)
|
|
+ dcache_by_line_op_no_dsb civac, x0, x1, x2, x3
|
|
+ ret
|
|
+SYM_FUNC_END(__dma_flush_area_no_dsb)
|
|
+
|
|
+/*
|
|
* dcache_clean_poc(start, end)
|
|
*
|
|
* Ensure that any D-cache lines for the interval [start, end)
|
|
--- a/arch/arm64/mm/flush.c
|
|
+++ b/arch/arm64/mm/flush.c
|
|
@@ -100,3 +100,27 @@ void arch_invalidate_pmem(void *addr, si
|
|
}
|
|
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
|
|
#endif
|
|
+
|
|
+void dmac_flush_range_no_dsb(const void *start, const void *end)
|
|
+{
|
|
+ __dma_flush_area_no_dsb(start, (void *)(end) - (void *)(start));
|
|
+}
|
|
+EXPORT_SYMBOL(dmac_flush_range_no_dsb);
|
|
+
|
|
+void dmac_inv_range(const void *start, const void *end)
|
|
+{
|
|
+ dcache_inval_poc((unsigned long)start, (unsigned long)(end));
|
|
+}
|
|
+EXPORT_SYMBOL(dmac_inv_range);
|
|
+
|
|
+void dmac_inv_range_no_dsb(const void *start, const void *end)
|
|
+{
|
|
+ __dma_inv_area_no_dsb(start, (void *)(end) - (void *)(start));
|
|
+}
|
|
+EXPORT_SYMBOL(dmac_inv_range_no_dsb);
|
|
+
|
|
+void dmac_clean_range_no_dsb(const void *start, const void *end)
|
|
+{
|
|
+ __dma_clean_area_no_dsb(start, (void *)(end) - (void *)(start));
|
|
+}
|
|
+EXPORT_SYMBOL(dmac_clean_range_no_dsb);
|