[RFC/PATCH] ppc64: Move ppc64_enable_pmcs() logic into a ppc_md function
Michael Ellerman
michael at ellerman.id.au
Tue Jul 12 17:07:30 EST 2005
This patch adds an enable_pmc entry to the ppc_md structure, and moves code
from arch/ppc64/kerne/sysfs.c into the various platform files. There should be
no functional changes.
The logic for pSeries seems a little confused. Are the platform check and the
firmware_features check equivalent?
We also call power4_enable_pmcs() unconditionally on pSeries. It seems to
work on power3, but not power5. Maybe it should be called something else?
And therefore probably not be in op_model_power4.c?
Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
arch/ppc64/kernel/iSeries_setup.c | 2 +
arch/ppc64/kernel/pSeries_setup.c | 18 ++++++++++
arch/ppc64/kernel/pmac_setup.c | 6 +++
arch/ppc64/kernel/sysfs.c | 56 ++--------------------------------
arch/ppc64/oprofile/op_model_power4.c | 21 ++++++++++++
include/asm-ppc64/machdep.h | 5 +++
6 files changed, 56 insertions(+), 52 deletions(-)
Index: work/arch/ppc64/kernel/iSeries_setup.c
===================================================================
--- work.orig/arch/ppc64/kernel/iSeries_setup.c
+++ work/arch/ppc64/kernel/iSeries_setup.c
@@ -946,6 +946,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
@@ -574,6 +574,23 @@ static int pseries_shared_idle(void)
return 0;
}
+static void pSeries_enable_pmcs(void)
+{
+ power4_enable_pmcs();
+
+ if (systemcfg->platform & PLATFORM_LPAR) {
+ unsigned long set, reset;
+
+ set = 1UL << 63;
+ reset = 0;
+ plpar_hcall_norets(H_PERFMON, set, reset);
+ }
+
+ /* instruct hypervisor to maintain PMCs */
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+ get_paca()->lppaca.pmcregs_in_use = 1;
+}
+
struct machdep_calls __initdata pSeries_md = {
.probe = pSeries_probe,
.setup_arch = pSeries_setup_arch,
@@ -595,4 +612,5 @@ struct machdep_calls __initdata pSeries_
.check_legacy_ioport = pSeries_check_legacy_ioport,
.system_reset_exception = pSeries_system_reset_exception,
.machine_check_exception = pSeries_machine_check_exception,
+ .enable_pmcs = pSeries_enable_pmcs,
};
Index: work/arch/ppc64/kernel/pmac_setup.c
===================================================================
--- work.orig/arch/ppc64/kernel/pmac_setup.c
+++ work/arch/ppc64/kernel/pmac_setup.c
@@ -489,6 +489,11 @@ static int __init pmac_probe(int platfor
return 1;
}
+static void pmac_enable_pmcs(void)
+{
+ power4_enable_pmcs();
+}
+
struct machdep_calls __initdata pmac_md = {
#ifdef CONFIG_HOTPLUG_CPU
.cpu_die = generic_mach_cpu_die,
@@ -511,4 +516,5 @@ struct machdep_calls __initdata pmac_md
.progress = pmac_progress,
.check_legacy_ioport = pmac_check_legacy_ioport,
.idle_loop = native_idle,
+ .enable_pmcs = pmac_enable_pmcs,
};
Index: work/arch/ppc64/kernel/sysfs.c
===================================================================
--- work.orig/arch/ppc64/kernel/sysfs.c
+++ work/arch/ppc64/kernel/sysfs.c
@@ -100,6 +100,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.
@@ -109,65 +111,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;
- }
-
-#ifdef CONFIG_PPC_PSERIES
- /* instruct hypervisor to maintain PMCs */
- if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
- get_paca()->lppaca.pmcregs_in_use = 1;
-#endif /* CONFIG_PPC_PSERIES */
+ 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
@@ -142,11 +142,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