Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c154cdd authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "arm64: perf: add support for percpu pmu interrupt"

parents 52e33c8a 467c4004
Loading
Loading
Loading
Loading
+78 −30
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include <linux/bitmap.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/perf_event.h>
@@ -362,27 +363,54 @@ validate_group(struct perf_event *event)
	return 0;
}

static void
armpmu_disable_percpu_irq(void *data)
{
	unsigned int irq = *(unsigned int *)data;
	disable_percpu_irq(irq);
}

static void
armpmu_release_hardware(struct arm_pmu *armpmu)
{
	int i, irq, irqs;
	int irq;
	unsigned int i, irqs;
	struct platform_device *pmu_device = armpmu->plat_device;

	irqs = min(pmu_device->num_resources, num_possible_cpus());
	if (!irqs)
		return;

	irq = platform_get_irq(pmu_device, 0);
	if (irq <= 0)
		return;

	if (irq_is_per_cpu(irq)) {
		on_each_cpu(armpmu_disable_percpu_irq, &irq, 1);
		free_percpu_irq(irq, &cpu_hw_events);
	} else {
		for (i = 0; i < irqs; ++i) {
			if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
				continue;
			irq = platform_get_irq(pmu_device, i);
		if (irq >= 0)
			if (irq > 0)
				free_irq(irq, armpmu);
		}
	}
}

static void
armpmu_enable_percpu_irq(void *data)
{
	unsigned int irq = *(unsigned int *)data;
	enable_percpu_irq(irq, IRQ_TYPE_NONE);
}

static int
armpmu_reserve_hardware(struct arm_pmu *armpmu)
{
	int i, err, irq, irqs;
	int err, irq;
	unsigned int i, irqs;
	struct platform_device *pmu_device = armpmu->plat_device;

	if (!pmu_device) {
@@ -391,15 +419,34 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
	}

	irqs = min(pmu_device->num_resources, num_possible_cpus());
	if (irqs < 1) {
	if (!irqs) {
		pr_err("no irqs for PMUs defined\n");
		return -ENODEV;
	}

	irq = platform_get_irq(pmu_device, 0);
	if (irq <= 0) {
		pr_err("failed to get valid irq for PMU device\n");
		return -ENODEV;
	}

	if (irq_is_per_cpu(irq)) {
		err = request_percpu_irq(irq, armpmu->handle_irq,
				"arm-pmu", &cpu_hw_events);

		if (err) {
			pr_err("unable to request percpu IRQ%d for ARM PMU counters\n",
					irq);
			armpmu_release_hardware(armpmu);
			return err;
		}

		on_each_cpu(armpmu_enable_percpu_irq, &irq, 1);
	} else {
		for (i = 0; i < irqs; ++i) {
			err = 0;
			irq = platform_get_irq(pmu_device, i);
		if (irq < 0)
			if (irq <= 0)
				continue;

			/*
@@ -425,6 +472,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)

			cpumask_set_cpu(i, &armpmu->active_irqs);
		}
	}

	return 0;
}