aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/perf/arm_pmu.c53
-rw-r--r--include/linux/perf/arm_pmu.h1
2 files changed, 38 insertions, 16 deletions
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index ae9fc6c6add3..f6ab4f7f75bf 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -685,6 +685,9 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
685 return 0; 685 return 0;
686} 686}
687 687
688static DEFINE_MUTEX(arm_pmu_mutex);
689static LIST_HEAD(arm_pmu_list);
690
688/* 691/*
689 * PMU hardware loses all context when a CPU goes offline. 692 * PMU hardware loses all context when a CPU goes offline.
690 * When a CPU is hotplugged back in, since some hardware registers are 693 * When a CPU is hotplugged back in, since some hardware registers are
@@ -693,12 +696,17 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
693 */ 696 */
694static int arm_perf_starting_cpu(unsigned int cpu) 697static int arm_perf_starting_cpu(unsigned int cpu)
695{ 698{
696 if (!__oprofile_cpu_pmu) 699 struct arm_pmu *pmu;
697 return 0; 700
698 if (!cpumask_test_cpu(cpu, &__oprofile_cpu_pmu->supported_cpus)) 701 mutex_lock(&arm_pmu_mutex);
699 return 0; 702 list_for_each_entry(pmu, &arm_pmu_list, entry) {
700 if (__oprofile_cpu_pmu->reset) 703
701 __oprofile_cpu_pmu->reset(__oprofile_cpu_pmu); 704 if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
705 continue;
706 if (pmu->reset)
707 pmu->reset(pmu);
708 }
709 mutex_unlock(&arm_pmu_mutex);
702 return 0; 710 return 0;
703} 711}
704 712
@@ -810,11 +818,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
810 if (!cpu_hw_events) 818 if (!cpu_hw_events)
811 return -ENOMEM; 819 return -ENOMEM;
812 820
813 err = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_STARTING, 821 mutex_lock(&arm_pmu_mutex);
814 "AP_PERF_ARM_STARTING", 822 list_add_tail(&cpu_pmu->entry, &arm_pmu_list);
815 arm_perf_starting_cpu, NULL); 823 mutex_unlock(&arm_pmu_mutex);
816 if (err)
817 goto out_hw_events;
818 824
819 err = cpu_pm_pmu_register(cpu_pmu); 825 err = cpu_pm_pmu_register(cpu_pmu);
820 if (err) 826 if (err)
@@ -850,8 +856,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
850 return 0; 856 return 0;
851 857
852out_unregister: 858out_unregister:
853 cpuhp_remove_state_nocalls(CPUHP_AP_PERF_ARM_STARTING); 859 mutex_lock(&arm_pmu_mutex);
854out_hw_events: 860 list_del(&cpu_pmu->entry);
861 mutex_unlock(&arm_pmu_mutex);
855 free_percpu(cpu_hw_events); 862 free_percpu(cpu_hw_events);
856 return err; 863 return err;
857} 864}
@@ -859,7 +866,9 @@ out_hw_events:
859static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu) 866static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
860{ 867{
861 cpu_pm_pmu_unregister(cpu_pmu); 868 cpu_pm_pmu_unregister(cpu_pmu);
862 cpuhp_remove_state_nocalls(CPUHP_AP_PERF_ARM_STARTING); 869 mutex_lock(&arm_pmu_mutex);
870 list_del(&cpu_pmu->entry);
871 mutex_unlock(&arm_pmu_mutex);
863 free_percpu(cpu_pmu->hw_events); 872 free_percpu(cpu_pmu->hw_events);
864} 873}
865 874
@@ -1019,8 +1028,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
1019 if (ret) 1028 if (ret)
1020 goto out_destroy; 1029 goto out_destroy;
1021 1030
1022 WARN(__oprofile_cpu_pmu, "%s(): missing PMU strucure for CPU-hotplug\n",
1023 __func__);
1024 if (!__oprofile_cpu_pmu) 1031 if (!__oprofile_cpu_pmu)
1025 __oprofile_cpu_pmu = pmu; 1032 __oprofile_cpu_pmu = pmu;
1026 1033
@@ -1038,3 +1045,17 @@ out_free:
1038 kfree(pmu); 1045 kfree(pmu);
1039 return ret; 1046 return ret;
1040} 1047}
1048
1049static int arm_pmu_hp_init(void)
1050{
1051 int ret;
1052
1053 ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_STARTING,
1054 "AP_PERF_ARM_STARTING",
1055 arm_perf_starting_cpu, NULL);
1056 if (ret)
1057 pr_err("CPU hotplug notifier for ARM PMU could not be registered: %d\n",
1058 ret);
1059 return ret;
1060}
1061subsys_initcall(arm_pmu_hp_init);
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index e6ed34eb2b2b..e18843809eec 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -109,6 +109,7 @@ struct arm_pmu {
109 DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS); 109 DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS);
110 struct platform_device *plat_device; 110 struct platform_device *plat_device;
111 struct pmu_hw_events __percpu *hw_events; 111 struct pmu_hw_events __percpu *hw_events;
112 struct list_head entry;
112 struct notifier_block cpu_pm_nb; 113 struct notifier_block cpu_pm_nb;
113}; 114};
114 115