summaryrefslogtreecommitdiff
path: root/arch/arm64/mm/ioremap.c
diff options
context:
space:
mode:
authorMark Salter <msalter@redhat.com>2013-10-24 18:54:17 +0400
committerCatalin Marinas <catalin.marinas@arm.com>2013-10-30 16:10:37 +0400
commitc04e8e2fe5e0163fd37ccec7f538be8fa63be40e (patch)
tree913804962b54cac275b6b2112c202b976265e19e /arch/arm64/mm/ioremap.c
parentd0f38f9130b7683e39611c5a661349e301ee43c8 (diff)
downloadlinux-c04e8e2fe5e0163fd37ccec7f538be8fa63be40e.tar.xz
arm64: allow ioremap_cache() to use existing RAM mappings
Some drivers (ACPI notably) use ioremap_cache() to map an area which could either be outside of kernel RAM or in an already mapped reserved area of RAM. To avoid aliases with different caching attributes, ioremap() does not allow RAM to be remapped. But for ioremap_cache(), the existing kernel mapping may be used. Signed-off-by: Mark Salter <msalter@redhat.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/mm/ioremap.c')
-rw-r--r--arch/arm64/mm/ioremap.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 1725cd6db37a..2bb1d586664c 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -77,8 +77,24 @@ EXPORT_SYMBOL(__ioremap);
void __iounmap(volatile void __iomem *io_addr)
{
- void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+ unsigned long addr = (unsigned long)io_addr & PAGE_MASK;
- vunmap(addr);
+ /*
+ * We could get an address outside vmalloc range in case
+ * of ioremap_cache() reusing a RAM mapping.
+ */
+ if (VMALLOC_START <= addr && addr < VMALLOC_END)
+ vunmap((void *)addr);
}
EXPORT_SYMBOL(__iounmap);
+
+void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
+{
+ /* For normal memory we already have a cacheable mapping. */
+ if (pfn_valid(__phys_to_pfn(phys_addr)))
+ return (void __iomem *)__phys_to_virt(phys_addr);
+
+ return __ioremap_caller(phys_addr, size, __pgprot(PROT_NORMAL),
+ __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_cache);