Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / arch / x86 / mm / ioremap.c
index 83ed74a..12e4d2d 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/pat.h>
 
-static inline int phys_addr_valid(resource_size_t addr)
-{
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-       return !(addr >> boot_cpu_data.x86_phys_bits);
-#else
-       return 1;
-#endif
-}
-
-#ifdef CONFIG_X86_64
-
-unsigned long __phys_addr(unsigned long x)
-{
-       if (x >= __START_KERNEL_map) {
-               x -= __START_KERNEL_map;
-               VIRTUAL_BUG_ON(x >= KERNEL_IMAGE_SIZE);
-               x += phys_base;
-       } else {
-               VIRTUAL_BUG_ON(x < PAGE_OFFSET);
-               x -= PAGE_OFFSET;
-               VIRTUAL_BUG_ON(!phys_addr_valid(x));
-       }
-       return x;
-}
-EXPORT_SYMBOL(__phys_addr);
-
-bool __virt_addr_valid(unsigned long x)
-{
-       if (x >= __START_KERNEL_map) {
-               x -= __START_KERNEL_map;
-               if (x >= KERNEL_IMAGE_SIZE)
-                       return false;
-               x += phys_base;
-       } else {
-               if (x < PAGE_OFFSET)
-                       return false;
-               x -= PAGE_OFFSET;
-               if (!phys_addr_valid(x))
-                       return false;
-       }
-
-       return pfn_valid(x >> PAGE_SHIFT);
-}
-EXPORT_SYMBOL(__virt_addr_valid);
-
-#else
-
-#ifdef CONFIG_DEBUG_VIRTUAL
-unsigned long __phys_addr(unsigned long x)
-{
-       /* VMALLOC_* aren't constants  */
-       VIRTUAL_BUG_ON(x < PAGE_OFFSET);
-       VIRTUAL_BUG_ON(__vmalloc_start_set && is_vmalloc_addr((void *) x));
-       return x - PAGE_OFFSET;
-}
-EXPORT_SYMBOL(__phys_addr);
-#endif
-
-bool __virt_addr_valid(unsigned long x)
-{
-       if (x < PAGE_OFFSET)
-               return false;
-       if (__vmalloc_start_set && is_vmalloc_addr((void *) x))
-               return false;
-       if (x >= FIXADDR_START)
-               return false;
-       return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT);
-}
-EXPORT_SYMBOL(__virt_addr_valid);
-
-#endif
-
-int page_is_ram(unsigned long pagenr)
-{
-       resource_size_t addr, end;
-       int i;
-
-       /*
-        * A special case is the first 4Kb of memory;
-        * This is a BIOS owned area, not kernel ram, but generally
-        * not listed as such in the E820 table.
-        */
-       if (pagenr == 0)
-               return 0;
-
-       /*
-        * Second special case: Some BIOSen report the PC BIOS
-        * area (640->1Mb) as ram even though it is not.
-        */
-       if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) &&
-                   pagenr < (BIOS_END >> PAGE_SHIFT))
-               return 0;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               /*
-                * Not usable memory:
-                */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT;
-               end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
-
-
-               if ((pagenr >= addr) && (pagenr < end))
-                       return 1;
-       }
-       return 0;
-}
+#include "physaddr.h"
 
 /*
  * Fix up the linear direct mapping of the kernel to avoid cache attribute
@@ -228,30 +121,19 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
        retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
                                                prot_val, &new_prot_val);
        if (retval) {
-               pr_debug("Warning: reserve_memtype returned %d\n", retval);
+               printk(KERN_ERR "ioremap reserve_memtype failed %d\n", retval);
                return NULL;
        }
 
        if (prot_val != new_prot_val) {
-               /*
-                * Do not fallback to certain memory types with certain
-                * requested type:
-                * - request is uc-, return cannot be write-back
-                * - request is uc-, return cannot be write-combine
-                * - request is write-combine, return cannot be write-back
-                */
-               if ((prot_val == _PAGE_CACHE_UC_MINUS &&
-                    (new_prot_val == _PAGE_CACHE_WB ||
-                     new_prot_val == _PAGE_CACHE_WC)) ||
-                   (prot_val == _PAGE_CACHE_WC &&
-                    new_prot_val == _PAGE_CACHE_WB)) {
-                       pr_debug(
+               if (!is_new_memtype_allowed(phys_addr, size,
+                                           prot_val, new_prot_val)) {
+                       printk(KERN_ERR
                "ioremap error for 0x%llx-0x%llx, requested 0x%lx, got 0x%lx\n",
                                (unsigned long long)phys_addr,
                                (unsigned long long)(phys_addr + size),
                                prot_val, new_prot_val);
-                       free_memtype(phys_addr, phys_addr + size);
-                       return NULL;
+                       goto err_free_memtype;
                }
                prot_val = new_prot_val;
        }
@@ -277,25 +159,25 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
         */
        area = get_vm_area_caller(size, VM_IOREMAP, caller);
        if (!area)
-               return NULL;
+               goto err_free_memtype;
        area->phys_addr = phys_addr;
        vaddr = (unsigned long) area->addr;
-       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
-               free_memtype(phys_addr, phys_addr + size);
-               free_vm_area(area);
-               return NULL;
-       }
 
-       if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
-               free_memtype(phys_addr, phys_addr + size);
-               vunmap(area->addr);
-               return NULL;
-       }
+       if (kernel_map_sync_memtype(phys_addr, size, prot_val))
+               goto err_free_area;
+
+       if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot))
+               goto err_free_area;
 
        ret_addr = (void __iomem *) (vaddr + offset);
        mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret_addr);
 
        return ret_addr;
+err_free_area:
+       free_vm_area(area);
+err_free_memtype:
+       free_memtype(phys_addr, phys_addr + size);
+       return NULL;
 }
 
 /**
@@ -362,29 +244,6 @@ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
 }
 EXPORT_SYMBOL(ioremap_cache);
 
-static void __iomem *ioremap_default(resource_size_t phys_addr,
-                                       unsigned long size)
-{
-       unsigned long flags;
-       void __iomem *ret;
-       int err;
-
-       /*
-        * - WB for WB-able memory and no other conflicting mappings
-        * - UC_MINUS for non-WB-able memory with no other conflicting mappings
-        * - Inherit from confliting mappings otherwise
-        */
-       err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
-       if (err < 0)
-               return NULL;
-
-       ret = __ioremap_caller(phys_addr, size, flags,
-                              __builtin_return_address(0));
-
-       free_memtype(phys_addr, phys_addr + size);
-       return ret;
-}
-
 void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
                                unsigned long prot_val)
 {
@@ -460,7 +319,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
        if (page_is_ram(start >> PAGE_SHIFT))
                return __va(phys);
 
-       addr = (void __force *)ioremap_default(start, PAGE_SIZE);
+       addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
        if (addr)
                addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
 
@@ -516,7 +375,7 @@ void __init early_ioremap_init(void)
                printk(KERN_INFO "early_ioremap_init()\n");
 
        for (i = 0; i < FIX_BTMAPS_SLOTS; i++)
-               slot_virt[i] = fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
+               slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i);
 
        pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
        memset(bm_pte, 0, sizeof(bm_pte));
@@ -526,6 +385,10 @@ void __init early_ioremap_init(void)
         * The boot-ioremap range spans multiple pmds, for which
         * we are not prepared:
         */
+#define __FIXADDR_TOP (-PAGE_SIZE)
+       BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+                    != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+#undef __FIXADDR_TOP
        if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
                WARN_ON(1);
                printk(KERN_WARNING "pmd %p != %p\n",
@@ -547,7 +410,7 @@ void __init early_ioremap_reset(void)
 }
 
 static void __init __early_set_fixmap(enum fixed_addresses idx,
-                                  unsigned long phys, pgprot_t flags)
+                                     phys_addr_t phys, pgprot_t flags)
 {
        unsigned long addr = __fix_to_virt(idx);
        pte_t *pte;
@@ -566,7 +429,7 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
 }
 
 static inline void __init early_set_fixmap(enum fixed_addresses idx,
-                                          unsigned long phys, pgprot_t prot)
+                                          phys_addr_t phys, pgprot_t prot)
 {
        if (after_paging_init)
                __set_fixmap(idx, phys, prot);
@@ -585,6 +448,20 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx)
 static void __iomem *prev_map[FIX_BTMAPS_SLOTS] __initdata;
 static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata;
 
+void __init fixup_early_ioremap(void)
+{
+       int i;
+
+       for (i = 0; i < FIX_BTMAPS_SLOTS; i++) {
+               if (prev_map[i]) {
+                       WARN_ON(1);
+                       break;
+               }
+       }
+
+       early_ioremap_init();
+}
+
 static int __init check_early_ioremap_leak(void)
 {
        int count = 0;
@@ -607,9 +484,10 @@ static int __init check_early_ioremap_leak(void)
 late_initcall(check_early_ioremap_leak);
 
 static void __init __iomem *
-__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
+__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot)
 {
-       unsigned long offset, last_addr;
+       unsigned long offset;
+       resource_size_t last_addr;
        unsigned int nrpages;
        enum fixed_addresses idx0, idx;
        int i, slot;
@@ -625,15 +503,15 @@ __early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
        }
 
        if (slot < 0) {
-               printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n",
-                        phys_addr, size);
+               printk(KERN_INFO "early_iomap(%08llx, %08lx) not found slot\n",
+                        (u64)phys_addr, size);
                WARN_ON(1);
                return NULL;
        }
 
        if (early_ioremap_debug) {
-               printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ",
-                      phys_addr, size, slot);
+               printk(KERN_INFO "early_ioremap(%08llx, %08lx) [%d] => ",
+                      (u64)phys_addr, size, slot);
                dump_stack();
        }
 
@@ -680,13 +558,15 @@ __early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot)
 }
 
 /* Remap an IO device */
-void __init __iomem *early_ioremap(unsigned long phys_addr, unsigned long size)
+void __init __iomem *
+early_ioremap(resource_size_t phys_addr, unsigned long size)
 {
        return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO);
 }
 
 /* Remap memory */
-void __init __iomem *early_memremap(unsigned long phys_addr, unsigned long size)
+void __init __iomem *
+early_memremap(resource_size_t phys_addr, unsigned long size)
 {
        return __early_ioremap(phys_addr, size, PAGE_KERNEL);
 }