summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/pmu.h15
-rw-r--r--arch/arm/kernel/perf_event.c10
2 files changed, 20 insertions, 5 deletions
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 0bda22c094a..b5a5be2536c 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -27,13 +27,22 @@ enum arm_pmu_type {
/*
* struct arm_pmu_platdata - ARM PMU platform data
*
- * @handle_irq: an optional handler which will be called from the interrupt and
- * passed the address of the low level handler, and can be used to implement
- * any platform specific handling before or after calling it.
+ * @handle_irq: an optional handler which will be called from the
+ * interrupt and passed the address of the low level handler,
+ * and can be used to implement any platform specific handling
+ * before or after calling it.
+ * @enable_irq: an optional handler which will be called after
+ * request_irq and be used to handle some platform specific
+ * irq enablement
+ * @disable_irq: an optional handler which will be called before
+ * free_irq and be used to handle some platform specific
+ * irq disablement
*/
struct arm_pmu_platdata {
irqreturn_t (*handle_irq)(int irq, void *dev,
irq_handler_t pmu_handler);
+ void (*enable_irq)(int irq);
+ void (*disable_irq)(int irq);
};
#ifdef CONFIG_CPU_HAS_PMU
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c475379199b..daa1db84452 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)
{
int i, irq, irqs;
struct platform_device *pmu_device = armpmu->plat_device;
+ struct arm_pmu_platdata *plat =
+ dev_get_platdata(&pmu_device->dev);
irqs = min(pmu_device->num_resources, num_possible_cpus());
@@ -387,8 +389,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
continue;
irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
+ if (irq >= 0) {
+ if (plat && plat->disable_irq)
+ plat->disable_irq(irq);
free_irq(irq, armpmu);
+ }
}
release_pmu(armpmu->type);
@@ -448,7 +453,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
irq);
armpmu_release_hardware(armpmu);
return err;
- }
+ } else if (plat && plat->enable_irq)
+ plat->enable_irq(irq);
cpumask_set_cpu(i, &armpmu->active_irqs);
}