Add WB/UC check for early_ioremap
authorLi, Zhen-Hua <zhen-hual@hp.com>
Mon, 18 Mar 2013 02:45:43 +0000 (10:45 +0800)
committerTony Luck <tony.luck@intel.com>
Tue, 19 Mar 2013 23:14:52 +0000 (16:14 -0700)
On ia64 system, the function early_ioremap returned an uncached memory
reference without checking whether this was consistent with existing
mappings. This causes efi error and the kernel failed during boot.  Add a
check to test whether memory has EFI_MEMORY_WB set.  Use the function
kern_mem_attribute() in early_iomap() function to provide appropriate
cacheable or uncacheable mapped address.

See the document Documentation/ia64/aliasing.txt for more details.

Signed-off-by: Li, Zhen-Hua <zhen-hual@hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/mm/ioremap.c

index 3dccdd8eb275fd9c36c1e3105791a09f34e0a858..43964cde6214ae6b0fc3cb6cfec911b6a4df2fd2 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/meminit.h>
 
 static inline void __iomem *
-__ioremap (unsigned long phys_addr)
+__ioremap_uc(unsigned long phys_addr)
 {
        return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
 }
@@ -24,7 +24,11 @@ __ioremap (unsigned long phys_addr)
 void __iomem *
 early_ioremap (unsigned long phys_addr, unsigned long size)
 {
-       return __ioremap(phys_addr);
+       u64 attr;
+       attr = kern_mem_attribute(phys_addr, size);
+       if (attr & EFI_MEMORY_WB)
+               return (void __iomem *) phys_to_virt(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 
 void __iomem *
@@ -47,7 +51,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
        if (attr & EFI_MEMORY_WB)
                return (void __iomem *) phys_to_virt(phys_addr);
        else if (attr & EFI_MEMORY_UC)
-               return __ioremap(phys_addr);
+               return __ioremap_uc(phys_addr);
 
        /*
         * Some chipsets don't support UC access to memory.  If
@@ -93,7 +97,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
                return (void __iomem *) (offset + (char __iomem *)addr);
        }
 
-       return __ioremap(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap);
 
@@ -103,7 +107,7 @@ ioremap_nocache (unsigned long phys_addr, unsigned long size)
        if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
                return NULL;
 
-       return __ioremap(phys_addr);
+       return __ioremap_uc(phys_addr);
 }
 EXPORT_SYMBOL(ioremap_nocache);