Merge branch 'master' of git://oak/home/sfr/kernels/iseries/work
[sfrench/cifs-2.6.git] / arch / i386 / mm / highmem.c
index 4b7aaf99d7ea7a1d9a19d2f821070fd4d1a85c4f..f9f647cdbc7ba3550e83d82c0c9e6996b3ae8878 100644 (file)
@@ -38,23 +38,20 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
        if (!pte_none(*(kmap_pte-idx)))
                BUG();
-#endif
        set_pte(kmap_pte-idx, mk_pte(page, kmap_prot));
-       __flush_tlb_one(vaddr);
 
        return (void*) vaddr;
 }
 
 void kunmap_atomic(void *kvaddr, enum km_type type)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-       if (vaddr < FIXADDR_START) { // FIXME
+#ifdef CONFIG_DEBUG_HIGHMEM
+       if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
                dec_preempt_count();
                preempt_check_resched();
                return;
@@ -62,19 +59,36 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
 
        if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
                BUG();
-
+#endif
        /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
+        * Force other mappings to Oops if they'll try to access this pte
+        * without first remap it.  Keeping stale mappings around is a bad idea
+        * also, in case the page changes cacheability attributes or becomes
+        * a protected page in a hypervisor.
         */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       __flush_tlb_one(vaddr);
-#endif
+       kpte_clear_flush(kmap_pte-idx, vaddr);
 
        dec_preempt_count();
        preempt_check_resched();
 }
 
+/* This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+
+       inc_preempt_count();
+
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+       set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+
+       return (void*) vaddr;
+}
+
 struct page *kmap_atomic_to_page(void *ptr)
 {
        unsigned long idx, vaddr = (unsigned long)ptr;