diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2011-01-11 01:02:59 -0500 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-11 01:02:59 -0500 |
| commit | efb3e34b6176d30c4fe8635fa8e1beb6280cc2cd (patch) | |
| tree | e5ed3fee988e3816a9f4ea47bf83970a010cb83e /arch | |
| parent | 11e1ed6e88616be5489a43bc6297d9bb8464908b (diff) | |
sh: Fix up legacy PTEA space attribute mapping.
When p3_ioremap() was converted to ioremap_prot() there was some breakage
introduced where the 29-bit segmentation logic would trap the area range
and return an identity mapping without having allowed the area
specification to force mapping through page tables. This wires up a PCC
mask for pgprot verification to work out whether to short-circuit the
identity mapping on legacy parts, restoring the previous behaviour.
Reported-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: stable@kernel.org
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/sh/include/asm/io.h | 10 | ||||
| -rw-r--r-- | arch/sh/include/asm/pgtable_32.h | 7 |
2 files changed, 15 insertions, 2 deletions
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 70c1186b5088..28c5aa58bb45 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h | |||
| @@ -290,7 +290,15 @@ __ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot) | |||
| 290 | * mapping must be done by the PMB or by using page tables. | 290 | * mapping must be done by the PMB or by using page tables. |
| 291 | */ | 291 | */ |
| 292 | if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { | 292 | if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { |
| 293 | if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE)) | 293 | u64 flags = pgprot_val(prot); |
| 294 | |||
| 295 | /* | ||
| 296 | * Anything using the legacy PTEA space attributes needs | ||
| 297 | * to be kicked down to page table mappings. | ||
| 298 | */ | ||
| 299 | if (unlikely(flags & _PAGE_PCC_MASK)) | ||
| 300 | return NULL; | ||
| 301 | if (unlikely(flags & _PAGE_CACHABLE)) | ||
| 294 | return (void __iomem *)P1SEGADDR(offset); | 302 | return (void __iomem *)P1SEGADDR(offset); |
| 295 | 303 | ||
| 296 | return (void __iomem *)P2SEGADDR(offset); | 304 | return (void __iomem *)P2SEGADDR(offset); |
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index 3cbedd21fd83..b799fe71114c 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h | |||
| @@ -76,6 +76,10 @@ | |||
| 76 | /* Wrapper for extended mode pgprot twiddling */ | 76 | /* Wrapper for extended mode pgprot twiddling */ |
| 77 | #define _PAGE_EXT(x) ((unsigned long long)(x) << 32) | 77 | #define _PAGE_EXT(x) ((unsigned long long)(x) << 32) |
| 78 | 78 | ||
| 79 | #ifdef CONFIG_X2TLB | ||
| 80 | #define _PAGE_PCC_MASK 0x00000000 /* No legacy PTEA support */ | ||
| 81 | #else | ||
| 82 | |||
| 79 | /* software: moves to PTEA.TC (Timing Control) */ | 83 | /* software: moves to PTEA.TC (Timing Control) */ |
| 80 | #define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ | 84 | #define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ |
| 81 | #define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ | 85 | #define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ |
| @@ -89,7 +93,8 @@ | |||
| 89 | #define _PAGE_PCC_ATR8 0x60000000 /* Attribute Memory space, 8 bit bus */ | 93 | #define _PAGE_PCC_ATR8 0x60000000 /* Attribute Memory space, 8 bit bus */ |
| 90 | #define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */ | 94 | #define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */ |
| 91 | 95 | ||
| 92 | #ifndef CONFIG_X2TLB | 96 | #define _PAGE_PCC_MASK 0xe0000001 |
| 97 | |||
| 93 | /* copy the ptea attributes */ | 98 | /* copy the ptea attributes */ |
| 94 | static inline unsigned long copy_ptea_attributes(unsigned long x) | 99 | static inline unsigned long copy_ptea_attributes(unsigned long x) |
| 95 | { | 100 | { |
