Skip to content

Commit

Permalink
sh: Correct iounmap fixmap teardown.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Mundt committed Jan 20, 2010
1 parent b51989b commit 920efaa
Showing 1 changed file with 2 additions and 7 deletions.
9 changes: 2 additions & 7 deletions arch/sh/mm/ioremap_fixed.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
int iounmap_fixed(void __iomem *addr)
{
enum fixed_addresses idx;
unsigned long virt_addr;
struct ioremap_map *map;
unsigned long offset;
unsigned int nrpages;
int i, slot;

Expand All @@ -114,12 +112,9 @@ int iounmap_fixed(void __iomem *addr)
if (slot < 0)
return -EINVAL;

virt_addr = (unsigned long)addr;
nrpages = map->size >> PAGE_SHIFT;

offset = virt_addr & ~PAGE_MASK;
nrpages = PAGE_ALIGN(offset + map->size - 1) >> PAGE_SHIFT;

idx = FIX_IOREMAP_BEGIN + slot + nrpages;
idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1;
while (nrpages > 0) {
__clear_fixmap(idx, __pgprot(_PAGE_WIRED));
--idx;
Expand Down

0 comments on commit 920efaa

Please sign in to comment.