Perf: Update power collapse support for perf

Update the CPU PM notifier functions in perf to use the new
perf data structures.

Change-Id: I0f183072b8de65057f56d92301c22d1e9f93218b
Signed-off-by: Ashwin Chaugule <ashwinc@codeaurora.org>
This commit is contained in:
Ashwin Chaugule
2012-06-07 13:41:37 -04:00
committed by Stephen Boyd
parent 419645cf2a
commit f999487712

View File

@@ -28,6 +28,8 @@
#include <asm/pmu.h>
#include <asm/stacktrace.h>
#include <linux/cpu_pm.h>
/*
* ARMv6 supports a maximum of 3 events, starting from index 0. If we add
* another platform that supports more, we need to increase this to be the
@@ -383,8 +385,6 @@ 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());
@@ -393,11 +393,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
continue;
irq = platform_get_irq(pmu_device, i);
armpmu->free_pmu_irq(irq);
if (irq >= 0) {
if (plat && plat->disable_irq)
plat->disable_irq(irq);
free_irq(irq, armpmu);
}
}
release_pmu(armpmu->type);
@@ -459,17 +454,6 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
return err;
}
err = request_irq(irq, handle_irq,
IRQF_DISABLED | IRQF_NOBALANCING,
"arm-pmu", armpmu);
if (err) {
pr_err("unable to request IRQ%d for ARM PMU counters\n",
irq);
armpmu_release_hardware(armpmu);
return err;
} else if (plat && plat->enable_irq)
plat->enable_irq(irq);
cpumask_set_cpu(i, &armpmu->active_irqs);
}
@@ -729,10 +713,76 @@ static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
return NOTIFY_OK;
}
static void armpmu_update_counters(void)
{
struct pmu_hw_events *hw_events;
int idx;
if (!cpu_pmu)
return;
hw_events = cpu_pmu->get_hw_events();
for (idx = 0; idx <= cpu_pmu->num_events; ++idx) {
struct perf_event *event = hw_events->events[idx];
if (!event)
continue;
armpmu_read(event);
}
}
static int cpu_has_active_perf(void)
{
struct pmu_hw_events *hw_events;
int enabled;
if (!cpu_pmu)
return 0;
hw_events = cpu_pmu->get_hw_events();
enabled = bitmap_weight(hw_events->used_mask, cpu_pmu->num_events);
if (enabled)
/*Even one event's existence is good enough.*/
return 1;
return 0;
}
static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
.notifier_call = pmu_cpu_notify,
};
/*TODO: Unify with pending patch from ARM */
static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
void *v)
{
switch (cmd) {
case CPU_PM_ENTER:
if (cpu_has_active_perf()) {
armpmu_update_counters();
perf_pmu_disable(&cpu_pmu->pmu);
}
break;
case CPU_PM_ENTER_FAILED:
case CPU_PM_EXIT:
if (cpu_has_active_perf() && cpu_pmu->reset) {
cpu_pmu->reset(NULL);
perf_pmu_enable(&cpu_pmu->pmu);
}
break;
}
return NOTIFY_OK;
}
static struct notifier_block perf_cpu_pm_notifier_block = {
.notifier_call = perf_cpu_pm_notifier,
};
/*
* CPU PMU identification and registration.
*/
@@ -809,6 +859,7 @@ init_hw_perf_events(void)
cpu_pmu_init(cpu_pmu);
register_cpu_notifier(&pmu_cpu_notifier);
armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
cpu_pm_register_notifier(&perf_cpu_pm_notifier_block);
} else {
pr_info("no hardware support available\n");
}