[PATCH v1 02/10] powerpc/mm: rework io-workaround invocation.

From: Christophe Leroy
Date: Tue Aug 13 2019 - 16:12:10 EST


ppc_md.ioremap() is only used for I/O workaround on CELL platform,
so indirect function call can be avoided.

This patch reworks the io-workaround and ioremap() functions to
use static keys for the activation of io-workaround.

When CONFIG_PPC_IO_WORKAROUNDS or CONFIG_PPC_INDIRECT_MMIO are not
selected, the I/O workaround ioremap() voids and the static key is
not used at all.

Signed-off-by: Christophe Leroy <christophe.leroy@xxxxxx>
---
arch/powerpc/include/asm/io-workarounds.h | 19 +++++++++++++++++++
arch/powerpc/include/asm/machdep.h | 2 --
arch/powerpc/kernel/io-workarounds.c | 11 ++++++-----
arch/powerpc/mm/pgtable_64.c | 17 +++++++++--------
4 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/io-workarounds.h b/arch/powerpc/include/asm/io-workarounds.h
index 01567ea4ceaf..ce337d17ac40 100644
--- a/arch/powerpc/include/asm/io-workarounds.h
+++ b/arch/powerpc/include/asm/io-workarounds.h
@@ -8,6 +8,7 @@
#ifndef _IO_WORKAROUNDS_H
#define _IO_WORKAROUNDS_H

+#ifdef CONFIG_PPC_IO_WORKAROUNDS
#include <linux/io.h>
#include <asm/pci-bridge.h>

@@ -32,4 +33,22 @@ extern int spiderpci_iowa_init(struct iowa_bus *, void *);
#define SPIDER_PCI_DUMMY_READ 0x0810
#define SPIDER_PCI_DUMMY_READ_BASE 0x0814

+#endif
+
+#if defined(CONFIG_PPC_IO_WORKAROUNDS) && defined(CONFIG_PPC_INDIRECT_MMIO)
+DECLARE_STATIC_KEY_FALSE(iowa_key);
+static inline bool iowa_is_active(void)
+{
+ return static_branch_unlikely(&iowa_key);
+}
+#else
+static inline bool iowa_is_active(void)
+{
+ return false;
+}
+#endif
+
+void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
+ pgprot_t prot, void *caller);
+
#endif /* _IO_WORKAROUNDS_H */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 3370df4bdaa0..657ec893bdcb 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -31,8 +31,6 @@ struct pci_host_bridge;
struct machdep_calls {
char *name;
#ifdef CONFIG_PPC64
- void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size,
- pgprot_t prot, void *caller);
#ifdef CONFIG_PM
void (*iommu_save)(void);
void (*iommu_restore)(void);
diff --git a/arch/powerpc/kernel/io-workarounds.c b/arch/powerpc/kernel/io-workarounds.c
index fbd2d0007c52..8b5b2aa70840 100644
--- a/arch/powerpc/kernel/io-workarounds.c
+++ b/arch/powerpc/kernel/io-workarounds.c
@@ -18,6 +18,7 @@
#include <asm/io-workarounds.h>
#include <asm/pte-walk.h>

+DEFINE_STATIC_KEY_FALSE(iowa_key);

#define IOWA_MAX_BUS 8

@@ -149,8 +150,8 @@ static const struct ppc_pci_io iowa_pci_io = {
};

#ifdef CONFIG_PPC_INDIRECT_MMIO
-static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
- pgprot_t prot, void *caller)
+void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
+ pgprot_t prot, void *caller)
{
struct iowa_bus *bus;
void __iomem *res = __ioremap_caller(addr, size, prot, caller);
@@ -163,8 +164,6 @@ static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
}
return res;
}
-#else /* CONFIG_PPC_INDIRECT_MMIO */
-#define iowa_ioremap NULL
#endif /* !CONFIG_PPC_INDIRECT_MMIO */

/* Enable IO workaround */
@@ -175,7 +174,9 @@ static void io_workaround_init(void)
if (io_workaround_inited)
return;
ppc_pci_io = iowa_pci_io;
- ppc_md.ioremap = iowa_ioremap;
+#ifdef CONFIG_PPC_INDIRECT_MMIO
+ static_branch_enable(&iowa_key);
+#endif
io_workaround_inited = 1;
}

diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 11eb90ea2d4f..194efc6f39fb 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -35,6 +35,7 @@
#include <asm/page.h>
#include <asm/prom.h>
#include <asm/io.h>
+#include <asm/io-workarounds.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/mmu.h>
@@ -214,8 +215,8 @@ void __iomem * ioremap(phys_addr_t addr, unsigned long size)
pgprot_t prot = pgprot_noncached(PAGE_KERNEL);
void *caller = __builtin_return_address(0);

- if (ppc_md.ioremap)
- return ppc_md.ioremap(addr, size, prot, caller);
+ if (iowa_is_active())
+ return iowa_ioremap(addr, size, prot, caller);
return __ioremap_caller(addr, size, prot, caller);
}

@@ -224,8 +225,8 @@ void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size)
pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL);
void *caller = __builtin_return_address(0);

- if (ppc_md.ioremap)
- return ppc_md.ioremap(addr, size, prot, caller);
+ if (iowa_is_active())
+ return iowa_ioremap(addr, size, prot, caller);
return __ioremap_caller(addr, size, prot, caller);
}

@@ -234,8 +235,8 @@ void __iomem *ioremap_coherent(phys_addr_t addr, unsigned long size)
pgprot_t prot = pgprot_cached(PAGE_KERNEL);
void *caller = __builtin_return_address(0);

- if (ppc_md.ioremap)
- return ppc_md.ioremap(addr, size, prot, caller);
+ if (iowa_is_active())
+ return iowa_ioremap(addr, size, prot, caller);
return __ioremap_caller(addr, size, prot, caller);
}

@@ -256,8 +257,8 @@ void __iomem * ioremap_prot(phys_addr_t addr, unsigned long size,
*/
pte = pte_mkprivileged(pte);

- if (ppc_md.ioremap)
- return ppc_md.ioremap(addr, size, pte_pgprot(pte), caller);
+ if (iowa_is_active())
+ return iowa_ioremap(addr, size, pte_pgprot(pte), caller);
return __ioremap_caller(addr, size, pte_pgprot(pte), caller);
}

--
2.13.3