diff options
author | Li, Zhen-Hua <zhen-hual@hp.com> | 2013-03-17 22:45:43 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-03-19 19:14:52 -0400 |
commit | a4279e6202bbd08ac6038234571ac639c98879cf (patch) | |
tree | cd3e2a755a22304e695494115484a15fdb038d05 | |
parent | deb60015096102f9842b631dcad98a05001268e9 (diff) |
Add WB/UC check for early_ioremap
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>
-rw-r--r-- | arch/ia64/mm/ioremap.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 3dccdd8eb275..43964cde6214 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <asm/meminit.h> | 16 | #include <asm/meminit.h> |
17 | 17 | ||
18 | static inline void __iomem * | 18 | static inline void __iomem * |
19 | __ioremap (unsigned long phys_addr) | 19 | __ioremap_uc(unsigned long phys_addr) |
20 | { | 20 | { |
21 | return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr); | 21 | return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr); |
22 | } | 22 | } |
@@ -24,7 +24,11 @@ __ioremap (unsigned long phys_addr) | |||
24 | void __iomem * | 24 | void __iomem * |
25 | early_ioremap (unsigned long phys_addr, unsigned long size) | 25 | early_ioremap (unsigned long phys_addr, unsigned long size) |
26 | { | 26 | { |
27 | return __ioremap(phys_addr); | 27 | u64 attr; |
28 | attr = kern_mem_attribute(phys_addr, size); | ||
29 | if (attr & EFI_MEMORY_WB) | ||
30 | return (void __iomem *) phys_to_virt(phys_addr); | ||
31 | return __ioremap_uc(phys_addr); | ||
28 | } | 32 | } |
29 | 33 | ||
30 | void __iomem * | 34 | void __iomem * |
@@ -47,7 +51,7 @@ ioremap (unsigned long phys_addr, unsigned long size) | |||
47 | if (attr & EFI_MEMORY_WB) | 51 | if (attr & EFI_MEMORY_WB) |
48 | return (void __iomem *) phys_to_virt(phys_addr); | 52 | return (void __iomem *) phys_to_virt(phys_addr); |
49 | else if (attr & EFI_MEMORY_UC) | 53 | else if (attr & EFI_MEMORY_UC) |
50 | return __ioremap(phys_addr); | 54 | return __ioremap_uc(phys_addr); |
51 | 55 | ||
52 | /* | 56 | /* |
53 | * Some chipsets don't support UC access to memory. If | 57 | * Some chipsets don't support UC access to memory. If |
@@ -93,7 +97,7 @@ ioremap (unsigned long phys_addr, unsigned long size) | |||
93 | return (void __iomem *) (offset + (char __iomem *)addr); | 97 | return (void __iomem *) (offset + (char __iomem *)addr); |
94 | } | 98 | } |
95 | 99 | ||
96 | return __ioremap(phys_addr); | 100 | return __ioremap_uc(phys_addr); |
97 | } | 101 | } |
98 | EXPORT_SYMBOL(ioremap); | 102 | EXPORT_SYMBOL(ioremap); |
99 | 103 | ||
@@ -103,7 +107,7 @@ ioremap_nocache (unsigned long phys_addr, unsigned long size) | |||
103 | if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) | 107 | if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) |
104 | return NULL; | 108 | return NULL; |
105 | 109 | ||
106 | return __ioremap(phys_addr); | 110 | return __ioremap_uc(phys_addr); |
107 | } | 111 | } |
108 | EXPORT_SYMBOL(ioremap_nocache); | 112 | EXPORT_SYMBOL(ioremap_nocache); |
109 | 113 | ||