Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / arch / sh / mm / ioremap_64.c
index 95462a0..31e1bb5 100644 (file)
@@ -1,23 +1,24 @@
 /*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * arch/sh64/mm/ioremap.c
+ * arch/sh/mm/ioremap_64.c
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003, 2004  Paul Mundt
+ * Copyright (C) 2003 - 2007  Paul Mundt
  *
  * Mostly derived from arch/sh/mm/ioremap.c which, in turn is mostly
  * derived from arch/i386/mm/ioremap.c .
  *
  *   (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/vmalloc.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/io.h>
+#include <linux/bootmem.h>
 #include <linux/proc_fs.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -42,7 +43,8 @@ static unsigned long shmedia_ioremap(struct resource *, u32, int);
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void *__ioremap(unsigned long phys_addr, unsigned long size,
+               unsigned long flags)
 {
        void * addr;
        struct vm_struct * area;
@@ -69,9 +71,9 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
         * Ok, go for it..
         */
        area = get_vm_area(size, VM_IOREMAP);
-       pr_debug("Get vm_area returns %p addr %p\n",area,area->addr);
        if (!area)
                return NULL;
+       pr_debug("Get vm_area returns %p addr %p\n", area, area->addr);
        area->phys_addr = phys_addr;
        addr = area->addr;
        if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
@@ -83,7 +85,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
 }
 EXPORT_SYMBOL(__ioremap);
 
-void iounmap(void *addr)
+void __iounmap(void *addr)
 {
        struct vm_struct *area;
 
@@ -96,7 +98,7 @@ void iounmap(void *addr)
 
        kfree(area);
 }
-EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(__iounmap);
 
 static struct resource shmedia_iomap = {
        .name   = "shmedia_iomap",
@@ -176,7 +178,7 @@ static unsigned long shmedia_alloc_io(unsigned long phys, unsigned long size,
         } else {
                 if (!printed_full) {
                         printk("%s: done with statics, switching to kmalloc\n",
-                              __FUNCTION__);
+                              __func__);
                         printed_full = 1;
                 }
                 tlen = strlen(name);
@@ -265,6 +267,7 @@ static __init_refok void *sh64_get_page(void)
 static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
 {
        pgd_t *pgdp;
+       pud_t *pudp;
        pmd_t *pmdp;
        pte_t *ptep, pte;
        pgprot_t prot;
@@ -274,11 +277,17 @@ static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
 
        pgdp = pgd_offset_k(va);
        if (pgd_none(*pgdp) || !pgd_present(*pgdp)) {
+               pudp = (pud_t *)sh64_get_page();
+               set_pgd(pgdp, __pgd((unsigned long)pudp | _KERNPG_TABLE));
+       }
+
+       pudp = pud_offset(pgdp, va);
+       if (pud_none(*pudp) || !pud_present(*pudp)) {
                pmdp = (pmd_t *)sh64_get_page();
-               set_pgd(pgdp, __pgd((unsigned long)pmdp | _KERNPG_TABLE));
+               set_pud(pudp, __pud((unsigned long)pmdp | _KERNPG_TABLE));
        }
 
-       pmdp = pmd_offset(pgdp, va);
+       pmdp = pmd_offset(pudp, va);
        if (pmd_none(*pmdp) || !pmd_present(*pmdp) ) {
                ptep = (pte_t *)sh64_get_page();
                set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE));
@@ -302,12 +311,19 @@ static void shmedia_mapioaddr(unsigned long pa, unsigned long va)
 static void shmedia_unmapioaddr(unsigned long vaddr)
 {
        pgd_t *pgdp;
+       pud_t *pudp;
        pmd_t *pmdp;
        pte_t *ptep;
 
        pgdp = pgd_offset_k(vaddr);
-       pmdp = pmd_offset(pgdp, vaddr);
+       if (pgd_none(*pgdp) || pgd_bad(*pgdp))
+               return;
+
+       pudp = pud_offset(pgdp, vaddr);
+       if (pud_none(*pudp) || pud_bad(*pudp))
+               return;
 
+       pmdp = pmd_offset(pudp, vaddr);
        if (pmd_none(*pmdp) || pmd_bad(*pmdp))
                return;
 
@@ -327,6 +343,7 @@ unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *n
 
        return shmedia_alloc_io(phys, size, name);
 }
+EXPORT_SYMBOL(onchip_remap);
 
 void onchip_unmap(unsigned long vaddr)
 {
@@ -336,7 +353,7 @@ void onchip_unmap(unsigned long vaddr)
        res = shmedia_find_resource(&shmedia_iomap, vaddr);
        if (!res) {
                printk(KERN_ERR "%s: Failed to free 0x%08lx\n",
-                      __FUNCTION__, vaddr);
+                      __func__, vaddr);
                return;
        }
 
@@ -354,6 +371,7 @@ void onchip_unmap(unsigned long vaddr)
                kfree(res);
        }
 }
+EXPORT_SYMBOL(onchip_unmap);
 
 #ifdef CONFIG_PROC_FS
 static int