summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c2
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c21
-rw-r--r--arch/ppc64/kernel/pmac_setup.c2
-rw-r--r--arch/ppc64/kernel/pmc.c21
-rw-r--r--arch/ppc64/kernel/sysfs.c54
-rw-r--r--include/asm-ppc64/machdep.h3
-rw-r--r--include/asm-ppc64/pmc.h2
7 files changed, 55 insertions, 50 deletions
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index b384a6ad0a57..3ffefbbc6623 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -964,6 +964,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");
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 54e0651ba3fd..f0f0630cf07c 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/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(void)
" 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(void)
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)
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e40877fa67cd..8ff86a766cdf 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/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_pmcs,
};
diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
index 67be773f9c00..cdfec7438d01 100644
--- a/arch/ppc64/kernel/pmc.c
+++ b/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");
+}
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index eca15d25e026..f311ee7c0070 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -101,6 +101,8 @@ static int __init setup_smt_snooze_delay(char *str)
}
__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 */
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index f0ef06375947..ff2c9287d3b6 100644
--- a/include/asm-ppc64/machdep.h
+++ b/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);
diff --git a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
index c924748c0bea..d1d297dbccfe 100644
--- a/include/asm-ppc64/pmc.h
+++ b/include/asm-ppc64/pmc.h
@@ -26,4 +26,6 @@ typedef void (*perf_irq_t)(struct pt_regs *);
int reserve_pmc_hardware(perf_irq_t new_perf_irq);
void release_pmc_hardware(void);
+void power4_enable_pmcs(void);
+
#endif /* _PPC64_PMC_H */
OpenPOWER on IntegriCloud