2006-08-10 16:04:10

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 0/14] Generic ioremap_page_range: introduction

Hi Andrew,

If this is acked by the relevant people, could you give it a spin
in -mm?

This is a resend of the generic ioremap_page_range() patchset with
one minor change noted below. As Andi Kleen pointed out, I should
send the patches directly to the arch maintainers, so I'm Cc'ing them
this time around. Hopefully at least -- I'm not 100% confident with
git-send-email yet, but I'm getting there :)

Some patches have already been acked, but I'm cc'ing the maintainer
anyway.

I've reverted the "implementation" patch to use the same
flush_cache_all()/flush_tlb_all() scheme used by i386 and most other
architectures and added a second patch that converts them to
flush_cache_vmap(). This way, if things fall apart during testing,
there's only a single patch to revert.

In addition to the generic ioremap_page_range() implementation, this
updates all architectures that were relatively trivial to convert.
Most of remaining architectures implement ioremap() as a no-op or
something close. Exceptions are m68k, powerpc and sparc.

m68k has some CPU-dependent logic in the middle of the loop.

powerpc could probably use generic ioremap_page_range(), but doing so
would probably increase the code size, as the map_page() functions
have other users in addition to ioremap().

sparc maps in huge pages when possible. Better not touch it.

Oh, and I'm going to Taiwan next week, so I may be slow to respond.

Haavard


2006-08-10 16:04:35

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 1/14] Generic ioremap_page_range: implementation

This patch adds a generic implementation of ioremap_page_range() in
lib/ioremap.c based on the i386 implementation. It differs from the
i386 version in the following ways:

* The PTE flags are passed as a pgprot_t argument and must be
determined up front by the arch-specific code. No additional
PTE flags are added.
* Uses set_pte_at() instead of set_pte()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
include/linux/io.h | 4 ++
lib/Makefile | 2 +
lib/ioremap.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 1 deletions(-)

diff --git a/include/linux/io.h b/include/linux/io.h
index 420e2fd..aa3f5af 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -19,8 +19,12 @@ #ifndef _LINUX_IO_H
#define _LINUX_IO_H

#include <asm/io.h>
+#include <asm/page.h>

void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
void __iowrite64_copy(void __iomem *to, const void *from, size_t count);

+int ioremap_page_range(unsigned long addr, unsigned long end,
+ unsigned long phys_addr, pgprot_t prot);
+
#endif /* _LINUX_IO_H */
diff --git a/lib/Makefile b/lib/Makefile
index be9719a..a4dcb07 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,7 +5,7 @@ #
lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
- sha1.o
+ sha1.o ioremap.o

lib-$(CONFIG_SMP) += cpumask.o

diff --git a/lib/ioremap.c b/lib/ioremap.c
new file mode 100644
index 0000000..6419101
--- /dev/null
+++ b/lib/ioremap.c
@@ -0,0 +1,93 @@
+/*
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ */
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+
+static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+ pte_t *pte;
+ unsigned long pfn;
+
+ pfn = phys_addr >> PAGE_SHIFT;
+ pte = pte_alloc_kernel(pmd, addr);
+ if (!pte)
+ return -ENOMEM;
+ do {
+ BUG_ON(!pte_none(*pte));
+ set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
+ pfn++;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ return 0;
+}
+
+static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ phys_addr -= addr;
+ pmd = pmd_alloc(&init_mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
+ do {
+ next = pmd_addr_end(addr, end);
+ if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
+ return -ENOMEM;
+ } while (pmd++, addr = next, addr != end);
+ return 0;
+}
+
+static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ phys_addr -= addr;
+ pud = pud_alloc(&init_mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
+ do {
+ next = pud_addr_end(addr, end);
+ if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr != end);
+ return 0;
+}
+
+int ioremap_page_range(unsigned long addr,
+ unsigned long end, unsigned long phys_addr, pgprot_t prot)
+{
+ pgd_t *pgd;
+ unsigned long start;
+ unsigned long next;
+ int err;
+
+ BUG_ON(addr >= end);
+
+ flush_cache_all();
+
+ start = addr;
+ phys_addr -= addr;
+ pgd = pgd_offset_k(addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot);
+ if (err)
+ break;
+ } while (pgd++, addr = next, addr != end);
+
+ flush_tlb_all();
+
+ return err;
+}
--
1.4.0

2006-08-10 16:04:13

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 2/14] Generic ioremap_page_range: flush_cache_vmap

The existing implementation of ioremap_page_range(), which was taken
from i386, does this:

flush_cache_all();
/* modify page tables */
flush_tlb_all();

I think this is a bit defensive, so this patch changes the generic
implementation to do:

/* modify page tables */
flush_cache_vmap(start, end);

instead, which is similar to what vmalloc() does. This should still
be correct because we never modify existing PTEs. According to
James Bottomley:

The problem the flush_tlb_all() is trying to solve is to avoid stale tlb
entries in the ioremap area. We're just being conservative by flushing
on both map and unmap. Technically what vmalloc/vfree does (only flush
the tlb on unmap) is just fine because it means that the only tlb
entries in the remap area must belong to in-use mappings.

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
lib/ioremap.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/lib/ioremap.c b/lib/ioremap.c
index 6419101..d2cb1eb 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -75,8 +75,6 @@ int ioremap_page_range(unsigned long add

BUG_ON(addr >= end);

- flush_cache_all();
-
start = addr;
phys_addr -= addr;
pgd = pgd_offset_k(addr);
@@ -87,7 +85,7 @@ int ioremap_page_range(unsigned long add
break;
} while (pgd++, addr = next, addr != end);

- flush_tlb_all();
+ flush_cache_vmap(start, end);

return err;
}
--
1.4.0

2006-08-10 16:04:38

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 3/14] Generic ioremap_page_range: alpha conversion

From: Richard Henderson <[email protected]>

Convert Alpha to use generic ioremap_page_range() by turning
__alpha_remap_area_pages() into an inline wrapper around
ioremap_page_range().

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/alpha/kernel/proto.h | 15 ++++++--
arch/alpha/mm/Makefile | 2 +
arch/alpha/mm/remap.c | 86 ---------------------------------------------
3 files changed, 13 insertions(+), 90 deletions(-)

diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 2a6e3da..21f7128 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -1,5 +1,7 @@
#include <linux/interrupt.h>
+#include <linux/io.h>

+#include <asm/pgtable.h>

/* Prototypes of functions used across modules here in this directory. */

@@ -181,9 +183,16 @@ extern void titan_dispatch_irqs(u64, str
extern void switch_to_system_map(void);
extern void srm_paging_stop(void);

-/* ../mm/remap.c */
-extern int __alpha_remap_area_pages(unsigned long, unsigned long,
- unsigned long, unsigned long);
+static inline int
+__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ pgprot_t prot;
+
+ prot = __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE
+ | _PAGE_KWE | flags);
+ return ioremap_page_range(address, address + size, phys_addr, prot);
+}

/* irq.c */

diff --git a/arch/alpha/mm/Makefile b/arch/alpha/mm/Makefile
index 6edd9a0..09399c5 100644
--- a/arch/alpha/mm/Makefile
+++ b/arch/alpha/mm/Makefile
@@ -4,6 +4,6 @@ #

EXTRA_CFLAGS := -Werror

-obj-y := init.o fault.o extable.o remap.o
+obj-y := init.o fault.o extable.o

obj-$(CONFIG_DISCONTIGMEM) += numa.o
diff --git a/arch/alpha/mm/remap.c b/arch/alpha/mm/remap.c
deleted file mode 100644
index a78356c..0000000
--- a/arch/alpha/mm/remap.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include <linux/vmalloc.h>
-#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-
-static inline void
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn,
- __pgprot(_PAGE_VALID | _PAGE_ASM |
- _PAGE_KRE | _PAGE_KWE | flags)));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address,
- address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-int
-__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- pgd_t * dir;
- int error = 0;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- return error;
-}
-
--
1.4.0

2006-08-10 16:05:19

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 13/14] Generic ioremap_page_range: sh64 conversion

From: Paul Mundt <[email protected]>

Convert SH64 to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/sh64/mm/ioremap.c | 100 ++++--------------------------------------------
1 files changed, 8 insertions(+), 92 deletions(-)

diff --git a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c
index fb1866f..e77d85f 100644
--- a/arch/sh64/mm/ioremap.c
+++ b/arch/sh64/mm/ioremap.c
@@ -18,7 +18,7 @@ #include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <linux/ioport.h>
@@ -28,96 +28,6 @@ #include <linux/proc_fs.h>
static void shmedia_mapioaddr(unsigned long, unsigned long);
static unsigned long shmedia_ioremap(struct resource *, u32, int);

-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ |
- _PAGE_WRITE | _PAGE_DIRTY |
- _PAGE_ACCESSED | _PAGE_SHARED | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
-
- pfn = phys_addr >> PAGE_SHIFT;
-
- pr_debug(" %s: pte %p address %lx size %lx phys_addr %lx\n",
- __FUNCTION__,pte,address,size,phys_addr);
-
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
-
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
-
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- phys_addr -= address;
-
- if (address >= end)
- BUG();
-
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags)) {
- break;
- }
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return 0;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -136,12 +46,17 @@ void * __ioremap(unsigned long phys_addr
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
return NULL;

+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ |
+ _PAGE_WRITE | _PAGE_DIRTY |
+ _PAGE_ACCESSED | _PAGE_SHARED | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -158,7 +73,8 @@ void * __ioremap(unsigned long phys_addr
return NULL;
area->phys_addr = phys_addr;
addr = area->addr;
- if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, pgprot)) {
vunmap(addr);
return NULL;
}
--
1.4.0

2006-08-10 16:05:59

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 10/14] Generic ioremap_page_range: parisc conversion

From: Kyle McMartin <[email protected]>

Convert parisc to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
Acked-by: Kyle McMartin <[email protected]>
---
arch/parisc/mm/ioremap.c | 111 +++-------------------------------------------
1 files changed, 7 insertions(+), 104 deletions(-)

diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 2738456..a31da6c 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -9,110 +9,8 @@
#include <linux/vmalloc.h>
#include <linux/errno.h>
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/cacheflush.h>
-
-static inline void
-remap_area_pte(pte_t *pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end, pfn;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
- _PAGE_ACCESSED | flags);
-
- address &= ~PMD_MASK;
-
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
-
- BUG_ON(address >= end);
-
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- BUG_ON(!pte_none(*pte));
-
- set_pte(pte, pfn_pte(pfn, pgprot));
-
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int
-remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
-
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- BUG_ON(address >= end);
-
- phys_addr -= address;
- do {
- pte_t *pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
-
- remap_area_pte(pte, address, end - address,
- address + phys_addr, flags);
-
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
-
- return 0;
-}
-
-static int
-remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- pgd_t *dir;
- int error = 0;
- unsigned long end = address + size;
-
- BUG_ON(address >= end);
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
-
- flush_cache_all();
-
- do {
- pud_t *pud;
- pmd_t *pmd;
-
- 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))
- break;
-
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
-
- flush_tlb_all();
-
- return error;
-}

/*
* Generic mapping function (not visible outside):
@@ -131,6 +29,7 @@ void __iomem * __ioremap(unsigned long p
void *addr;
struct vm_struct *area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;

#ifdef CONFIG_EISA
unsigned long end = phys_addr + size - 1;
@@ -164,6 +63,9 @@ #endif
}
}

+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+ _PAGE_ACCESSED | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -179,7 +81,8 @@ #endif
return NULL;

addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, pgprot)) {
vfree(addr);
return NULL;
}
--
1.4.0

2006-08-10 16:05:06

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 9/14] Generic ioremap_page_range: mips conversion

From: Ralf Baechle <[email protected]>

Convert MIPS to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/mips/mm/ioremap.c | 95 ++++--------------------------------------------
1 files changed, 7 insertions(+), 88 deletions(-)

diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index 3101d1d..cac79ae 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -11,93 +11,7 @@ #include <asm/addrspace.h>
#include <asm/byteorder.h>

#include <linux/vmalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
- phys_t size, phys_t phys_addr, unsigned long flags)
-{
- phys_t end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
- | __WRITEABLE | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
- phys_t size, phys_t phys_addr, unsigned long flags)
-{
- phys_t end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, phys_t phys_addr,
- phys_t size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pud_t *pud;
- pmd_t *pmd;
-
- 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))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}
+#include <linux/io.h>

/*
* Generic mapping function (not visible outside):
@@ -121,6 +35,7 @@ void __iomem * __ioremap(phys_t phys_add
unsigned long offset;
phys_t last_addr;
void * addr;
+ pgprot_t pgprot;

phys_addr = fixup_bigphys_addr(phys_addr, size);

@@ -152,6 +67,9 @@ void __iomem * __ioremap(phys_t phys_add
return NULL;
}

+ pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE
+ | __WRITEABLE | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -166,7 +84,8 @@ void __iomem * __ioremap(phys_t phys_add
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, pgprot)) {
vunmap(addr);
return NULL;
}
--
1.4.0

2006-08-10 16:06:07

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 5/14] Generic ioremap_page_range: avr32 conversion

Convert AVR32 to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/avr32/mm/ioremap.c | 120 ++---------------------------------------------
1 files changed, 6 insertions(+), 114 deletions(-)

diff --git a/arch/avr32/mm/ioremap.c b/arch/avr32/mm/ioremap.c
index 5360218..8cfec65 100644
--- a/arch/avr32/mm/ioremap.c
+++ b/arch/avr32/mm/ioremap.c
@@ -7,119 +7,11 @@
*/
#include <linux/vmalloc.h>
#include <linux/module.h>
+#include <linux/io.h>

-#include <asm/io.h>
#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
#include <asm/addrspace.h>

-static inline int remap_area_pte(pte_t *pte, unsigned long address,
- unsigned long end, unsigned long phys_addr,
- pgprot_t prot)
-{
- unsigned long pfn;
-
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- WARN_ON(!pte_none(*pte));
-
- set_pte(pte, pfn_pte(pfn, prot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-
- return 0;
-}
-
-static inline int remap_area_pmd(pmd_t *pmd, unsigned long address,
- unsigned long end, unsigned long phys_addr,
- pgprot_t prot)
-{
- unsigned long next;
-
- phys_addr -= address;
-
- do {
- pte_t *pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
-
- next = (address + PMD_SIZE) & PMD_MASK;
- if (remap_area_pte(pte, address, next,
- address + phys_addr, prot))
- return -ENOMEM;
-
- address = next;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pud(pud_t *pud, unsigned long address,
- unsigned long end, unsigned long phys_addr,
- pgprot_t prot)
-{
- unsigned long next;
-
- phys_addr -= address;
-
- do {
- pmd_t *pmd = pmd_alloc(&init_mm, pud, address);
- if (!pmd)
- return -ENOMEM;
- next = (address + PUD_SIZE) & PUD_MASK;
- if (remap_area_pmd(pmd, address, next,
- phys_addr + address, prot))
- return -ENOMEM;
-
- address = next;
- pud++;
- } while (address && address < end);
-
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- size_t size, pgprot_t prot)
-{
- unsigned long end = address + size;
- unsigned long next;
- pgd_t *pgd;
- int err = 0;
-
- phys_addr -= address;
-
- pgd = pgd_offset_k(address);
- flush_cache_all();
- BUG_ON(address >= end);
-
- spin_lock(&init_mm.page_table_lock);
- do {
- pud_t *pud = pud_alloc(&init_mm, pgd, address);
-
- err = -ENOMEM;
- if (!pud)
- break;
-
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next < address || next > end)
- next = end;
- err = remap_area_pud(pud, address, next,
- phys_addr + address, prot);
- if (err)
- break;
-
- address = next;
- pgd++;
- } while (address && (address < end));
-
- spin_unlock(&init_mm.page_table_lock);
- flush_tlb_all();
- return err;
-}
-
/*
* Re-map an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access physical
@@ -128,7 +20,7 @@ static int remap_area_pages(unsigned lon
void __iomem *__ioremap(unsigned long phys_addr, size_t size,
unsigned long flags)
{
- void *addr;
+ unsigned long addr;
struct vm_struct *area;
unsigned long offset, last_addr;
pgprot_t prot;
@@ -159,7 +51,7 @@ void __iomem *__ioremap(unsigned long ph
phys_addr &= PAGE_MASK;
size = PAGE_ALIGN(last_addr + 1) - phys_addr;

- prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
+ prot = __pgprot(_PAGE_PRESENT | _PAGE_GLOBAL | _PAGE_RW | _PAGE_DIRTY
| _PAGE_ACCESSED | _PAGE_TYPE_SMALL | flags);

/*
@@ -169,9 +61,9 @@ void __iomem *__ioremap(unsigned long ph
if (!area)
return NULL;
area->phys_addr = phys_addr;
- addr = area->addr;
- if (remap_area_pages((unsigned long)addr, phys_addr, size, prot)) {
- vunmap(addr);
+ addr = (unsigned long )area->addr;
+ if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+ vunmap((void *)addr);
return NULL;
}

--
1.4.0

2006-08-10 16:06:43

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 14/14] Generic ioremap_page_range: x86_64 conversion

From: Andi Kleen <[email protected]>

Convert x86_64 to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
Acked-by: Andi Kleen <[email protected]>
---
arch/x86_64/mm/ioremap.c | 110 +++-------------------------------------------
1 files changed, 6 insertions(+), 104 deletions(-)

diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 45d7d82..6bb0712 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -12,117 +12,15 @@ #include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
#include <asm/fixmap.h>
-#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/proto.h>

#define ISA_START_ADDRESS 0xa0000
#define ISA_END_ADDRESS 0x100000

-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_GLOBAL | _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static inline int remap_area_pud(pud_t * pud, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pmd_t * pmd = pmd_alloc(&init_mm, pud, address);
- if (!pmd)
- return -ENOMEM;
- remap_area_pmd(pmd, address, end - address, address + phys_addr, flags);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t *pgd;
- unsigned long end = address + size;
-
- phys_addr -= address;
- pgd = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pud_t *pud;
- pud = pud_alloc(&init_mm, pgd, address);
- error = -ENOMEM;
- if (!pud)
- break;
- if (remap_area_pud(pud, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- pgd++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}
-
/*
* Fix up the linear direct mapping of the kernel to avoid cache attribute
* conflicts.
@@ -165,6 +63,7 @@ void __iomem * __ioremap(unsigned long p
void * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -194,6 +93,8 @@ #ifdef CONFIG_FLATMEM
}
#endif

+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_GLOBAL
+ | _PAGE_DIRTY | _PAGE_ACCESSED | flags);
/*
* Mappings have to be page-aligned
*/
@@ -209,7 +110,8 @@ #endif
return NULL;
area->phys_addr = phys_addr;
addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, pgprot)) {
remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
return NULL;
}
--
1.4.0

2006-08-10 16:06:46

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 11/14] Generic ioremap_page_range: s390 conversion

From: Martin Schwidefsky <[email protected]>

Convert S390 to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/s390/mm/ioremap.c | 84 ++----------------------------------------------
1 files changed, 3 insertions(+), 81 deletions(-)

diff --git a/arch/s390/mm/ioremap.c b/arch/s390/mm/ioremap.c
index 0f6e9ec..3d2100a 100644
--- a/arch/s390/mm/ioremap.c
+++ b/arch/s390/mm/ioremap.c
@@ -15,87 +15,8 @@

#include <linux/vmalloc.h>
#include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, __pgprot(flags)));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return 0;
-}

/*
* Generic mapping function (not visible outside):
@@ -122,7 +43,8 @@ void * __ioremap(unsigned long phys_addr
if (!area)
return NULL;
addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, __pgprot(flags))) {
vfree(addr);
return NULL;
}
--
1.4.0

2006-08-10 16:07:41

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 7/14] Generic ioremap_page_range: i386 conversion

From: Andi Kleen <[email protected]>

Convert i386 to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
Acked-by: Andi Kleen <[email protected]>
---
arch/i386/mm/ioremap.c | 85 +++---------------------------------------------
1 files changed, 6 insertions(+), 79 deletions(-)

diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 247fde7..f773126 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -12,91 +12,14 @@ #include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/fixmap.h>
-#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/pgtable.h>

#define ISA_START_ADDRESS 0xa0000
#define ISA_END_ADDRESS 0x100000

-static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
- unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
- pte_t *pte;
- unsigned long pfn;
-
- pfn = phys_addr >> PAGE_SHIFT;
- pte = pte_alloc_kernel(pmd, addr);
- if (!pte)
- return -ENOMEM;
- do {
- BUG_ON(!pte_none(*pte));
- set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
- pfn++;
- } while (pte++, addr += PAGE_SIZE, addr != end);
- return 0;
-}
-
-static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
- unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
- pmd_t *pmd;
- unsigned long next;
-
- phys_addr -= addr;
- pmd = pmd_alloc(&init_mm, pud, addr);
- if (!pmd)
- return -ENOMEM;
- do {
- next = pmd_addr_end(addr, end);
- if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, flags))
- return -ENOMEM;
- } while (pmd++, addr = next, addr != end);
- return 0;
-}
-
-static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
- unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
- pud_t *pud;
- unsigned long next;
-
- phys_addr -= addr;
- pud = pud_alloc(&init_mm, pgd, addr);
- if (!pud)
- return -ENOMEM;
- do {
- next = pud_addr_end(addr, end);
- if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, flags))
- return -ENOMEM;
- } while (pud++, addr = next, addr != end);
- return 0;
-}
-
-static int ioremap_page_range(unsigned long addr,
- unsigned long end, unsigned long phys_addr, unsigned long flags)
-{
- pgd_t *pgd;
- unsigned long next;
- int err;
-
- BUG_ON(addr >= end);
- flush_cache_all();
- phys_addr -= addr;
- pgd = pgd_offset_k(addr);
- do {
- next = pgd_addr_end(addr, end);
- err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
- if (err)
- break;
- } while (pgd++, addr = next, addr != end);
- flush_tlb_all();
- return err;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -115,6 +38,7 @@ void __iomem * __ioremap(unsigned long p
void __iomem * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t prot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -142,6 +66,9 @@ void __iomem * __ioremap(unsigned long p
return NULL;
}

+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
+ | _PAGE_ACCESSED | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -158,7 +85,7 @@ void __iomem * __ioremap(unsigned long p
area->phys_addr = phys_addr;
addr = (void __iomem *) area->addr;
if (ioremap_page_range((unsigned long) addr,
- (unsigned long) addr + size, phys_addr, flags)) {
+ (unsigned long) addr + size, phys_addr, prot)) {
vunmap((void __force *) addr);
return NULL;
}
--
1.4.0

2006-08-10 16:07:22

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 12/14] Generic ioremap_page_range: sh conversion

From: Paul Mundt <[email protected]>

Convert SH to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/sh/mm/ioremap.c | 97 ++++----------------------------------------------
1 files changed, 7 insertions(+), 90 deletions(-)

diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index 96fa4a9..5ef9245 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -15,98 +15,10 @@
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/addrspace.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void remap_area_pte(pte_t * pte, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_DIRTY | _PAGE_ACCESSED |
- _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address,
- unsigned long size, unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset_k(address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pud_t *pud;
- pmd_t *pmd;
-
- 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))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}

/*
* Remap an arbitrary physical address space into the kernel virtual
@@ -122,6 +34,7 @@ void __iomem *__ioremap(unsigned long ph
{
struct vm_struct * area;
unsigned long offset, last_addr, addr, orig_addr;
+ pgprot_t pgprot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -177,8 +90,12 @@ #ifdef CONFIG_32BIT
}
#endif

+ pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW |
+ _PAGE_DIRTY | _PAGE_ACCESSED |
+ _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags);
+
if (likely(size))
- if (remap_area_pages(addr, phys_addr, size, flags)) {
+ if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
vunmap((void *)orig_addr);
return NULL;
}
--
1.4.0

2006-08-10 16:08:45

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 6/14] Generic ioremap_page_range: cris conversion

From: Mikael Starvik <[email protected]>

Convert CRIS to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
Acked-by: Mikael Starvik <[email protected]>
---
arch/cris/mm/ioremap.c | 88 ++----------------------------------------------
1 files changed, 3 insertions(+), 85 deletions(-)

diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index 1780df3..8b0b934 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -10,93 +10,10 @@
*/

#include <linux/vmalloc.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
#include <asm/arch/memmap.h>

-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;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, prot));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, pgprot_t prot)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, prot);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, pgprot_t prot)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pud_t *pud;
- pmd_t *pmd;
-
- 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, prot))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}
-
/*
* Generic mapping function (not visible outside):
*/
@@ -135,7 +52,8 @@ void __iomem * __ioremap_prot(unsigned l
if (!area)
return NULL;
addr = (void __iomem *)area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, prot)) {
vfree((void __force *)addr);
return NULL;
}
--
1.4.0

2006-08-10 16:09:07

by Haavard Skinnemoen

[permalink] [raw]
Subject: Re: [PATCH 3/14] Generic ioremap_page_range: alpha conversion

On Thu, 10 Aug 2006 18:03:35 +0200
Haavard Skinnemoen <[email protected]> wrote:

> From: Richard Henderson <[email protected]>

Uh...does anyone have an idea why git-send-email added this line for
me? All I did was add a Cc line to the mbox like this:

Cc: Richard Henderson <[email protected]>

> Convert Alpha to use generic ioremap_page_range() by turning
> __alpha_remap_area_pages() into an inline wrapper around
> ioremap_page_range().
>
> Signed-off-by: Haavard Skinnemoen <[email protected]>

Håvard

2006-08-10 16:08:31

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 4/14] Generic ioremap_page_range: arm conversion

From: Russell King <[email protected]>

Convert ARM to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---
arch/arm/mm/ioremap.c | 95 +++----------------------------------------------
1 files changed, 5 insertions(+), 90 deletions(-)

diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 88a999d..942a1ee 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -22,11 +22,11 @@
*/
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/io.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>

#include <asm/cacheflush.h>
-#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -38,94 +38,6 @@ #include <asm/sizes.h>
*/
#define VM_ARM_SECTION_MAPPING 0x80000000

-static inline void
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, pgprot_t pgprot)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- BUG_ON(address >= end);
- do {
- if (!pte_none(*pte))
- goto bad;
-
- set_pte(pte, pfn_pte(phys_addr >> PAGE_SHIFT, pgprot));
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
- return;
-
- bad:
- printk("remap_area_pte: page already exists\n");
- BUG();
-}
-
-static inline int
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- pgprot_t pgprot;
-
- address &= ~PGDIR_MASK;
- end = address + size;
-
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
-
- phys_addr -= address;
- BUG_ON(address >= end);
-
- pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int
-remap_area_pages(unsigned long start, unsigned long pfn,
- unsigned long size, unsigned long flags)
-{
- unsigned long address = start;
- unsigned long end = start + size;
- unsigned long phys_addr = __pfn_to_phys(pfn);
- int err = 0;
- pgd_t * dir;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- BUG_ON(address >= end);
- do {
- pmd_t *pmd = pmd_alloc(&init_mm, dir, address);
- if (!pmd) {
- err = -ENOMEM;
- break;
- }
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags)) {
- err = -ENOMEM;
- break;
- }
-
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
-
- return err;
-}
-
-
void __check_kvm_seq(struct mm_struct *mm)
{
unsigned int seq;
@@ -326,7 +238,10 @@ #ifndef CONFIG_SMP
err = remap_area_sections(addr, pfn, size, flags);
} else
#endif
- err = remap_area_pages(addr, pfn, size, flags);
+ err = ioremap_page_range(addr, addr + size, pfn << PAGE_SHIFT,
+ __pgprot(L_PTE_PRESENT | L_PTE_YOUNG
+ | L_PTE_DIRTY | L_PTE_WRITE
+ | flags));

if (err) {
vunmap((void *)addr);
--
1.4.0

2006-08-10 16:09:27

by Haavard Skinnemoen

[permalink] [raw]
Subject: [PATCH 8/14] Generic ioremap_page_range: m32r conversion

From: [email protected]

Convert m32r to use generic ioremap_page_range()

Signed-off-by: Haavard Skinnemoen <[email protected]>
---

m32r doesn't have a MAINTAINERS entry, so I'm Cc'ing the list.

arch/m32r/mm/ioremap.c | 93 ++++--------------------------------------------
1 files changed, 7 insertions(+), 86 deletions(-)

diff --git a/arch/m32r/mm/ioremap.c b/arch/m32r/mm/ioremap.c
index a151849..5152c4e 100644
--- a/arch/m32r/mm/ioremap.c
+++ b/arch/m32r/mm/ioremap.c
@@ -20,92 +20,8 @@ #include <asm/addrspace.h>
#include <asm/byteorder.h>

#include <linux/vmalloc.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-static inline void
-remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
- unsigned long pfn;
- pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
- | _PAGE_WRITE | flags);
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
- pfn = phys_addr >> PAGE_SHIFT;
- do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, pfn_pte(pfn, pgprot));
- address += PAGE_SIZE;
- pfn++;
- pte++;
- } while (address && (address < end));
-}
-
-static inline int
-remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
- do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
- if (!pte)
- return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return 0;
-}
-
-static int
-remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
-{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
-
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
- flush_cache_all();
- if (address >= end)
- BUG();
- do {
- pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
- error = -ENOMEM;
- if (!pmd)
- break;
- if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
- break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
- flush_tlb_all();
- return error;
-}

/*
* Generic mapping function (not visible outside):
@@ -129,6 +45,7 @@ __ioremap(unsigned long phys_addr, unsig
void __iomem * addr;
struct vm_struct * area;
unsigned long offset, last_addr;
+ pgprot_t pgprot;

/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -157,6 +74,9 @@ __ioremap(unsigned long phys_addr, unsig
return NULL;
}

+ pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
+ | _PAGE_WRITE | flags);
+
/*
* Mappings have to be page-aligned
*/
@@ -172,7 +92,8 @@ __ioremap(unsigned long phys_addr, unsig
return NULL;
area->phys_addr = phys_addr;
addr = (void __iomem *) area->addr;
- if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
+ phys_addr, pgprot)) {
vunmap((void __force *) addr);
return NULL;
}
--
1.4.0

2006-08-10 16:53:55

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH 7/14] Generic ioremap_page_range: i386 conversion

On Thursday 10 August 2006 18:03, Haavard Skinnemoen wrote:
> From: Andi Kleen <[email protected]>

Hmm? I didn't write this patch.

> Convert i386 to use generic ioremap_page_range()

-Andi


> Signed-off-by: Haavard Skinnemoen <[email protected]>
> Acked-by: Andi Kleen <[email protected]>

2006-08-10 16:54:26

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH 14/14] Generic ioremap_page_range: x86_64 conversion

On Thursday 10 August 2006 18:03, Haavard Skinnemoen wrote:
> From: Andi Kleen <[email protected]>

That one neither. Why are you forging patch authors?

-Andi

2006-08-10 17:39:30

by Håvard Skinnemoen

[permalink] [raw]
Subject: Re: [PATCH 7/14] Generic ioremap_page_range: i386 conversion

On 8/10/06, Andi Kleen <[email protected]> wrote:
> On Thursday 10 August 2006 18:03, Haavard Skinnemoen wrote:
> > From: Andi Kleen <[email protected]>
>
> Hmm? I didn't write this patch.

No, the original patch didn't have that line. I must have messed up
something with git-send-email...

H?vard

2006-08-10 18:42:22

by Håvard Skinnemoen

[permalink] [raw]
Subject: Re: [PATCH 0/14] Generic ioremap_page_range: introduction

On 8/10/06, Haavard Skinnemoen <[email protected]> wrote:
> Hopefully at least -- I'm not 100% confident with
> git-send-email yet, but I'm getting there :)

Apparently, I still have a long way to go. It looks like
git-send-email inserts a bogus "From:" line in patches with a Cc: line
in the mbox header.

I'll submit a patch to the git mailing list tomorrow, and then I'll
resend the bad patches manually. I'm terribly sorry for the noise.

Haavard

2006-08-10 18:52:29

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH 0/14] Generic ioremap_page_range: introduction

On Thu, 10 Aug 2006 20:42:19 +0200
"H__vard Skinnemoen" <[email protected]> wrote:

> I'll submit a patch to the git mailing list tomorrow, and then I'll
> resend the bad patches manually.

Is OK, I'll fix them up. I assume they're all really From:yourself?

2006-08-10 18:56:45

by Håvard Skinnemoen

[permalink] [raw]
Subject: Re: [PATCH 0/14] Generic ioremap_page_range: introduction

On 8/10/06, Andrew Morton <[email protected]> wrote:
> On Thu, 10 Aug 2006 20:42:19 +0200
> "H__vard Skinnemoen" <[email protected]> wrote:

(wonder why gmail keeps resetting my name all the time...this is the
third time I'm changing it to "Haavard Skinnemoen")

> > I'll submit a patch to the git mailing list tomorrow, and then I'll
> > resend the bad patches manually.
>
> Is OK, I'll fix them up. I assume they're all really From:yourself?

Thanks. They're all from me, yes.

Haavard

2006-08-14 07:20:05

by Russell King

[permalink] [raw]
Subject: Re: [PATCH 4/14] Generic ioremap_page_range: arm conversion

On Thu, Aug 10, 2006 at 06:03:36PM +0200, Haavard Skinnemoen wrote:
> From: Russell King <[email protected]>
>
> Convert ARM to use generic ioremap_page_range()

NAK. There are already issues with using the xxx_kernel variants of
the page table functions for IO mappings on later architectures (caused
by speculative loads hitting IO regions.) This code needs to change
slightly so that we have xxx_io versions of pte_alloc and friends.

(It also means that we need an ioremap region and a separate vmalloc
region on ARM...)

--
Russell King
Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/
maintainer of: 2.6 Serial core