Loading arch/arm64/kernel/perf_event.c +78 −30 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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; /* Loading @@ -425,6 +472,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) cpumask_set_cpu(i, &armpmu->active_irqs); } } return 0; } Loading Loading
arch/arm64/kernel/perf_event.c +78 −30 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading @@ -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; /* Loading @@ -425,6 +472,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) cpumask_set_cpu(i, &armpmu->active_irqs); } } return 0; } Loading