[PATCH] ppc64: Move ppc64_enable_pmcs() logic into a ppc_md function

Michael Ellerman michael at ellerman.id.au
Tue Aug 9 11:13:36 EST 2005


David asked me to put power4_enable_pmcs() in arch/ppc64/kernel/pmc.c, so
here's an updated (again) version.

I've tested it on P5 LPAR and P4. It does what it used to.

Signed-off-by: Michael Ellerman <michael at ellerman.id.au>

 arch/ppc64/kernel/iSeries_setup.c |    2 +
 arch/ppc64/kernel/pSeries_setup.c |   21 ++++++++++++++
 arch/ppc64/kernel/pmac_setup.c    |    2 +
 arch/ppc64/kernel/pmc.c           |   21 ++++++++++++++
 arch/ppc64/kernel/sysfs.c         |   54 ++------------------------------------
 include/asm-ppc64/machdep.h       |    3 ++
 include/asm-ppc64/pmc.h           |    2 +
 7 files changed, 55 insertions(+), 50 deletions(-)

Index: work/arch/ppc64/kernel/iSeries_setup.c
===================================================================
--- work.orig/arch/ppc64/kernel/iSeries_setup.c
+++ work/arch/ppc64/kernel/iSeries_setup.c
@@ -947,6 +947,8 @@ void __init iSeries_early_setup(void)
 	ppc_md.calibrate_decr = iSeries_calibrate_decr;
 	ppc_md.progress = iSeries_progress;
 
+	/* XXX Implement enable_pmcs for iSeries */
+
 	if (get_paca()->lppaca.shared_proc) {
 		ppc_md.idle_loop = iseries_shared_idle;
 		printk(KERN_INFO "Using shared processor idle loop\n");
Index: work/arch/ppc64/kernel/pSeries_setup.c
===================================================================
--- work.orig/arch/ppc64/kernel/pSeries_setup.c
+++ work/arch/ppc64/kernel/pSeries_setup.c
@@ -61,6 +61,7 @@
 #include <asm/plpar_wrappers.h>
 #include <asm/xics.h>
 #include <asm/firmware.h>
+#include <asm/pmc.h>
 
 #include "i8259.h"
 #include "mpic.h"
@@ -187,6 +188,21 @@ static void __init pSeries_setup_mpic(vo
 				  " MPIC     ");
 }
 
+static void pseries_lpar_enable_pmcs(void)
+{
+	unsigned long set, reset;
+
+	power4_enable_pmcs();
+
+	set = 1UL << 63;
+	reset = 0;
+	plpar_hcall_norets(H_PERFMON, set, reset);
+
+	/* instruct hypervisor to maintain PMCs */
+	if (firmware_has_feature(FW_FEATURE_SPLPAR))
+		get_paca()->lppaca.pmcregs_in_use = 1;
+}
+
 static void __init pSeries_setup_arch(void)
 {
 	/* Fixup ppc_md depending on the type of interrupt controller */
@@ -245,6 +261,11 @@ static void __init pSeries_setup_arch(vo
 		printk(KERN_INFO "Using default idle loop\n");
 		ppc_md.idle_loop = default_idle;
 	}
+
+	if (systemcfg->platform & PLATFORM_LPAR)
+		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
+	else
+		ppc_md.enable_pmcs = power4_enable_pmcs;
 }
 
 static int __init pSeries_init_panel(void)
Index: work/arch/ppc64/kernel/pmac_setup.c
===================================================================
--- work.orig/arch/ppc64/kernel/pmac_setup.c
+++ work/arch/ppc64/kernel/pmac_setup.c
@@ -71,6 +71,7 @@
 #include <asm/of_device.h>
 #include <asm/lmb.h>
 #include <asm/smu.h>
+#include <asm/pmc.h>
 
 #include "pmac.h"
 #include "mpic.h"
@@ -511,4 +512,5 @@ struct machdep_calls __initdata pmac_md 
 	.progress		= pmac_progress,
 	.check_legacy_ioport	= pmac_check_legacy_ioport,
 	.idle_loop		= native_idle,
+	.enable_pmcs		= power4_enable_cpus,
 };
Index: work/arch/ppc64/kernel/sysfs.c
===================================================================
--- work.orig/arch/ppc64/kernel/sysfs.c
+++ work/arch/ppc64/kernel/sysfs.c
@@ -101,6 +101,8 @@ static int __init setup_smt_snooze_delay
 }
 __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
 /*
  * Enabling PMCs will slow partition context switch times so we only do
  * it the first time we write to the PMCs.
@@ -110,63 +112,15 @@ static DEFINE_PER_CPU(char, pmcs_enabled
 
 void ppc64_enable_pmcs(void)
 {
-	unsigned long hid0;
-#ifdef CONFIG_PPC_PSERIES
-	unsigned long set, reset;
-#endif /* CONFIG_PPC_PSERIES */
-
 	/* Only need to enable them once */
 	if (__get_cpu_var(pmcs_enabled))
 		return;
 
 	__get_cpu_var(pmcs_enabled) = 1;
 
-	switch (systemcfg->platform) {
-	case PLATFORM_PSERIES:
-	case PLATFORM_POWERMAC:
-		hid0 = mfspr(HID0);
-		hid0 |= 1UL << (63 - 20);
-
-		/* POWER4 requires the following sequence */
-		asm volatile(
-			     "sync\n"
-			     "mtspr	%1, %0\n"
-			     "mfspr	%0, %1\n"
-			     "mfspr	%0, %1\n"
-			     "mfspr	%0, %1\n"
-			     "mfspr	%0, %1\n"
-			     "mfspr	%0, %1\n"
-			     "mfspr	%0, %1\n"
-			     "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
-			     "memory");
-		break;
-
-#ifdef CONFIG_PPC_PSERIES
-	case PLATFORM_PSERIES_LPAR:
-		set = 1UL << 63;
-		reset = 0;
-		plpar_hcall_norets(H_PERFMON, set, reset);
-		break;
-#endif /* CONFIG_PPC_PSERIES */
-
-	default:
-		break;
-	}
-
-	/* instruct hypervisor to maintain PMCs */
-	if (firmware_has_feature(FW_FEATURE_SPLPAR))
-		get_paca()->lppaca.pmcregs_in_use = 1;
+	if (ppc_md.enable_pmcs)
+		ppc_md.enable_pmcs();
 }
-
-#else
-
-/* PMC stuff */
-void ppc64_enable_pmcs(void)
-{
-	/* XXX Implement for iseries */
-}
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 EXPORT_SYMBOL(ppc64_enable_pmcs);
 
 /* XXX convert to rusty's on_one_cpu */
Index: work/include/asm-ppc64/machdep.h
===================================================================
--- work.orig/include/asm-ppc64/machdep.h
+++ work/include/asm-ppc64/machdep.h
@@ -140,6 +140,9 @@ struct machdep_calls {
 
 	/* Idle loop for this platform, leave empty for default idle loop */
 	int		(*idle_loop)(void);
+
+	/* Function to enable pmcs for this platform, called once per cpu. */
+	void		(*enable_pmcs)(void);
 };
 
 extern int default_idle(void);
Index: work/arch/ppc64/kernel/pmc.c
===================================================================
--- work.orig/arch/ppc64/kernel/pmc.c
+++ work/arch/ppc64/kernel/pmc.c
@@ -65,3 +65,24 @@ void release_pmc_hardware(void)
 	spin_unlock(&pmc_owner_lock);
 }
 EXPORT_SYMBOL_GPL(release_pmc_hardware);
+
+void power4_enable_pmcs(void)
+{
+	unsigned long hid0;
+
+	hid0 = mfspr(HID0);
+	hid0 |= 1UL << (63 - 20);
+
+	/* POWER4 requires the following sequence */
+	asm volatile(
+		"sync\n"
+		"mtspr     %1, %0\n"
+		"mfspr     %0, %1\n"
+		"mfspr     %0, %1\n"
+		"mfspr     %0, %1\n"
+		"mfspr     %0, %1\n"
+		"mfspr     %0, %1\n"
+		"mfspr     %0, %1\n"
+		"isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
+		"memory");
+}
Index: work/include/asm-ppc64/pmc.h
===================================================================
--- work.orig/include/asm-ppc64/pmc.h
+++ work/include/asm-ppc64/pmc.h
@@ -26,4 +26,6 @@ typedef void (*perf_irq_t)(struct pt_reg
 int reserve_pmc_hardware(perf_irq_t new_perf_irq);
 void release_pmc_hardware(void);
 
+void power4_enable_pmcs(void);
+
 #endif /* _PPC64_PMC_H */



More information about the Linuxppc64-dev mailing list