]> err.no Git - linux-2.6/blobdiff - arch/x86/mm/ioremap.c
x86_64/mm: check and print vmemmap allocation continuous
[linux-2.6] / arch / x86 / mm / ioremap.c
index 51cd3956c564ccccf9e7858758211572e3c7e911..d176b23110cc875187be67d3c22f227ec38cbdeb 100644 (file)
@@ -47,7 +47,7 @@ static inline int phys_addr_valid(unsigned long addr)
 
 int page_is_ram(unsigned long pagenr)
 {
-       unsigned long addr, end;
+       resource_size_t addr, end;
        int i;
 
        /*
@@ -120,10 +120,12 @@ int ioremap_change_attr(unsigned long vaddr, unsigned long size,
 static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
                               unsigned long prot_val)
 {
-       unsigned long pfn, offset, last_addr, vaddr;
+       unsigned long pfn, offset, vaddr;
+       resource_size_t last_addr;
        struct vm_struct *area;
        unsigned long new_prot_val;
        pgprot_t prot;
+       int retval;
 
        /* Don't allow wraparound or zero size */
        last_addr = phys_addr + size - 1;
@@ -131,8 +133,8 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
                return NULL;
 
        if (!phys_addr_valid(phys_addr)) {
-               printk(KERN_WARNING "ioremap: invalid physical address %lx\n",
-                      phys_addr);
+               printk(KERN_WARNING "ioremap: invalid physical address %llx\n",
+                      (unsigned long long)phys_addr);
                WARN_ON_ONCE(1);
                return NULL;
        }
@@ -163,8 +165,14 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
        phys_addr &= PAGE_MASK;
        size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
-       if (reserve_memtype(phys_addr, phys_addr + size,
-                           prot_val, &new_prot_val)) {
+       retval = reserve_memtype(phys_addr, phys_addr + size,
+                                               prot_val, &new_prot_val);
+       if (retval) {
+               pr_debug("Warning: reserve_memtype returned %d\n", retval);
+               return NULL;
+       }
+
+       if (prot_val != new_prot_val) {
                /*
                 * Do not fallback to certain memory types with certain
                 * requested type:
@@ -177,6 +185,11 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
                      new_prot_val == _PAGE_CACHE_WC)) ||
                    (prot_val == _PAGE_CACHE_WC &&
                     new_prot_val == _PAGE_CACHE_WB)) {
+                       pr_debug(
+               "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;
                }
@@ -323,6 +336,35 @@ void iounmap(volatile void __iomem *addr)
 }
 EXPORT_SYMBOL(iounmap);
 
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+void *xlate_dev_mem_ptr(unsigned long phys)
+{
+       void *addr;
+       unsigned long start = phys & PAGE_MASK;
+
+       /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
+       if (page_is_ram(start >> PAGE_SHIFT))
+               return __va(phys);
+
+       addr = (void *)ioremap(start, PAGE_SIZE);
+       if (addr)
+               addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+
+       return addr;
+}
+
+void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+{
+       if (page_is_ram(phys >> PAGE_SHIFT))
+               return;
+
+       iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
+       return;
+}
+
 #ifdef CONFIG_X86_32
 
 int __initdata early_ioremap_debug;
@@ -394,7 +436,7 @@ void __init early_ioremap_clear(void)
 
        pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
        pmd_clear(pmd);
-       paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
+       paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
        __flush_tlb_all();
 }