summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch119
1 files changed, 119 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch b/extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch
new file mode 100644
index 00000000..a9fd1f02
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/linus/0005-ARM-fix-cache-feroceon-l2-after-stack-based-kmap_ato.patch
@@ -0,0 +1,119 @@
1From ccb2858c9bd5fff216feab665db14ca32be8d6fe Mon Sep 17 00:00:00 2001
2From: Nicolas Pitre <nicolas.pitre@linaro.org>
3Date: Thu, 16 Dec 2010 14:56:34 -0500
4Subject: [PATCH 05/65] ARM: fix cache-feroceon-l2 after stack based kmap_atomic()
5
6Since commit 3e4d3af501 "mm: stack based kmap_atomic()", it is actively
7wrong to rely on fixed kmap type indices (namely KM_L2_CACHE) as
8kmap_atomic() totally ignores them and a concurrent instance of it may
9happily reuse any slot for any purpose. Because kmap_atomic() is now
10able to deal with reentrancy, we can get rid of the ad hoc mapping here.
11
12While the code is made much simpler, there is a needless cache flush
13introduced by the usage of __kunmap_atomic(). It is not clear if the
14performance difference to remove that is worth the cost in code
15maintenance (I don't think there are that many highmem users on that
16platform anyway) but that should be reconsidered when/if someone cares
17enough to do some measurements.
18
19Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
20---
21 arch/arm/mm/cache-feroceon-l2.c | 37 +++++++++++++++++++------------------
22 1 files changed, 19 insertions(+), 18 deletions(-)
23
24diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
25index 6e77c04..e0b0e7a 100644
26--- a/arch/arm/mm/cache-feroceon-l2.c
27+++ b/arch/arm/mm/cache-feroceon-l2.c
28@@ -13,13 +13,9 @@
29 */
30
31 #include <linux/init.h>
32+#include <linux/highmem.h>
33 #include <asm/cacheflush.h>
34-#include <asm/kmap_types.h>
35-#include <asm/fixmap.h>
36-#include <asm/pgtable.h>
37-#include <asm/tlbflush.h>
38 #include <plat/cache-feroceon-l2.h>
39-#include "mm.h"
40
41 /*
42 * Low-level cache maintenance operations.
43@@ -39,27 +35,30 @@
44 * between which we don't want to be preempted.
45 */
46
47-static inline unsigned long l2_start_va(unsigned long paddr)
48+static inline unsigned long l2_get_va(unsigned long paddr)
49 {
50 #ifdef CONFIG_HIGHMEM
51 /*
52- * Let's do our own fixmap stuff in a minimal way here.
53 * Because range ops can't be done on physical addresses,
54 * we simply install a virtual mapping for it only for the
55 * TLB lookup to occur, hence no need to flush the untouched
56- * memory mapping. This is protected with the disabling of
57- * interrupts by the caller.
58+ * memory mapping afterwards (note: a cache flush may happen
59+ * in some circumstances depending on the path taken in kunmap_atomic).
60 */
61- unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
62- unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
63- set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
64- local_flush_tlb_kernel_page(vaddr);
65- return vaddr + (paddr & ~PAGE_MASK);
66+ void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
67+ return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
68 #else
69 return __phys_to_virt(paddr);
70 #endif
71 }
72
73+static inline void l2_put_va(unsigned long vaddr)
74+{
75+#ifdef CONFIG_HIGHMEM
76+ kunmap_atomic((void *)vaddr);
77+#endif
78+}
79+
80 static inline void l2_clean_pa(unsigned long addr)
81 {
82 __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
83@@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
84 */
85 BUG_ON((start ^ end) >> PAGE_SHIFT);
86
87- raw_local_irq_save(flags);
88- va_start = l2_start_va(start);
89+ va_start = l2_get_va(start);
90 va_end = va_start + (end - start);
91+ raw_local_irq_save(flags);
92 __asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
93 "mcr p15, 1, %1, c15, c9, 5"
94 : : "r" (va_start), "r" (va_end));
95 raw_local_irq_restore(flags);
96+ l2_put_va(va_start);
97 }
98
99 static inline void l2_clean_inv_pa(unsigned long addr)
100@@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
101 */
102 BUG_ON((start ^ end) >> PAGE_SHIFT);
103
104- raw_local_irq_save(flags);
105- va_start = l2_start_va(start);
106+ va_start = l2_get_va(start);
107 va_end = va_start + (end - start);
108+ raw_local_irq_save(flags);
109 __asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
110 "mcr p15, 1, %1, c15, c11, 5"
111 : : "r" (va_start), "r" (va_end));
112 raw_local_irq_restore(flags);
113+ l2_put_va(va_start);
114 }
115
116 static inline void l2_inv_all(void)
117--
1181.6.6.1
119