diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2006-12-08 05:38:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:52 -0500 |
commit | 5b3e1a85c2145813898ac50530c70e6d03a6aa19 (patch) | |
tree | 9a5738f026dd86d7a896b4359ea9c6e0e2d38caa | |
parent | a151ca62d7c28d67a8ca0e950452b5208d1d572d (diff) |
[PATCH] Generic ioremap_page_range: sh conversion
Convert SH to use generic ioremap_page_range()
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/sh/mm/ioremap.c | 90 |
1 files changed, 4 insertions, 86 deletions
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index 11d54c149821..90b494a0cf45 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c | |||
@@ -16,97 +16,13 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <asm/io.h> | 19 | #include <linux/io.h> |
20 | #include <asm/page.h> | 20 | #include <asm/page.h> |
21 | #include <asm/pgalloc.h> | 21 | #include <asm/pgalloc.h> |
22 | #include <asm/addrspace.h> | 22 | #include <asm/addrspace.h> |
23 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
24 | #include <asm/tlbflush.h> | 24 | #include <asm/tlbflush.h> |
25 | 25 | ||
26 | static inline void remap_area_pte(pte_t * pte, unsigned long address, | ||
27 | unsigned long size, unsigned long phys_addr, unsigned long flags) | ||
28 | { | ||
29 | unsigned long end; | ||
30 | unsigned long pfn; | ||
31 | pgprot_t pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); | ||
32 | |||
33 | address &= ~PMD_MASK; | ||
34 | end = address + size; | ||
35 | if (end > PMD_SIZE) | ||
36 | end = PMD_SIZE; | ||
37 | if (address >= end) | ||
38 | BUG(); | ||
39 | pfn = phys_addr >> PAGE_SHIFT; | ||
40 | do { | ||
41 | if (!pte_none(*pte)) { | ||
42 | printk("remap_area_pte: page already exists\n"); | ||
43 | BUG(); | ||
44 | } | ||
45 | set_pte(pte, pfn_pte(pfn, pgprot)); | ||
46 | address += PAGE_SIZE; | ||
47 | pfn++; | ||
48 | pte++; | ||
49 | } while (address && (address < end)); | ||
50 | } | ||
51 | |||
52 | static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, | ||
53 | unsigned long size, unsigned long phys_addr, unsigned long flags) | ||
54 | { | ||
55 | unsigned long end; | ||
56 | |||
57 | address &= ~PGDIR_MASK; | ||
58 | end = address + size; | ||
59 | if (end > PGDIR_SIZE) | ||
60 | end = PGDIR_SIZE; | ||
61 | phys_addr -= address; | ||
62 | if (address >= end) | ||
63 | BUG(); | ||
64 | do { | ||
65 | pte_t * pte = pte_alloc_kernel(pmd, address); | ||
66 | if (!pte) | ||
67 | return -ENOMEM; | ||
68 | remap_area_pte(pte, address, end - address, address + phys_addr, flags); | ||
69 | address = (address + PMD_SIZE) & PMD_MASK; | ||
70 | pmd++; | ||
71 | } while (address && (address < end)); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int remap_area_pages(unsigned long address, unsigned long phys_addr, | ||
76 | unsigned long size, unsigned long flags) | ||
77 | { | ||
78 | int error; | ||
79 | pgd_t * dir; | ||
80 | unsigned long end = address + size; | ||
81 | |||
82 | phys_addr -= address; | ||
83 | dir = pgd_offset_k(address); | ||
84 | flush_cache_all(); | ||
85 | if (address >= end) | ||
86 | BUG(); | ||
87 | do { | ||
88 | pud_t *pud; | ||
89 | pmd_t *pmd; | ||
90 | |||
91 | error = -ENOMEM; | ||
92 | |||
93 | pud = pud_alloc(&init_mm, dir, address); | ||
94 | if (!pud) | ||
95 | break; | ||
96 | pmd = pmd_alloc(&init_mm, pud, address); | ||
97 | if (!pmd) | ||
98 | break; | ||
99 | if (remap_area_pmd(pmd, address, end - address, | ||
100 | phys_addr + address, flags)) | ||
101 | break; | ||
102 | error = 0; | ||
103 | address = (address + PGDIR_SIZE) & PGDIR_MASK; | ||
104 | dir++; | ||
105 | } while (address && (address < end)); | ||
106 | flush_tlb_all(); | ||
107 | return error; | ||
108 | } | ||
109 | |||
110 | /* | 26 | /* |
111 | * Remap an arbitrary physical address space into the kernel virtual | 27 | * Remap an arbitrary physical address space into the kernel virtual |
112 | * address space. Needed when the kernel wants to access high addresses | 28 | * address space. Needed when the kernel wants to access high addresses |
@@ -121,6 +37,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, | |||
121 | { | 37 | { |
122 | struct vm_struct * area; | 38 | struct vm_struct * area; |
123 | unsigned long offset, last_addr, addr, orig_addr; | 39 | unsigned long offset, last_addr, addr, orig_addr; |
40 | pgprot_t pgprot; | ||
124 | 41 | ||
125 | /* Don't allow wraparound or zero size */ | 42 | /* Don't allow wraparound or zero size */ |
126 | last_addr = phys_addr + size - 1; | 43 | last_addr = phys_addr + size - 1; |
@@ -190,8 +107,9 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, | |||
190 | } | 107 | } |
191 | #endif | 108 | #endif |
192 | 109 | ||
110 | pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); | ||
193 | if (likely(size)) | 111 | if (likely(size)) |
194 | if (remap_area_pages(addr, phys_addr, size, flags)) { | 112 | if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { |
195 | vunmap((void *)orig_addr); | 113 | vunmap((void *)orig_addr); |
196 | return NULL; | 114 | return NULL; |
197 | } | 115 | } |