ARM: perf: move active_events into struct arm_pmu

This patch moves the active_events counter into struct arm_pmu, in
preparation for supporting multiple PMUs. This also moves
pmu_reserve_mutex, as it is used to guard accesses to active_events.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
Mark Rutland 2011-04-27 11:20:11 +01:00 committed by Will Deacon
parent c47f8684ba
commit 03b7898d30
1 changed files with 20 additions and 11 deletions

View File

@ -82,6 +82,8 @@ struct arm_pmu {
const unsigned (*event_map)[PERF_COUNT_HW_MAX]; const unsigned (*event_map)[PERF_COUNT_HW_MAX];
u32 raw_event_mask; u32 raw_event_mask;
int num_events; int num_events;
atomic_t active_events;
struct mutex reserve_mutex;
u64 max_period; u64 max_period;
}; };
@ -454,15 +456,15 @@ armpmu_reserve_hardware(void)
return 0; return 0;
} }
static atomic_t active_events = ATOMIC_INIT(0);
static DEFINE_MUTEX(pmu_reserve_mutex);
static void static void
hw_perf_event_destroy(struct perf_event *event) hw_perf_event_destroy(struct perf_event *event)
{ {
if (atomic_dec_and_mutex_lock(&active_events, &pmu_reserve_mutex)) { atomic_t *active_events = &armpmu->active_events;
struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
armpmu_release_hardware(); armpmu_release_hardware();
mutex_unlock(&pmu_reserve_mutex); mutex_unlock(pmu_reserve_mutex);
} }
} }
@ -543,6 +545,7 @@ __hw_perf_event_init(struct perf_event *event)
static int armpmu_event_init(struct perf_event *event) static int armpmu_event_init(struct perf_event *event)
{ {
int err = 0; int err = 0;
atomic_t *active_events = &armpmu->active_events;
switch (event->attr.type) { switch (event->attr.type) {
case PERF_TYPE_RAW: case PERF_TYPE_RAW:
@ -556,15 +559,14 @@ static int armpmu_event_init(struct perf_event *event)
event->destroy = hw_perf_event_destroy; event->destroy = hw_perf_event_destroy;
if (!atomic_inc_not_zero(&active_events)) { if (!atomic_inc_not_zero(active_events)) {
mutex_lock(&pmu_reserve_mutex); mutex_lock(&armpmu->reserve_mutex);
if (atomic_read(&active_events) == 0) { if (atomic_read(active_events) == 0)
err = armpmu_reserve_hardware(); err = armpmu_reserve_hardware();
}
if (!err) if (!err)
atomic_inc(&active_events); atomic_inc(active_events);
mutex_unlock(&pmu_reserve_mutex); mutex_unlock(&armpmu->reserve_mutex);
} }
if (err) if (err)
@ -613,6 +615,12 @@ static struct pmu pmu = {
.read = armpmu_read, .read = armpmu_read,
}; };
static void __init armpmu_init(struct arm_pmu *armpmu)
{
atomic_set(&armpmu->active_events, 0);
mutex_init(&armpmu->reserve_mutex);
}
/* Include the PMU-specific implementations. */ /* Include the PMU-specific implementations. */
#include "perf_event_xscale.c" #include "perf_event_xscale.c"
#include "perf_event_v6.c" #include "perf_event_v6.c"
@ -718,6 +726,7 @@ init_hw_perf_events(void)
if (armpmu) { if (armpmu) {
pr_info("enabled with %s PMU driver, %d counters available\n", pr_info("enabled with %s PMU driver, %d counters available\n",
armpmu->name, armpmu->num_events); armpmu->name, armpmu->num_events);
armpmu_init(armpmu);
perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
} else { } else {
pr_info("no hardware support available\n"); pr_info("no hardware support available\n");