diff options
| -rw-r--r-- | arch/arm/include/asm/pmu.h | 15 | ||||
| -rw-r--r-- | arch/arm/kernel/perf_event.c | 10 |
2 files changed, 20 insertions, 5 deletions
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 0bda22c094a6..b5a5be2536c1 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h | |||
| @@ -27,13 +27,22 @@ enum arm_pmu_type { | |||
| 27 | /* | 27 | /* |
| 28 | * struct arm_pmu_platdata - ARM PMU platform data | 28 | * struct arm_pmu_platdata - ARM PMU platform data |
| 29 | * | 29 | * |
| 30 | * @handle_irq: an optional handler which will be called from the interrupt and | 30 | * @handle_irq: an optional handler which will be called from the |
| 31 | * passed the address of the low level handler, and can be used to implement | 31 | * interrupt and passed the address of the low level handler, |
| 32 | * any platform specific handling before or after calling it. | 32 | * and can be used to implement any platform specific handling |
| 33 | * before or after calling it. | ||
| 34 | * @enable_irq: an optional handler which will be called after | ||
| 35 | * request_irq and be used to handle some platform specific | ||
| 36 | * irq enablement | ||
| 37 | * @disable_irq: an optional handler which will be called before | ||
| 38 | * free_irq and be used to handle some platform specific | ||
| 39 | * irq disablement | ||
| 33 | */ | 40 | */ |
| 34 | struct arm_pmu_platdata { | 41 | struct arm_pmu_platdata { |
| 35 | irqreturn_t (*handle_irq)(int irq, void *dev, | 42 | irqreturn_t (*handle_irq)(int irq, void *dev, |
| 36 | irq_handler_t pmu_handler); | 43 | irq_handler_t pmu_handler); |
| 44 | void (*enable_irq)(int irq); | ||
| 45 | void (*disable_irq)(int irq); | ||
| 37 | }; | 46 | }; |
| 38 | 47 | ||
| 39 | #ifdef CONFIG_CPU_HAS_PMU | 48 | #ifdef CONFIG_CPU_HAS_PMU |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index c475379199b1..daa1db84452e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
| @@ -380,6 +380,8 @@ armpmu_release_hardware(struct arm_pmu *armpmu) | |||
| 380 | { | 380 | { |
| 381 | int i, irq, irqs; | 381 | int i, irq, irqs; |
| 382 | struct platform_device *pmu_device = armpmu->plat_device; | 382 | struct platform_device *pmu_device = armpmu->plat_device; |
| 383 | struct arm_pmu_platdata *plat = | ||
| 384 | dev_get_platdata(&pmu_device->dev); | ||
| 383 | 385 | ||
| 384 | irqs = min(pmu_device->num_resources, num_possible_cpus()); | 386 | irqs = min(pmu_device->num_resources, num_possible_cpus()); |
| 385 | 387 | ||
| @@ -387,8 +389,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu) | |||
| 387 | if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) | 389 | if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) |
| 388 | continue; | 390 | continue; |
| 389 | irq = platform_get_irq(pmu_device, i); | 391 | irq = platform_get_irq(pmu_device, i); |
| 390 | if (irq >= 0) | 392 | if (irq >= 0) { |
| 393 | if (plat && plat->disable_irq) | ||
| 394 | plat->disable_irq(irq); | ||
| 391 | free_irq(irq, armpmu); | 395 | free_irq(irq, armpmu); |
| 396 | } | ||
| 392 | } | 397 | } |
| 393 | 398 | ||
| 394 | release_pmu(armpmu->type); | 399 | release_pmu(armpmu->type); |
| @@ -448,7 +453,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) | |||
| 448 | irq); | 453 | irq); |
| 449 | armpmu_release_hardware(armpmu); | 454 | armpmu_release_hardware(armpmu); |
| 450 | return err; | 455 | return err; |
| 451 | } | 456 | } else if (plat && plat->enable_irq) |
| 457 | plat->enable_irq(irq); | ||
| 452 | 458 | ||
| 453 | cpumask_set_cpu(i, &armpmu->active_irqs); | 459 | cpumask_set_cpu(i, &armpmu->active_irqs); |
| 454 | } | 460 | } |
