kmap_atomic: make kunmap_atomic() harder to misuse
[firefly-linux-kernel-4.4.55.git] / arch / arm / mm / highmem.c
index 77b030f5ec09fa2dfbbcc562f345eb0ec04e3092..1fbdb55bfd1bd34a480ea0e45b7f3a39a2934c6a 100644 (file)
@@ -48,7 +48,16 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        debug_kmap_atomic(type);
 
-       kmap = kmap_high_get(page);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       /*
+        * There is no cache coherency issue when non VIVT, so force the
+        * dedicated kmap usage for better debugging purposes in that case.
+        */
+       if (!cache_is_vivt())
+               kmap = NULL;
+       else
+#endif
+               kmap = kmap_high_get(page);
        if (kmap)
                return kmap;
 
@@ -73,7 +82,7 @@ void *kmap_atomic(struct page *page, enum km_type type)
 }
 EXPORT_SYMBOL(kmap_atomic);
 
-void kunmap_atomic(void *kvaddr, enum km_type type)
+void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
        unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
@@ -94,7 +103,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
        }
        pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic_notypecheck);
 
 void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
 {
@@ -154,19 +163,22 @@ static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
 
 void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
 {
-       unsigned int idx, cpu = smp_processor_id();
-       int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
+       unsigned int idx, cpu;
+       int *depth;
        unsigned long vaddr, flags;
        pte_t pte, *ptep;
 
+       if (!in_interrupt())
+               preempt_disable();
+
+       cpu = smp_processor_id();
+       depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
+
        idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        ptep = TOP_PTE(vaddr);
        pte = mk_pte(page, kmap_prot);
 
-       if (!in_interrupt())
-               preempt_disable();
-
        raw_local_irq_save(flags);
        (*depth)++;
        if (pte_val(*ptep) == pte_val(pte)) {