[PATCH] ppc64: Move ppc64_enable_pmcs() logic into a ppc_md function
Michael Ellerman
michael at ellerman.id.au
Mon Aug 8 18:45:39 EST 2005
Ok, here's an updated version.
I've tested it on P5 LPAR and P4. It does what it used to.
It still doesn't seem to actually work on P5, with or without this patch,
ie. the counters never increment. I take it that's normal.
Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
arch/ppc64/kernel/iSeries_setup.c | 2 +
arch/ppc64/kernel/pSeries_setup.c | 20 ++++++++++++
arch/ppc64/kernel/pmac_setup.c | 1
arch/ppc64/kernel/sysfs.c | 54 ++--------------------------------
arch/ppc64/oprofile/op_model_power4.c | 21 +++++++++++++
include/asm-ppc64/machdep.h | 5 +++
6 files changed, 53 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
@@ -187,6 +187,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 +260,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
@@ -511,4 +511,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/arch/ppc64/oprofile/op_model_power4.c
===================================================================
--- work.orig/arch/ppc64/oprofile/op_model_power4.c
+++ work/arch/ppc64/oprofile/op_model_power4.c
@@ -83,6 +83,27 @@ static void power4_reg_setup(struct op_c
mmcr0_val |= MMCR0_PROBLEM_DISABLE;
}
+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");
+}
+
extern void ppc64_enable_pmcs(void);
static void power4_cpu_setup(void *unused)
Index: work/include/asm-ppc64/machdep.h
===================================================================
--- work.orig/include/asm-ppc64/machdep.h
+++ work/include/asm-ppc64/machdep.h
@@ -140,11 +140,16 @@ 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);
extern int native_idle(void);
+extern void power4_enable_pmcs(void);
+
extern struct machdep_calls ppc_md;
extern char cmd_line[COMMAND_LINE_SIZE];
More information about the Linuxppc64-dev
mailing list