aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-18 23:34:38 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-18 23:34:38 -0500
commitd57d64080ddc0ff13fcffc898b6251074a482ba1 (patch)
treec38fd506a30d56de84a39285412ffc1b45cc8d33 /arch/sh
parentaf1415314a4190b8ea06e53808d392fcf91555af (diff)
sh: Prevent 64-bit pgprot clobbering across ioremap implementations.
Presently 'flags' gets passed around a lot between the various ioremap helpers and implementations, which is only 32-bits. In the X2TLB case we use 64-bit pgprots which presently results in the upper 32bits being chopped off (which handily include our read/write/exec permissions). As such, we convert everything internally to using pgprot_t directly and simply convert over with pgprot_val() where needed. With this in place, transparent fixmap utilization for early ioremap works as expected. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/boards/board-sh7785lcr.c6
-rw-r--r--arch/sh/boards/mach-landisk/setup.c2
-rw-r--r--arch/sh/boards/mach-lboxre2/setup.c2
-rw-r--r--arch/sh/boards/mach-sh03/setup.c2
-rw-r--r--arch/sh/include/asm/io.h53
-rw-r--r--arch/sh/mm/ioremap.c9
6 files changed, 41 insertions, 33 deletions
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 511de38d2046..fe7e686c94ac 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -21,6 +21,7 @@
21#include <linux/i2c-algo-pca.h> 21#include <linux/i2c-algo-pca.h>
22#include <linux/usb/r8a66597.h> 22#include <linux/usb/r8a66597.h>
23#include <linux/irq.h> 23#include <linux/irq.h>
24#include <linux/io.h>
24#include <linux/clk.h> 25#include <linux/clk.h>
25#include <linux/errno.h> 26#include <linux/errno.h>
26#include <mach/sh7785lcr.h> 27#include <mach/sh7785lcr.h>
@@ -332,15 +333,14 @@ static void __init sh7785lcr_setup(char **cmdline_p)
332 pm_power_off = sh7785lcr_power_off; 333 pm_power_off = sh7785lcr_power_off;
333 334
334 /* sm501 DRAM configuration */ 335 /* sm501 DRAM configuration */
335 sm501_reg = ioremap_fixed(SM107_REG_ADDR, SM501_DRAM_CONTROL, 336 sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL);
336 PAGE_KERNEL);
337 if (!sm501_reg) { 337 if (!sm501_reg) {
338 printk(KERN_ERR "%s: ioremap error.\n", __func__); 338 printk(KERN_ERR "%s: ioremap error.\n", __func__);
339 return; 339 return;
340 } 340 }
341 341
342 writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL); 342 writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL);
343 iounmap_fixed(sm501_reg); 343 iounmap(sm501_reg);
344} 344}
345 345
346/* Return the board specific boot mode pin configuration */ 346/* Return the board specific boot mode pin configuration */
diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c
index db22ea2e6d49..59816355d199 100644
--- a/arch/sh/boards/mach-landisk/setup.c
+++ b/arch/sh/boards/mach-landisk/setup.c
@@ -63,7 +63,7 @@ static int __init landisk_devices_setup(void)
63 /* open I/O area window */ 63 /* open I/O area window */
64 paddrbase = virt_to_phys((void *)PA_AREA5_IO); 64 paddrbase = virt_to_phys((void *)PA_AREA5_IO);
65 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); 65 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
66 cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); 66 cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot);
67 if (!cf_ide_base) { 67 if (!cf_ide_base) {
68 printk("allocate_cf_area : can't open CF I/O window!\n"); 68 printk("allocate_cf_area : can't open CF I/O window!\n");
69 return -ENOMEM; 69 return -ENOMEM;
diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c
index 2b0b5818e1e4..408dd5df7d45 100644
--- a/arch/sh/boards/mach-lboxre2/setup.c
+++ b/arch/sh/boards/mach-lboxre2/setup.c
@@ -57,7 +57,7 @@ static int __init lboxre2_devices_setup(void)
57 paddrbase = virt_to_phys((void*)PA_AREA5_IO); 57 paddrbase = virt_to_phys((void*)PA_AREA5_IO);
58 psize = PAGE_SIZE; 58 psize = PAGE_SIZE;
59 prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16); 59 prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16);
60 cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot.pgprot); 60 cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot);
61 if (!cf0_io_base) { 61 if (!cf0_io_base) {
62 printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ ); 62 printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ );
63 return -ENOMEM; 63 return -ENOMEM;
diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c
index 74cfb4b8b03d..f14ba0fa950b 100644
--- a/arch/sh/boards/mach-sh03/setup.c
+++ b/arch/sh/boards/mach-sh03/setup.c
@@ -82,7 +82,7 @@ static int __init sh03_devices_setup(void)
82 /* open I/O area window */ 82 /* open I/O area window */
83 paddrbase = virt_to_phys((void *)PA_AREA5_IO); 83 paddrbase = virt_to_phys((void *)PA_AREA5_IO);
84 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); 84 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
85 cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); 85 cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot);
86 if (!cf_ide_base) { 86 if (!cf_ide_base) {
87 printk("allocate_cf_area : can't open CF I/O window!\n"); 87 printk("allocate_cf_area : can't open CF I/O window!\n");
88 return -ENOMEM; 88 return -ENOMEM;
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 6a0dd8c1e0a9..13696dfccc16 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -235,7 +235,7 @@ unsigned long long poke_real_address_q(unsigned long long addr,
235 */ 235 */
236#ifdef CONFIG_MMU 236#ifdef CONFIG_MMU
237void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, 237void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
238 unsigned long flags, void *caller); 238 pgprot_t prot, void *caller);
239void __iounmap(void __iomem *addr); 239void __iounmap(void __iomem *addr);
240 240
241#ifdef CONFIG_IOREMAP_FIXED 241#ifdef CONFIG_IOREMAP_FIXED
@@ -254,13 +254,13 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; }
254#endif 254#endif
255 255
256static inline void __iomem * 256static inline void __iomem *
257__ioremap(unsigned long offset, unsigned long size, unsigned long flags) 257__ioremap(unsigned long offset, unsigned long size, pgprot_t prot)
258{ 258{
259 return __ioremap_caller(offset, size, flags, __builtin_return_address(0)); 259 return __ioremap_caller(offset, size, prot, __builtin_return_address(0));
260} 260}
261 261
262static inline void __iomem * 262static inline void __iomem *
263__ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) 263__ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot)
264{ 264{
265#ifdef CONFIG_29BIT 265#ifdef CONFIG_29BIT
266 unsigned long last_addr = offset + size - 1; 266 unsigned long last_addr = offset + size - 1;
@@ -272,7 +272,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags)
272 * mapping must be done by the PMB or by using page tables. 272 * mapping must be done by the PMB or by using page tables.
273 */ 273 */
274 if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { 274 if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) {
275 if (unlikely(flags & _PAGE_CACHABLE)) 275 if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE))
276 return (void __iomem *)P1SEGADDR(offset); 276 return (void __iomem *)P1SEGADDR(offset);
277 277
278 return (void __iomem *)P2SEGADDR(offset); 278 return (void __iomem *)P2SEGADDR(offset);
@@ -287,7 +287,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags)
287} 287}
288 288
289static inline void __iomem * 289static inline void __iomem *
290__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) 290__ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot)
291{ 291{
292 void __iomem *ret; 292 void __iomem *ret;
293 293
@@ -295,30 +295,39 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
295 if (ret) 295 if (ret)
296 return ret; 296 return ret;
297 297
298 ret = __ioremap_29bit(offset, size, flags); 298 ret = __ioremap_29bit(offset, size, prot);
299 if (ret) 299 if (ret)
300 return ret; 300 return ret;
301 301
302 return __ioremap(offset, size, flags); 302 return __ioremap(offset, size, prot);
303} 303}
304#else 304#else
305#define __ioremap(offset, size, flags) ((void __iomem *)(offset)) 305#define __ioremap(offset, size, prot) ((void __iomem *)(offset))
306#define __ioremap_mode(offset, size, flags) ((void __iomem *)(offset)) 306#define __ioremap_mode(offset, size, prot) ((void __iomem *)(offset))
307#define __iounmap(addr) do { } while (0) 307#define __iounmap(addr) do { } while (0)
308#endif /* CONFIG_MMU */ 308#endif /* CONFIG_MMU */
309 309
310#define ioremap(offset, size) \ 310static inline void __iomem *
311 __ioremap_mode((offset), (size), 0) 311ioremap(unsigned long offset, unsigned long size)
312#define ioremap_nocache(offset, size) \ 312{
313 __ioremap_mode((offset), (size), 0) 313 return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE);
314#define ioremap_cache(offset, size) \ 314}
315 __ioremap_mode((offset), (size), _PAGE_CACHABLE) 315
316#define p3_ioremap(offset, size, flags) \ 316static inline void __iomem *
317 __ioremap((offset), (size), (flags)) 317ioremap_cache(unsigned long offset, unsigned long size)
318#define ioremap_prot(offset, size, flags) \ 318{
319 __ioremap_mode((offset), (size), (flags)) 319 return __ioremap_mode(offset, size, PAGE_KERNEL);
320#define iounmap(addr) \ 320}
321 __iounmap((addr)) 321
322static inline void __iomem *
323ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags)
324{
325 return __ioremap_mode(offset, size, __pgprot(flags));
326}
327
328#define ioremap_nocache ioremap
329#define p3_ioremap __ioremap
330#define iounmap __iounmap
322 331
323#define maybebadio(port) \ 332#define maybebadio(port) \
324 printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ 333 printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index a130b2278e92..85b420d00622 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -35,11 +35,10 @@
35 */ 35 */
36void __iomem * __init_refok 36void __iomem * __init_refok
37__ioremap_caller(unsigned long phys_addr, unsigned long size, 37__ioremap_caller(unsigned long phys_addr, unsigned long size,
38 unsigned long flags, 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 pgprot_t pgprot;
43 42
44 /* Don't allow wraparound or zero size */ 43 /* Don't allow wraparound or zero size */
45 last_addr = phys_addr + size - 1; 44 last_addr = phys_addr + size - 1;
@@ -69,7 +68,7 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
69 * If we can't yet use the regular approach, go the fixmap route. 68 * If we can't yet use the regular approach, go the fixmap route.
70 */ 69 */
71 if (!mem_init_done) 70 if (!mem_init_done)
72 return ioremap_fixed(phys_addr, size, __pgprot(flags)); 71 return ioremap_fixed(phys_addr, size, pgprot);
73 72
74 /* 73 /*
75 * Ok, go for it.. 74 * Ok, go for it..
@@ -91,8 +90,9 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
91 * PMB entries are all pre-faulted. 90 * PMB entries are all pre-faulted.
92 */ 91 */
93 if (unlikely(phys_addr >= P1SEG)) { 92 if (unlikely(phys_addr >= P1SEG)) {
94 unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); 93 unsigned long mapped;
95 94
95 mapped = pmb_remap(addr, phys_addr, size, pgprot_val(pgprot));
96 if (likely(mapped)) { 96 if (likely(mapped)) {
97 addr += mapped; 97 addr += mapped;
98 phys_addr += mapped; 98 phys_addr += mapped;
@@ -101,7 +101,6 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
101 } 101 }
102#endif 102#endif
103 103
104 pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
105 if (likely(size)) 104 if (likely(size))
106 if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { 105 if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
107 vunmap((void *)orig_addr); 106 vunmap((void *)orig_addr);