aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/ioremap.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2011-12-08 13:02:04 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-12-08 13:02:04 -0500
commit6ae25a5b9d7ba86d6ac19c403dfa57dae6caa73d (patch)
tree41d04269f268d6162e5f1866496dd42fbc79d2a4 /arch/arm/mm/ioremap.c
parent3ee0fc5ca129cbae81c073756febcb1c552af446 (diff)
parent497b7e943d0dc5743454de56dcdb67352bbf96b2 (diff)
Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux into devel-stable
Conflicts: arch/arm/mm/ioremap.c
Diffstat (limited to 'arch/arm/mm/ioremap.c')
-rw-r--r--arch/arm/mm/ioremap.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 12c7ad215ce7..80632e8d7538 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -58,7 +58,7 @@ void __check_kvm_seq(struct mm_struct *mm)
58 } while (seq != init_mm.context.kvm_seq); 58 } while (seq != init_mm.context.kvm_seq);
59} 59}
60 60
61#ifndef CONFIG_SMP 61#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
62/* 62/*
63 * Section support is unsafe on SMP - If you iounmap and ioremap a region, 63 * Section support is unsafe on SMP - If you iounmap and ioremap a region,
64 * the other CPUs will not see this change until their next context switch. 64 * the other CPUs will not see this change until their next context switch.
@@ -73,13 +73,16 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
73{ 73{
74 unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1)); 74 unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1));
75 pgd_t *pgd; 75 pgd_t *pgd;
76 pud_t *pud;
77 pmd_t *pmdp;
76 78
77 flush_cache_vunmap(addr, end); 79 flush_cache_vunmap(addr, end);
78 pgd = pgd_offset_k(addr); 80 pgd = pgd_offset_k(addr);
81 pud = pud_offset(pgd, addr);
82 pmdp = pmd_offset(pud, addr);
79 do { 83 do {
80 pmd_t pmd, *pmdp = pmd_offset(pgd, addr); 84 pmd_t pmd = *pmdp;
81 85
82 pmd = *pmdp;
83 if (!pmd_none(pmd)) { 86 if (!pmd_none(pmd)) {
84 /* 87 /*
85 * Clear the PMD from the page table, and 88 * Clear the PMD from the page table, and
@@ -98,8 +101,8 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
98 pte_free_kernel(&init_mm, pmd_page_vaddr(pmd)); 101 pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
99 } 102 }
100 103
101 addr += PGDIR_SIZE; 104 addr += PMD_SIZE;
102 pgd++; 105 pmdp += 2;
103 } while (addr < end); 106 } while (addr < end);
104 107
105 /* 108 /*
@@ -118,6 +121,8 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
118{ 121{
119 unsigned long addr = virt, end = virt + size; 122 unsigned long addr = virt, end = virt + size;
120 pgd_t *pgd; 123 pgd_t *pgd;
124 pud_t *pud;
125 pmd_t *pmd;
121 126
122 /* 127 /*
123 * Remove and free any PTE-based mapping, and 128 * Remove and free any PTE-based mapping, and
@@ -126,17 +131,17 @@ remap_area_sections(unsigned long virt, unsigned long pfn,
126 unmap_area_sections(virt, size); 131 unmap_area_sections(virt, size);
127 132
128 pgd = pgd_offset_k(addr); 133 pgd = pgd_offset_k(addr);
134 pud = pud_offset(pgd, addr);
135 pmd = pmd_offset(pud, addr);
129 do { 136 do {
130 pmd_t *pmd = pmd_offset(pgd, addr);
131
132 pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); 137 pmd[0] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
133 pfn += SZ_1M >> PAGE_SHIFT; 138 pfn += SZ_1M >> PAGE_SHIFT;
134 pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect); 139 pmd[1] = __pmd(__pfn_to_phys(pfn) | type->prot_sect);
135 pfn += SZ_1M >> PAGE_SHIFT; 140 pfn += SZ_1M >> PAGE_SHIFT;
136 flush_pmd_entry(pmd); 141 flush_pmd_entry(pmd);
137 142
138 addr += PGDIR_SIZE; 143 addr += PMD_SIZE;
139 pgd++; 144 pmd += 2;
140 } while (addr < end); 145 } while (addr < end);
141 146
142 return 0; 147 return 0;
@@ -148,6 +153,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
148{ 153{
149 unsigned long addr = virt, end = virt + size; 154 unsigned long addr = virt, end = virt + size;
150 pgd_t *pgd; 155 pgd_t *pgd;
156 pud_t *pud;
157 pmd_t *pmd;
151 158
152 /* 159 /*
153 * Remove and free any PTE-based mapping, and 160 * Remove and free any PTE-based mapping, and
@@ -156,6 +163,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
156 unmap_area_sections(virt, size); 163 unmap_area_sections(virt, size);
157 164
158 pgd = pgd_offset_k(virt); 165 pgd = pgd_offset_k(virt);
166 pud = pud_offset(pgd, addr);
167 pmd = pmd_offset(pud, addr);
159 do { 168 do {
160 unsigned long super_pmd_val, i; 169 unsigned long super_pmd_val, i;
161 170
@@ -164,14 +173,12 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
164 super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20; 173 super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20;
165 174
166 for (i = 0; i < 8; i++) { 175 for (i = 0; i < 8; i++) {
167 pmd_t *pmd = pmd_offset(pgd, addr);
168
169 pmd[0] = __pmd(super_pmd_val); 176 pmd[0] = __pmd(super_pmd_val);
170 pmd[1] = __pmd(super_pmd_val); 177 pmd[1] = __pmd(super_pmd_val);
171 flush_pmd_entry(pmd); 178 flush_pmd_entry(pmd);
172 179
173 addr += PGDIR_SIZE; 180 addr += PMD_SIZE;
174 pgd++; 181 pmd += 2;
175 } 182 }
176 183
177 pfn += SUPERSECTION_SIZE >> PAGE_SHIFT; 184 pfn += SUPERSECTION_SIZE >> PAGE_SHIFT;
@@ -189,11 +196,13 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
189 unsigned long addr; 196 unsigned long addr;
190 struct vm_struct * area; 197 struct vm_struct * area;
191 198
199#ifndef CONFIG_ARM_LPAE
192 /* 200 /*
193 * High mappings must be supersection aligned 201 * High mappings must be supersection aligned
194 */ 202 */
195 if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) 203 if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
196 return NULL; 204 return NULL;
205#endif
197 206
198 type = get_mem_type(mtype); 207 type = get_mem_type(mtype);
199 if (!type) 208 if (!type)
@@ -237,7 +246,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
237 return NULL; 246 return NULL;
238 addr = (unsigned long)area->addr; 247 addr = (unsigned long)area->addr;
239 248
240#ifndef CONFIG_SMP 249#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
241 if (DOMAIN_IO == 0 && 250 if (DOMAIN_IO == 0 &&
242 (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || 251 (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
243 cpu_is_xsc3()) && pfn >= 0x100000 && 252 cpu_is_xsc3()) && pfn >= 0x100000 &&
@@ -343,7 +352,7 @@ void __iounmap(volatile void __iomem *io_addr)
343 read_unlock(&vmlist_lock); 352 read_unlock(&vmlist_lock);
344 return; 353 return;
345 } 354 }
346#ifndef CONFIG_SMP 355#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
347 /* 356 /*
348 * If this is a section based mapping we need to handle it 357 * If this is a section based mapping we need to handle it
349 * specially as the VM subsystem does not know how to handle 358 * specially as the VM subsystem does not know how to handle