aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-20 04:10:30 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-20 04:10:30 -0500
commit920efaabcbd34e6b8dc05c5b777df3e936af5812 (patch)
tree34645e1ebe93a3a7365eb85b15d358e467e71f1b /arch/sh/mm
parentb51989b8afe9409ee68c67ce2a5de4390693bd2b (diff)
sh: Correct iounmap fixmap teardown.
iounmap_fixed() had a couple of bugs in it that caused it to effectively fail at life. The total number of pages to unmap factored in the mapping offset and aligned up to the next page boundary, which doesn't match the ioremap_fixed() behaviour. When ioremap_fixed() pegs a slot, the address in the mapping data already contains the offset displacement, and the size is recorded verbatim given that we're only interested in total number of pages required. As such, we need to calculate the total number from the original size in the unmap path as well. At the same time, there was also an off-by-1 problem in the fixmap index calculation which has also been corrected. Previously subsequent remaps of an identical fixmap index would trigger the pte_ERROR() in set_pte_phys(): arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). arch/sh/mm/init.c:77: bad pte 8053ffb0(0000781003fff506). With this patch in place, the iounmap-driven fixmap teardown actually does what it's supposed to do. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/ioremap_fixed.c9
1 files changed, 2 insertions, 7 deletions
diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c
index 551b513e8fce..0b78b1e20ef1 100644
--- a/arch/sh/mm/ioremap_fixed.c
+++ b/arch/sh/mm/ioremap_fixed.c
@@ -93,9 +93,7 @@ ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
93int iounmap_fixed(void __iomem *addr) 93int iounmap_fixed(void __iomem *addr)
94{ 94{
95 enum fixed_addresses idx; 95 enum fixed_addresses idx;
96 unsigned long virt_addr;
97 struct ioremap_map *map; 96 struct ioremap_map *map;
98 unsigned long offset;
99 unsigned int nrpages; 97 unsigned int nrpages;
100 int i, slot; 98 int i, slot;
101 99
@@ -114,12 +112,9 @@ int iounmap_fixed(void __iomem *addr)
114 if (slot < 0) 112 if (slot < 0)
115 return -EINVAL; 113 return -EINVAL;
116 114
117 virt_addr = (unsigned long)addr; 115 nrpages = map->size >> PAGE_SHIFT;
118 116
119 offset = virt_addr & ~PAGE_MASK; 117 idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1;
120 nrpages = PAGE_ALIGN(offset + map->size - 1) >> PAGE_SHIFT;
121
122 idx = FIX_IOREMAP_BEGIN + slot + nrpages;
123 while (nrpages > 0) { 118 while (nrpages > 0) {
124 __clear_fixmap(idx, __pgprot(_PAGE_WIRED)); 119 __clear_fixmap(idx, __pgprot(_PAGE_WIRED));
125 --idx; 120 --idx;