aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/ioremap.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/ioremap.c')
-rw-r--r--arch/sh/mm/ioremap.c70
1 files changed, 22 insertions, 48 deletions
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index c68d2d7d00a9..1ab2385ecefe 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -34,11 +34,12 @@
34 * caller shouldn't need to know that small detail. 34 * caller shouldn't need to know that small detail.
35 */ 35 */
36void __iomem * __init_refok 36void __iomem * __init_refok
37__ioremap_caller(unsigned long phys_addr, unsigned long size, 37__ioremap_caller(phys_addr_t phys_addr, unsigned long size,
38 pgprot_t pgprot, void *caller) 38 pgprot_t pgprot, void *caller)
39{ 39{
40 struct vm_struct *area; 40 struct vm_struct *area;
41 unsigned long offset, last_addr, addr, orig_addr; 41 unsigned long offset, last_addr, addr, orig_addr;
42 void __iomem *mapped;
42 43
43 /* Don't allow wraparound or zero size */ 44 /* Don't allow wraparound or zero size */
44 last_addr = phys_addr + size - 1; 45 last_addr = phys_addr + size - 1;
@@ -46,6 +47,20 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
46 return NULL; 47 return NULL;
47 48
48 /* 49 /*
50 * If we can't yet use the regular approach, go the fixmap route.
51 */
52 if (!mem_init_done)
53 return ioremap_fixed(phys_addr, size, pgprot);
54
55 /*
56 * First try to remap through the PMB.
57 * PMB entries are all pre-faulted.
58 */
59 mapped = pmb_remap_caller(phys_addr, size, pgprot, caller);
60 if (mapped && !IS_ERR(mapped))
61 return mapped;
62
63 /*
49 * Mappings have to be page-aligned 64 * Mappings have to be page-aligned
50 */ 65 */
51 offset = phys_addr & ~PAGE_MASK; 66 offset = phys_addr & ~PAGE_MASK;
@@ -53,12 +68,6 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
53 size = PAGE_ALIGN(last_addr+1) - phys_addr; 68 size = PAGE_ALIGN(last_addr+1) - phys_addr;
54 69
55 /* 70 /*
56 * If we can't yet use the regular approach, go the fixmap route.
57 */
58 if (!mem_init_done)
59 return ioremap_fixed(phys_addr, offset, size, pgprot);
60
61 /*
62 * Ok, go for it.. 71 * Ok, go for it..
63 */ 72 */
64 area = get_vm_area_caller(size, VM_IOREMAP, caller); 73 area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -67,33 +76,10 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
67 area->phys_addr = phys_addr; 76 area->phys_addr = phys_addr;
68 orig_addr = addr = (unsigned long)area->addr; 77 orig_addr = addr = (unsigned long)area->addr;
69 78
70#ifdef CONFIG_PMB 79 if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
71 /* 80 vunmap((void *)orig_addr);
72 * First try to remap through the PMB once a valid VMA has been 81 return NULL;
73 * established. Smaller allocations (or the rest of the size
74 * remaining after a PMB mapping due to the size not being
75 * perfectly aligned on a PMB size boundary) are then mapped
76 * through the UTLB using conventional page tables.
77 *
78 * PMB entries are all pre-faulted.
79 */
80 if (unlikely(phys_addr >= P1SEG)) {
81 unsigned long mapped;
82
83 mapped = pmb_remap(addr, phys_addr, size, pgprot);
84 if (likely(mapped)) {
85 addr += mapped;
86 phys_addr += mapped;
87 size -= mapped;
88 }
89 } 82 }
90#endif
91
92 if (likely(size))
93 if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
94 vunmap((void *)orig_addr);
95 return NULL;
96 }
97 83
98 return (void __iomem *)(offset + (char *)orig_addr); 84 return (void __iomem *)(offset + (char *)orig_addr);
99} 85}
@@ -133,23 +119,11 @@ void __iounmap(void __iomem *addr)
133 if (iounmap_fixed(addr) == 0) 119 if (iounmap_fixed(addr) == 0)
134 return; 120 return;
135 121
136#ifdef CONFIG_PMB
137 /* 122 /*
138 * Purge any PMB entries that may have been established for this 123 * If the PMB handled it, there's nothing else to do.
139 * mapping, then proceed with conventional VMA teardown.
140 *
141 * XXX: Note that due to the way that remove_vm_area() does
142 * matching of the resultant VMA, we aren't able to fast-forward
143 * the address past the PMB space until the end of the VMA where
144 * the page tables reside. As such, unmap_vm_area() will be
145 * forced to linearly scan over the area until it finds the page
146 * tables where PTEs that need to be unmapped actually reside,
147 * which is far from optimal. Perhaps we need to use a separate
148 * VMA for the PMB mappings?
149 * -- PFM.
150 */ 124 */
151 pmb_unmap(vaddr); 125 if (pmb_unmap(addr) == 0)
152#endif 126 return;
153 127
154 p = remove_vm_area((void *)(vaddr & PAGE_MASK)); 128 p = remove_vm_area((void *)(vaddr & PAGE_MASK));
155 if (!p) { 129 if (!p) {