Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / cris / mm / ioremap.c
index 6b9130b..1780df3 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm/arch/memmap.h>
 
-extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+       unsigned long phys_addr, pgprot_t prot)
 {
        unsigned long end;
 
@@ -31,9 +32,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
                        printk("remap_area_pte: page already exists\n");
                        BUG();
                }
-               set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE | 
-                                                            __WRITEABLE | _PAGE_GLOBAL |
-                                                            _PAGE_KERNEL | flags)));
+               set_pte(pte, mk_pte_phys(phys_addr, prot));
                address += PAGE_SIZE;
                phys_addr += PAGE_SIZE;
                pte++;
@@ -41,7 +40,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
 }
 
 static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long phys_addr, unsigned long flags)
+       unsigned long phys_addr, pgprot_t prot)
 {
        unsigned long end;
 
@@ -53,10 +52,10 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
        if (address >= end)
                BUG();
        do {
-               pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
+               pte_t * pte = pte_alloc_kernel(pmd, address);
                if (!pte)
                        return -ENOMEM;
-               remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+               remap_area_pte(pte, address, end - address, address + phys_addr, prot);
                address = (address + PMD_SIZE) & PMD_MASK;
                pmd++;
        } while (address && (address < end));
@@ -64,7 +63,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
 }
 
 static int remap_area_pages(unsigned long address, unsigned long phys_addr,
-                                unsigned long size, unsigned long flags)
+                                unsigned long size, pgprot_t prot)
 {
        int error;
        pgd_t * dir;
@@ -75,21 +74,25 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
        flush_cache_all();
        if (address >= end)
                BUG();
-       spin_lock(&init_mm.page_table_lock);
        do {
+               pud_t *pud;
                pmd_t *pmd;
-               pmd = pmd_alloc(&init_mm, dir, address);
+
                error = -ENOMEM;
+               pud = pud_alloc(&init_mm, dir, address);
+               if (!pud)
+                       break;
+               pmd = pmd_alloc(&init_mm, pud, address);
+
                if (!pmd)
                        break;
                if (remap_area_pmd(pmd, address, end - address,
-                                  phys_addr + address, flags))
+                                  phys_addr + address, prot))
                        break;
                error = 0;
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                dir++;
        } while (address && (address < end));
-       spin_unlock(&init_mm.page_table_lock);
        flush_tlb_all();
        return error;
 }
@@ -107,9 +110,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
  * 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 __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot)
 {
-       void * addr;
+       void __iomem * addr;
        struct vm_struct * area;
        unsigned long offset, last_addr;
 
@@ -131,15 +134,36 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
        area = get_vm_area(size, VM_IOREMAP);
        if (!area)
                return NULL;
-       addr = area->addr;
-       if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
-               vfree(addr);
+       addr = (void __iomem *)area->addr;
+       if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
+               vfree((void __force *)addr);
                return NULL;
        }
-       return (void *) (offset + (char *)addr);
+       return (void __iomem *) (offset + (char __iomem *)addr);
+}
+
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+       return __ioremap_prot(phys_addr, size,
+                             __pgprot(_PAGE_PRESENT | __READABLE |
+                                      __WRITEABLE | _PAGE_GLOBAL |
+                                      _PAGE_KERNEL | flags));
+}
+
+/**
+ * ioremap_nocache     -   map bus memory into CPU space
+ * @offset:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * Must be freed with iounmap.
+ */
+
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+{
+        return __ioremap(phys_addr | MEM_NON_CACHEABLE, size, 0);
 }
 
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
 {
        if (addr > high_memory)
                return vfree((void *) (PAGE_MASK & (unsigned long) addr));