static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
struct arm_pmu {
+ struct pmu pmu;
enum arm_perf_pmu_ids id;
enum arm_pmu_type type;
cpumask_t active_irqs;
struct cpu_hw_events *(*get_hw_events)(void);
};
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
/* Set at runtime when we know what CPU type we are. */
static struct arm_pmu *armpmu;
struct hw_perf_event *hwc,
int idx)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
s64 left = local64_read(&hwc->period_left);
s64 period = hwc->sample_period;
int ret = 0;
struct hw_perf_event *hwc,
int idx, int overflow)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
u64 delta, prev_raw_count, new_raw_count;
again:
static void
armpmu_stop(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
/*
static void
armpmu_start(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
/*
static void
armpmu_del(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct cpu_hw_events *cpuc = armpmu->get_hw_events();
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
static int
armpmu_add(struct perf_event *event, int flags)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct cpu_hw_events *cpuc = armpmu->get_hw_events();
struct hw_perf_event *hwc = &event->hw;
int idx;
return err;
}
-static struct pmu pmu;
-
static int
validate_event(struct cpu_hw_events *cpuc,
struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event fake_event = event->hw;
struct pmu *leader_pmu = event->group_leader->pmu;
static irqreturn_t armpmu_platform_irq(int irq, void *dev)
{
+ struct arm_pmu *armpmu = (struct arm_pmu *) dev;
struct platform_device *plat_device = armpmu->plat_device;
struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
}
static void
-armpmu_release_hardware(void)
+armpmu_release_hardware(struct arm_pmu *armpmu)
{
int i, irq, irqs;
struct platform_device *pmu_device = armpmu->plat_device;
continue;
irq = platform_get_irq(pmu_device, i);
if (irq >= 0)
- free_irq(irq, NULL);
+ free_irq(irq, armpmu);
}
release_pmu(armpmu->type);
}
static int
-armpmu_reserve_hardware(void)
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
{
struct arm_pmu_platdata *plat;
irq_handler_t handle_irq;
err = request_irq(irq, handle_irq,
IRQF_DISABLED | IRQF_NOBALANCING,
- "arm-pmu", NULL);
+ "arm-pmu", armpmu);
if (err) {
pr_err("unable to request IRQ%d for ARM PMU counters\n",
irq);
- armpmu_release_hardware();
+ armpmu_release_hardware(armpmu);
return err;
}
static void
hw_perf_event_destroy(struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
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(armpmu);
mutex_unlock(pmu_reserve_mutex);
}
}
static int
__hw_perf_event_init(struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = &event->hw;
int mapping, err;
static int armpmu_event_init(struct perf_event *event)
{
+ struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
int err = 0;
atomic_t *active_events = &armpmu->active_events;
if (!atomic_inc_not_zero(active_events)) {
mutex_lock(&armpmu->reserve_mutex);
if (atomic_read(active_events) == 0)
- err = armpmu_reserve_hardware();
+ err = armpmu_reserve_hardware(armpmu);
if (!err)
atomic_inc(active_events);
static void armpmu_enable(struct pmu *pmu)
{
+ struct arm_pmu *armpmu = to_arm_pmu(pmu);
/* Enable all of the perf events on hardware. */
int idx, enabled = 0;
struct cpu_hw_events *cpuc = armpmu->get_hw_events();
static void armpmu_disable(struct pmu *pmu)
{
+ struct arm_pmu *armpmu = to_arm_pmu(pmu);
armpmu->stop();
}
-static struct pmu pmu = {
- .pmu_enable = armpmu_enable,
- .pmu_disable = armpmu_disable,
- .event_init = armpmu_event_init,
- .add = armpmu_add,
- .del = armpmu_del,
- .start = armpmu_start,
- .stop = armpmu_stop,
- .read = armpmu_read,
-};
-
static void __init armpmu_init(struct arm_pmu *armpmu)
{
atomic_set(&armpmu->active_events, 0);
mutex_init(&armpmu->reserve_mutex);
+
+ armpmu->pmu = (struct pmu) {
+ .pmu_enable = armpmu_enable,
+ .pmu_disable = armpmu_disable,
+ .event_init = armpmu_event_init,
+ .add = armpmu_add,
+ .del = armpmu_del,
+ .start = armpmu_start,
+ .stop = armpmu_stop,
+ .read = armpmu_read,
+ };
+}
+
+static int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+ armpmu_init(armpmu);
+ return perf_pmu_register(&armpmu->pmu, name, type);
}
/* Include the PMU-specific implementations. */
pr_info("enabled with %s PMU driver, %d counters available\n",
armpmu->name, armpmu->num_events);
cpu_pmu_init(armpmu);
- armpmu_init(armpmu);
- perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
+ armpmu_register(armpmu, "cpu", PERF_TYPE_RAW);
} else {
pr_info("no hardware support available\n");
}