diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 14:30:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 14:30:02 -0500 |
commit | b1286f4e9ac14c8973140b338b4d3c5691264d3b (patch) | |
tree | 5a67788bb2276cd67230d24b5a6994ddafb10707 /arch/arm/kernel/perf_event_cpu.c | |
parent | 6facac1ab68fbf9cbad31a9d521f3a0d6aa9470e (diff) | |
parent | 0fa5d3996dbda1ee9653c43d39b7ef159fb57ee7 (diff) |
Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM updates from Russell King:
"Here's the updates for ARM for this merge window, which cover quite a
variety of areas.
There's a bunch of patch series from Will tackling various bugs like
the PROT_NONE handling, ASID allocation, cluster boot protocol and
ASID TLB tagging updates.
We move to a build-time sorted exception table rather than doing the
sorting at run-time, add support for the secure computing filter, and
some updates to the perf code. We also have sorted out the placement
of some headers, fixed some build warnings, fixed some hotplug
problems with the per-cpu TWD code."
* 'for-linus' of git://git.linaro.org/people/rmk/linux-arm: (73 commits)
ARM: 7594/1: Add .smp entry for REALVIEW_EB
ARM: 7599/1: head: Remove boot-time HYP mode check for v5 and below
ARM: 7598/1: net: bpf_jit_32: fix sp-relative load/stores offsets.
ARM: 7595/1: syscall: rework ordering in syscall_trace_exit
ARM: 7596/1: mmci: replace readsl/writesl with ioread32_rep/iowrite32_rep
ARM: 7597/1: net: bpf_jit_32: fix kzalloc gfp/size mismatch.
ARM: 7593/1: nommu: do not enable DCACHE_WORD_ACCESS when !CONFIG_MMU
ARM: 7592/1: nommu: prevent generation of kernel unaligned memory accesses
ARM: 7591/1: nommu: Enable the strict alignment (CR_A) bit only if ARCH < v6
ARM: 7590/1: /proc/interrupts: limit the display of IPIs to online CPUs only
ARM: 7587/1: implement optimized percpu variable access
ARM: 7589/1: integrator: pass the lm resource to amba
ARM: 7588/1: amba: create a resource parent registrator
ARM: 7582/2: rename kvm_seq to vmalloc_seq so to avoid confusion with KVM
ARM: 7585/1: kernel: fix nr_cpu_ids check in DT logical map init
ARM: 7584/1: perf: fix link error when CONFIG_HW_PERF_EVENTS is not selected
ARM: gic: use a private mapping for CPU target interfaces
ARM: kernel: add logical mappings look-up
ARM: kernel: add cpu logical map DT init in setup_arch
ARM: kernel: add device tree init map function
...
Diffstat (limited to 'arch/arm/kernel/perf_event_cpu.c')
-rw-r--r-- | arch/arm/kernel/perf_event_cpu.c | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 8d7d8d4de9d6..9a4f6307a016 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/slab.h> | ||
26 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
27 | 28 | ||
28 | #include <asm/cputype.h> | 29 | #include <asm/cputype.h> |
@@ -45,7 +46,7 @@ const char *perf_pmu_name(void) | |||
45 | if (!cpu_pmu) | 46 | if (!cpu_pmu) |
46 | return NULL; | 47 | return NULL; |
47 | 48 | ||
48 | return cpu_pmu->pmu.name; | 49 | return cpu_pmu->name; |
49 | } | 50 | } |
50 | EXPORT_SYMBOL_GPL(perf_pmu_name); | 51 | EXPORT_SYMBOL_GPL(perf_pmu_name); |
51 | 52 | ||
@@ -70,7 +71,7 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void) | |||
70 | return &__get_cpu_var(cpu_hw_events); | 71 | return &__get_cpu_var(cpu_hw_events); |
71 | } | 72 | } |
72 | 73 | ||
73 | static void cpu_pmu_free_irq(void) | 74 | static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu) |
74 | { | 75 | { |
75 | int i, irq, irqs; | 76 | int i, irq, irqs; |
76 | struct platform_device *pmu_device = cpu_pmu->plat_device; | 77 | struct platform_device *pmu_device = cpu_pmu->plat_device; |
@@ -86,7 +87,7 @@ static void cpu_pmu_free_irq(void) | |||
86 | } | 87 | } |
87 | } | 88 | } |
88 | 89 | ||
89 | static int cpu_pmu_request_irq(irq_handler_t handler) | 90 | static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler) |
90 | { | 91 | { |
91 | int i, err, irq, irqs; | 92 | int i, err, irq, irqs; |
92 | struct platform_device *pmu_device = cpu_pmu->plat_device; | 93 | struct platform_device *pmu_device = cpu_pmu->plat_device; |
@@ -147,7 +148,7 @@ static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu) | |||
147 | 148 | ||
148 | /* Ensure the PMU has sane values out of reset. */ | 149 | /* Ensure the PMU has sane values out of reset. */ |
149 | if (cpu_pmu && cpu_pmu->reset) | 150 | if (cpu_pmu && cpu_pmu->reset) |
150 | on_each_cpu(cpu_pmu->reset, NULL, 1); | 151 | on_each_cpu(cpu_pmu->reset, cpu_pmu, 1); |
151 | } | 152 | } |
152 | 153 | ||
153 | /* | 154 | /* |
@@ -163,7 +164,9 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, | |||
163 | return NOTIFY_DONE; | 164 | return NOTIFY_DONE; |
164 | 165 | ||
165 | if (cpu_pmu && cpu_pmu->reset) | 166 | if (cpu_pmu && cpu_pmu->reset) |
166 | cpu_pmu->reset(NULL); | 167 | cpu_pmu->reset(cpu_pmu); |
168 | else | ||
169 | return NOTIFY_DONE; | ||
167 | 170 | ||
168 | return NOTIFY_OK; | 171 | return NOTIFY_OK; |
169 | } | 172 | } |
@@ -195,13 +198,13 @@ static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = { | |||
195 | /* | 198 | /* |
196 | * CPU PMU identification and probing. | 199 | * CPU PMU identification and probing. |
197 | */ | 200 | */ |
198 | static struct arm_pmu *__devinit probe_current_pmu(void) | 201 | static int __devinit probe_current_pmu(struct arm_pmu *pmu) |
199 | { | 202 | { |
200 | struct arm_pmu *pmu = NULL; | ||
201 | int cpu = get_cpu(); | 203 | int cpu = get_cpu(); |
202 | unsigned long cpuid = read_cpuid_id(); | 204 | unsigned long cpuid = read_cpuid_id(); |
203 | unsigned long implementor = (cpuid & 0xFF000000) >> 24; | 205 | unsigned long implementor = (cpuid & 0xFF000000) >> 24; |
204 | unsigned long part_number = (cpuid & 0xFFF0); | 206 | unsigned long part_number = (cpuid & 0xFFF0); |
207 | int ret = -ENODEV; | ||
205 | 208 | ||
206 | pr_info("probing PMU on CPU %d\n", cpu); | 209 | pr_info("probing PMU on CPU %d\n", cpu); |
207 | 210 | ||
@@ -211,25 +214,25 @@ static struct arm_pmu *__devinit probe_current_pmu(void) | |||
211 | case 0xB360: /* ARM1136 */ | 214 | case 0xB360: /* ARM1136 */ |
212 | case 0xB560: /* ARM1156 */ | 215 | case 0xB560: /* ARM1156 */ |
213 | case 0xB760: /* ARM1176 */ | 216 | case 0xB760: /* ARM1176 */ |
214 | pmu = armv6pmu_init(); | 217 | ret = armv6pmu_init(pmu); |
215 | break; | 218 | break; |
216 | case 0xB020: /* ARM11mpcore */ | 219 | case 0xB020: /* ARM11mpcore */ |
217 | pmu = armv6mpcore_pmu_init(); | 220 | ret = armv6mpcore_pmu_init(pmu); |
218 | break; | 221 | break; |
219 | case 0xC080: /* Cortex-A8 */ | 222 | case 0xC080: /* Cortex-A8 */ |
220 | pmu = armv7_a8_pmu_init(); | 223 | ret = armv7_a8_pmu_init(pmu); |
221 | break; | 224 | break; |
222 | case 0xC090: /* Cortex-A9 */ | 225 | case 0xC090: /* Cortex-A9 */ |
223 | pmu = armv7_a9_pmu_init(); | 226 | ret = armv7_a9_pmu_init(pmu); |
224 | break; | 227 | break; |
225 | case 0xC050: /* Cortex-A5 */ | 228 | case 0xC050: /* Cortex-A5 */ |
226 | pmu = armv7_a5_pmu_init(); | 229 | ret = armv7_a5_pmu_init(pmu); |
227 | break; | 230 | break; |
228 | case 0xC0F0: /* Cortex-A15 */ | 231 | case 0xC0F0: /* Cortex-A15 */ |
229 | pmu = armv7_a15_pmu_init(); | 232 | ret = armv7_a15_pmu_init(pmu); |
230 | break; | 233 | break; |
231 | case 0xC070: /* Cortex-A7 */ | 234 | case 0xC070: /* Cortex-A7 */ |
232 | pmu = armv7_a7_pmu_init(); | 235 | ret = armv7_a7_pmu_init(pmu); |
233 | break; | 236 | break; |
234 | } | 237 | } |
235 | /* Intel CPUs [xscale]. */ | 238 | /* Intel CPUs [xscale]. */ |
@@ -237,43 +240,54 @@ static struct arm_pmu *__devinit probe_current_pmu(void) | |||
237 | part_number = (cpuid >> 13) & 0x7; | 240 | part_number = (cpuid >> 13) & 0x7; |
238 | switch (part_number) { | 241 | switch (part_number) { |
239 | case 1: | 242 | case 1: |
240 | pmu = xscale1pmu_init(); | 243 | ret = xscale1pmu_init(pmu); |
241 | break; | 244 | break; |
242 | case 2: | 245 | case 2: |
243 | pmu = xscale2pmu_init(); | 246 | ret = xscale2pmu_init(pmu); |
244 | break; | 247 | break; |
245 | } | 248 | } |
246 | } | 249 | } |
247 | 250 | ||
248 | put_cpu(); | 251 | put_cpu(); |
249 | return pmu; | 252 | return ret; |
250 | } | 253 | } |
251 | 254 | ||
252 | static int __devinit cpu_pmu_device_probe(struct platform_device *pdev) | 255 | static int __devinit cpu_pmu_device_probe(struct platform_device *pdev) |
253 | { | 256 | { |
254 | const struct of_device_id *of_id; | 257 | const struct of_device_id *of_id; |
255 | struct arm_pmu *(*init_fn)(void); | 258 | int (*init_fn)(struct arm_pmu *); |
256 | struct device_node *node = pdev->dev.of_node; | 259 | struct device_node *node = pdev->dev.of_node; |
260 | struct arm_pmu *pmu; | ||
261 | int ret = -ENODEV; | ||
257 | 262 | ||
258 | if (cpu_pmu) { | 263 | if (cpu_pmu) { |
259 | pr_info("attempt to register multiple PMU devices!"); | 264 | pr_info("attempt to register multiple PMU devices!"); |
260 | return -ENOSPC; | 265 | return -ENOSPC; |
261 | } | 266 | } |
262 | 267 | ||
268 | pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL); | ||
269 | if (!pmu) { | ||
270 | pr_info("failed to allocate PMU device!"); | ||
271 | return -ENOMEM; | ||
272 | } | ||
273 | |||
263 | if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { | 274 | if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { |
264 | init_fn = of_id->data; | 275 | init_fn = of_id->data; |
265 | cpu_pmu = init_fn(); | 276 | ret = init_fn(pmu); |
266 | } else { | 277 | } else { |
267 | cpu_pmu = probe_current_pmu(); | 278 | ret = probe_current_pmu(pmu); |
268 | } | 279 | } |
269 | 280 | ||
270 | if (!cpu_pmu) | 281 | if (ret) { |
271 | return -ENODEV; | 282 | pr_info("failed to register PMU devices!"); |
283 | kfree(pmu); | ||
284 | return ret; | ||
285 | } | ||
272 | 286 | ||
287 | cpu_pmu = pmu; | ||
273 | cpu_pmu->plat_device = pdev; | 288 | cpu_pmu->plat_device = pdev; |
274 | cpu_pmu_init(cpu_pmu); | 289 | cpu_pmu_init(cpu_pmu); |
275 | register_cpu_notifier(&cpu_pmu_hotplug_notifier); | 290 | armpmu_register(cpu_pmu, PERF_TYPE_RAW); |
276 | armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); | ||
277 | 291 | ||
278 | return 0; | 292 | return 0; |
279 | } | 293 | } |
@@ -290,6 +304,16 @@ static struct platform_driver cpu_pmu_driver = { | |||
290 | 304 | ||
291 | static int __init register_pmu_driver(void) | 305 | static int __init register_pmu_driver(void) |
292 | { | 306 | { |
293 | return platform_driver_register(&cpu_pmu_driver); | 307 | int err; |
308 | |||
309 | err = register_cpu_notifier(&cpu_pmu_hotplug_notifier); | ||
310 | if (err) | ||
311 | return err; | ||
312 | |||
313 | err = platform_driver_register(&cpu_pmu_driver); | ||
314 | if (err) | ||
315 | unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); | ||
316 | |||
317 | return err; | ||
294 | } | 318 | } |
295 | device_initcall(register_pmu_driver); | 319 | device_initcall(register_pmu_driver); |