Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / arch / ia64 / mm / ioremap.c
index 643ccc6..0c08ce1 100644 (file)
 #include <linux/module.h>
 #include <linux/efi.h>
 #include <asm/io.h>
+#include <asm/meminit.h>
 
 static inline void __iomem *
 __ioremap (unsigned long offset, unsigned long size)
 {
+#ifdef CONFIG_XEN
+       offset = HYPERVISOR_ioremap(offset, size);
+#endif
        return (void __iomem *) (__IA64_UNCACHED_OFFSET | offset);
 }
 
 void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-       if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
-               return phys_to_virt(offset);
+       u64 attr;
+       unsigned long gran_base, gran_size;
 
-       if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+       /*
+        * For things in kern_memmap, we must use the same attribute
+        * as the rest of the kernel.  For more details, see
+        * Documentation/ia64/aliasing.txt.
+        */
+       attr = kern_mem_attribute(offset, size);
+       if (attr & EFI_MEMORY_WB)
+               return (void __iomem *) phys_to_virt(offset);
+       else if (attr & EFI_MEMORY_UC)
                return __ioremap(offset, size);
 
        /*
-        * Someday this should check ACPI resources so we
-        * can do the right thing for hot-plugged regions.
+        * Some chipsets don't support UC access to memory.  If
+        * WB is supported for the whole granule, we prefer that.
         */
+       gran_base = GRANULEROUNDDOWN(offset);
+       gran_size = GRANULEROUNDUP(offset + size) - gran_base;
+       if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
+               return (void __iomem *) phys_to_virt(offset);
+
        return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap);
@@ -38,6 +55,9 @@ EXPORT_SYMBOL(ioremap);
 void __iomem *
 ioremap_nocache (unsigned long offset, unsigned long size)
 {
+       if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
+               return NULL;
+
        return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap_nocache);