[PATCH v2 12/12] powerpc/mm: split out early ioremap path.

From: Christophe Leroy
Date: Tue Aug 20 2019 - 10:07:30 EST


ioremap does things differently depending on whether
SLAB is available or not at different levels.

Try to separate the early path from the beginning.

Signed-off-by: Christophe Leroy <christophe.leroy@xxxxxx>
---
arch/powerpc/include/asm/io.h | 3 ++-
arch/powerpc/mm/ioremap.c | 17 +++++++----------
arch/powerpc/mm/ioremap_32.c | 13 +++++--------
arch/powerpc/mm/ioremap_64.c | 30 +++++++++++++++++++++---------
4 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index dc529ea0fffa..a63ec938636d 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -722,7 +722,8 @@ void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);

extern void iounmap(volatile void __iomem *addr);

-int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot);
+int early_ioremap_range(unsigned long ea, phys_addr_t pa,
+ unsigned long size, pgprot_t prot);
void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size,
pgprot_t prot, void *caller);

diff --git a/arch/powerpc/mm/ioremap.c b/arch/powerpc/mm/ioremap.c
index 57630325846c..fc669643ce6a 100644
--- a/arch/powerpc/mm/ioremap.c
+++ b/arch/powerpc/mm/ioremap.c
@@ -59,18 +59,11 @@ void __iomem *ioremap_prot(phys_addr_t addr, unsigned long size, unsigned long f
}
EXPORT_SYMBOL(ioremap_prot);

-int ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size, pgprot_t prot)
+int early_ioremap_range(unsigned long ea, phys_addr_t pa,
+ unsigned long size, pgprot_t prot)
{
unsigned long i;

- if (slab_is_available()) {
- int err = ioremap_page_range(ea, ea + size, pa, prot);
-
- if (err)
- unmap_kernel_range(ea, size);
- return err;
- }
-
for (i = 0; i < size; i += PAGE_SIZE) {
int err = map_kernel_page(ea + i, pa + i, prot);

@@ -86,16 +79,20 @@ void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size,
{
struct vm_struct *area;
int ret;
+ unsigned long va;

area = __get_vm_area_caller(size, VM_IOREMAP, IOREMAP_START, IOREMAP_END, caller);
if (area == NULL)
return NULL;

area->phys_addr = pa;
- ret = ioremap_range((unsigned long)area->addr, pa, size, prot);
+ va = (unsigned long)area->addr;
+
+ ret = ioremap_page_range(va, va + size, pa, prot);
if (!ret)
return (void __iomem *)area->addr + offset;

+ unmap_kernel_range(va, size);
free_vm_area(area);

return NULL;
diff --git a/arch/powerpc/mm/ioremap_32.c b/arch/powerpc/mm/ioremap_32.c
index fcf343dbf2bf..f36121f25243 100644
--- a/arch/powerpc/mm/ioremap_32.c
+++ b/arch/powerpc/mm/ioremap_32.c
@@ -60,24 +60,21 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *call
*/
v = p_block_mapped(p);
if (v)
- goto out;
+ return (void __iomem *)v + offset;

- if (slab_is_available()) {
+ if (slab_is_available())
return do_ioremap(p, offset, size, prot, caller);
- } else {
- v = (ioremap_bot -= size);
- }

/*
* Should check if it is a candidate for a BAT mapping
*/

- err = ioremap_range((unsigned long)v, p, size, prot);
+ err = early_ioremap_range(ioremap_bot - size, p, size, prot);
if (err)
return NULL;
+ ioremap_bot -= size;

-out:
- return (void __iomem *)(v + ((unsigned long)addr & ~PAGE_MASK));
+ return (void __iomem *)ioremap_bot + offset;
}

void iounmap(volatile void __iomem *addr)
diff --git a/arch/powerpc/mm/ioremap_64.c b/arch/powerpc/mm/ioremap_64.c
index e37b68b7f0e8..fd29e51700cd 100644
--- a/arch/powerpc/mm/ioremap_64.c
+++ b/arch/powerpc/mm/ioremap_64.c
@@ -9,6 +9,9 @@
*/
void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_t prot)
{
+ int ret;
+ unsigned long va = (unsigned long)ea;
+
/* We don't support the 4K PFN hack with ioremap */
if (pgprot_val(prot) & H_PAGE_4K_PFN)
return NULL;
@@ -22,7 +25,15 @@ void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_
WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
WARN_ON(size & ~PAGE_MASK);

- if (ioremap_range((unsigned long)ea, pa, size, prot))
+ if (slab_is_available()) {
+ ret = ioremap_page_range(va, va + size, pa, prot);
+ if (ret)
+ unmap_kernel_range(va, size);
+ } else {
+ ret = early_ioremap_range(va, pa, size, prot);
+ }
+
+ if (ret)
return NULL;

return (void __iomem *)ea;
@@ -48,6 +59,7 @@ void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size,
{
phys_addr_t paligned, offset;
void __iomem *ret;
+ int err;

/* We don't support the 4K PFN hack with ioremap */
if (pgprot_val(prot) & H_PAGE_4K_PFN)
@@ -66,16 +78,16 @@ void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size,
if (size == 0 || paligned == 0)
return NULL;

- if (slab_is_available()) {
+ if (slab_is_available())
return do_ioremap(paligned, offset, size, prot, caller);
- } else {
- ret = __ioremap_at(paligned, (void *)ioremap_bot, size, prot);
- if (ret)
- ioremap_bot += size;
- }

- if (ret)
- ret += addr & ~PAGE_MASK;
+ err = early_ioremap_range(ioremap_bot, paligned, size, prot);
+ if (err)
+ return NULL;
+
+ ret = (void __iomem *)ioremap_bot + offset;
+ ioremap_bot += size;
+
return ret;
}

--
2.13.3