Commit 7ffd4350 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] ppc64: fix iounmap TLB flushes

This patch fixes a bug in ppc64 local implementation of iounmap() that
would cause it to incorrectly flush the hash table since the changes to
set_pte have been applied.
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 1c2e2094
...@@ -288,7 +288,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea, ...@@ -288,7 +288,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
unsigned long size) unsigned long size)
{ {
unsigned long end; unsigned long base, end;
pte_t *pte; pte_t *pte;
if (pmd_none(*pmd)) if (pmd_none(*pmd))
...@@ -300,6 +300,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, ...@@ -300,6 +300,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
} }
pte = pte_offset_kernel(pmd, address); pte = pte_offset_kernel(pmd, address);
base = address & PMD_MASK;
address &= ~PMD_MASK; address &= ~PMD_MASK;
end = address + size; end = address + size;
if (end > PMD_SIZE) if (end > PMD_SIZE)
...@@ -307,7 +308,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, ...@@ -307,7 +308,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
do { do {
pte_t page; pte_t page;
page = ptep_get_and_clear(&ioremap_mm, address, pte); page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
address += PAGE_SIZE; address += PAGE_SIZE;
pte++; pte++;
if (pte_none(page)) if (pte_none(page))
...@@ -321,7 +322,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, ...@@ -321,7 +322,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
unsigned long size) unsigned long size)
{ {
unsigned long end; unsigned long base, end;
pmd_t *pmd; pmd_t *pmd;
if (pgd_none(*dir)) if (pgd_none(*dir))
...@@ -333,13 +334,14 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, ...@@ -333,13 +334,14 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
} }
pmd = pmd_offset(dir, address); pmd = pmd_offset(dir, address);
base = address & PGDIR_MASK;
address &= ~PGDIR_MASK; address &= ~PGDIR_MASK;
end = address + size; end = address + size;
if (end > PGDIR_SIZE) if (end > PGDIR_SIZE)
end = PGDIR_SIZE; end = PGDIR_SIZE;
do { do {
unmap_im_area_pte(pmd, address, end - address); unmap_im_area_pte(pmd, base + address, end - address);
address = (address + PMD_SIZE) & PMD_MASK; address = (address + PMD_SIZE) & PMD_MASK;
pmd++; pmd++;
} while (address < end); } while (address < end);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment