aboutsummaryrefslogtreecommitdiffstats
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)
964 ppc_md.calibrate_decr = iSeries_calibrate_decr; 964 ppc_md.calibrate_decr = iSeries_calibrate_decr;
965 ppc_md.progress = iSeries_progress; 965 ppc_md.progress = iSeries_progress;
966 966
967 /* XXX Implement enable_pmcs for iSeries */
968
967 if (get_paca()->lppaca.shared_proc) { 969 if (get_paca()->lppaca.shared_proc) {
968 ppc_md.idle_loop = iseries_shared_idle; 970 ppc_md.idle_loop = iseries_shared_idle;
969 printk(KERN_INFO "Using shared processor idle loop\n"); 971 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 @@
61#include <asm/plpar_wrappers.h> 61#include <asm/plpar_wrappers.h>
62#include <asm/xics.h> 62#include <asm/xics.h>
63#include <asm/firmware.h> 63#include <asm/firmware.h>
64#include <asm/pmc.h>
64 65
65#include "i8259.h" 66#include "i8259.h"
66#include "mpic.h" 67#include "mpic.h"
@@ -187,6 +188,21 @@ static void __init pSeries_setup_mpic(void)
187 " MPIC "); 188 " MPIC ");
188} 189}
189 190
191static void pseries_lpar_enable_pmcs(void)
192{
193 unsigned long set, reset;
194
195 power4_enable_pmcs();
196
197 set = 1UL << 63;
198 reset = 0;
199 plpar_hcall_norets(H_PERFMON, set, reset);
200
201 /* instruct hypervisor to maintain PMCs */
202 if (firmware_has_feature(FW_FEATURE_SPLPAR))
203 get_paca()->lppaca.pmcregs_in_use = 1;
204}
205
190static void __init pSeries_setup_arch(void) 206static void __init pSeries_setup_arch(void)
191{ 207{
192 /* Fixup ppc_md depending on the type of interrupt controller */ 208 /* Fixup ppc_md depending on the type of interrupt controller */
@@ -245,6 +261,11 @@ static void __init pSeries_setup_arch(void)
245 printk(KERN_INFO "Using default idle loop\n"); 261 printk(KERN_INFO "Using default idle loop\n");
246 ppc_md.idle_loop = default_idle; 262 ppc_md.idle_loop = default_idle;
247 } 263 }
264
265 if (systemcfg->platform & PLATFORM_LPAR)
266 ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
267 else
268 ppc_md.enable_pmcs = power4_enable_pmcs;
248} 269}
249 270
250static int __init pSeries_init_panel(void) 271static 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 @@
71#include <asm/of_device.h> 71#include <asm/of_device.h>
72#include <asm/lmb.h> 72#include <asm/lmb.h>
73#include <asm/smu.h> 73#include <asm/smu.h>
74#include <asm/pmc.h>
74 75
75#include "pmac.h" 76#include "pmac.h"
76#include "mpic.h" 77#include "mpic.h"
@@ -511,4 +512,5 @@ struct machdep_calls __initdata pmac_md = {
511 .progress = pmac_progress, 512 .progress = pmac_progress,
512 .check_legacy_ioport = pmac_check_legacy_ioport, 513 .check_legacy_ioport = pmac_check_legacy_ioport,
513 .idle_loop = native_idle, 514 .idle_loop = native_idle,
515 .enable_pmcs = power4_enable_pmcs,
514}; 516};
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)
65 spin_unlock(&pmc_owner_lock); 65 spin_unlock(&pmc_owner_lock);
66} 66}
67EXPORT_SYMBOL_GPL(release_pmc_hardware); 67EXPORT_SYMBOL_GPL(release_pmc_hardware);
68
69void power4_enable_pmcs(void)
70{
71 unsigned long hid0;
72
73 hid0 = mfspr(HID0);
74 hid0 |= 1UL << (63 - 20);
75
76 /* POWER4 requires the following sequence */
77 asm volatile(
78 "sync\n"
79 "mtspr %1, %0\n"
80 "mfspr %0, %1\n"
81 "mfspr %0, %1\n"
82 "mfspr %0, %1\n"
83 "mfspr %0, %1\n"
84 "mfspr %0, %1\n"
85 "mfspr %0, %1\n"
86 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
87 "memory");
88}
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)
101} 101}
102__setup("smt-snooze-delay=", setup_smt_snooze_delay); 102__setup("smt-snooze-delay=", setup_smt_snooze_delay);
103 103
104#endif /* CONFIG_PPC_MULTIPLATFORM */
105
104/* 106/*
105 * Enabling PMCs will slow partition context switch times so we only do 107 * Enabling PMCs will slow partition context switch times so we only do
106 * it the first time we write to the PMCs. 108 * it the first time we write to the PMCs.
@@ -110,63 +112,15 @@ static DEFINE_PER_CPU(char, pmcs_enabled);
110 112
111void ppc64_enable_pmcs(void) 113void ppc64_enable_pmcs(void)
112{ 114{
113 unsigned long hid0;
114#ifdef CONFIG_PPC_PSERIES
115 unsigned long set, reset;
116#endif /* CONFIG_PPC_PSERIES */
117
118 /* Only need to enable them once */ 115 /* Only need to enable them once */
119 if (__get_cpu_var(pmcs_enabled)) 116 if (__get_cpu_var(pmcs_enabled))
120 return; 117 return;
121 118
122 __get_cpu_var(pmcs_enabled) = 1; 119 __get_cpu_var(pmcs_enabled) = 1;
123 120
124 switch (systemcfg->platform) { 121 if (ppc_md.enable_pmcs)
125 case PLATFORM_PSERIES: 122 ppc_md.enable_pmcs();
126 case PLATFORM_POWERMAC:
127 hid0 = mfspr(HID0);
128 hid0 |= 1UL << (63 - 20);
129
130 /* POWER4 requires the following sequence */
131 asm volatile(
132 "sync\n"
133 "mtspr %1, %0\n"
134 "mfspr %0, %1\n"
135 "mfspr %0, %1\n"
136 "mfspr %0, %1\n"
137 "mfspr %0, %1\n"
138 "mfspr %0, %1\n"
139 "mfspr %0, %1\n"
140 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
141 "memory");
142 break;
143
144#ifdef CONFIG_PPC_PSERIES
145 case PLATFORM_PSERIES_LPAR:
146 set = 1UL << 63;
147 reset = 0;
148 plpar_hcall_norets(H_PERFMON, set, reset);
149 break;
150#endif /* CONFIG_PPC_PSERIES */
151
152 default:
153 break;
154 }
155
156 /* instruct hypervisor to maintain PMCs */
157 if (firmware_has_feature(FW_FEATURE_SPLPAR))
158 get_paca()->lppaca.pmcregs_in_use = 1;
159} 123}
160
161#else
162
163/* PMC stuff */
164void ppc64_enable_pmcs(void)
165{
166 /* XXX Implement for iseries */
167}
168#endif /* CONFIG_PPC_MULTIPLATFORM */
169
170EXPORT_SYMBOL(ppc64_enable_pmcs); 124EXPORT_SYMBOL(ppc64_enable_pmcs);
171 125
172/* XXX convert to rusty's on_one_cpu */ 126/* 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 {
140 140
141 /* Idle loop for this platform, leave empty for default idle loop */ 141 /* Idle loop for this platform, leave empty for default idle loop */
142 int (*idle_loop)(void); 142 int (*idle_loop)(void);
143
144 /* Function to enable pmcs for this platform, called once per cpu. */
145 void (*enable_pmcs)(void);
143}; 146};
144 147
145extern int default_idle(void); 148extern 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 *);
26int reserve_pmc_hardware(perf_irq_t new_perf_irq); 26int reserve_pmc_hardware(perf_irq_t new_perf_irq);
27void release_pmc_hardware(void); 27void release_pmc_hardware(void);
28 28
29void power4_enable_pmcs(void);
30
29#endif /* _PPC64_PMC_H */ 31#endif /* _PPC64_PMC_H */