summaryrefslogtreecommitdiffstats
path: root/drivers/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 16:55:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 16:55:30 -0400
commita6408f6cb63ac0958fee7dbce7861ffb540d8a49 (patch)
treec94a835d343974171951e3b805e6bbbb02852ebc /drivers/perf
parent1a81a8f2a5918956e214bb718099a89e500e7ec5 (diff)
parent4fae16dffb812f0e0d98a0b2b0856ca48ca63e6c (diff)
Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull smp hotplug updates from Thomas Gleixner: "This is the next part of the hotplug rework. - Convert all notifiers with a priority assigned - Convert all CPU_STARTING/DYING notifiers The final removal of the STARTING/DYING infrastructure will happen when the merge window closes. Another 700 hundred line of unpenetrable maze gone :)" * 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (70 commits) timers/core: Correct callback order during CPU hot plug leds/trigger/cpu: Move from CPU_STARTING to ONLINE level powerpc/numa: Convert to hotplug state machine arm/perf: Fix hotplug state machine conversion irqchip/armada: Avoid unused function warnings ARC/time: Convert to hotplug state machine clocksource/atlas7: Convert to hotplug state machine clocksource/armada-370-xp: Convert to hotplug state machine clocksource/exynos_mct: Convert to hotplug state machine clocksource/arm_global_timer: Convert to hotplug state machine rcu: Convert rcutree to hotplug state machine KVM/arm/arm64/vgic-new: Convert to hotplug state machine smp/cfd: Convert core to hotplug state machine x86/x2apic: Convert to CPU hotplug state machine profile: Convert to hotplug state machine timers/core: Convert to hotplug state machine hrtimer: Convert to hotplug state machine x86/tboot: Convert to hotplug state machine arm64/armv8 deprecated: Convert to hotplug state machine hwtracing/coresight-etm4x: Convert to hotplug state machine ...
Diffstat (limited to 'drivers/perf')
-rw-r--r--drivers/perf/arm_pmu.c59
1 files changed, 37 insertions, 22 deletions
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 8e4d7f590b06..6ccb994bdfcb 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -688,30 +688,29 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
688 return 0; 688 return 0;
689} 689}
690 690
691static DEFINE_MUTEX(arm_pmu_mutex);
692static LIST_HEAD(arm_pmu_list);
693
691/* 694/*
692 * PMU hardware loses all context when a CPU goes offline. 695 * PMU hardware loses all context when a CPU goes offline.
693 * When a CPU is hotplugged back in, since some hardware registers are 696 * When a CPU is hotplugged back in, since some hardware registers are
694 * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading 697 * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
695 * junk values out of them. 698 * junk values out of them.
696 */ 699 */
697static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, 700static int arm_perf_starting_cpu(unsigned int cpu)
698 void *hcpu)
699{ 701{
700 int cpu = (unsigned long)hcpu; 702 struct arm_pmu *pmu;
701 struct arm_pmu *pmu = container_of(b, struct arm_pmu, hotplug_nb);
702
703 if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
704 return NOTIFY_DONE;
705
706 if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
707 return NOTIFY_DONE;
708 703
709 if (pmu->reset) 704 mutex_lock(&arm_pmu_mutex);
710 pmu->reset(pmu); 705 list_for_each_entry(pmu, &arm_pmu_list, entry) {
711 else
712 return NOTIFY_DONE;
713 706
714 return NOTIFY_OK; 707 if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
708 continue;
709 if (pmu->reset)
710 pmu->reset(pmu);
711 }
712 mutex_unlock(&arm_pmu_mutex);
713 return 0;
715} 714}
716 715
717#ifdef CONFIG_CPU_PM 716#ifdef CONFIG_CPU_PM
@@ -822,10 +821,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
822 if (!cpu_hw_events) 821 if (!cpu_hw_events)
823 return -ENOMEM; 822 return -ENOMEM;
824 823
825 cpu_pmu->hotplug_nb.notifier_call = cpu_pmu_notify; 824 mutex_lock(&arm_pmu_mutex);
826 err = register_cpu_notifier(&cpu_pmu->hotplug_nb); 825 list_add_tail(&cpu_pmu->entry, &arm_pmu_list);
827 if (err) 826 mutex_unlock(&arm_pmu_mutex);
828 goto out_hw_events;
829 827
830 err = cpu_pm_pmu_register(cpu_pmu); 828 err = cpu_pm_pmu_register(cpu_pmu);
831 if (err) 829 if (err)
@@ -861,8 +859,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
861 return 0; 859 return 0;
862 860
863out_unregister: 861out_unregister:
864 unregister_cpu_notifier(&cpu_pmu->hotplug_nb); 862 mutex_lock(&arm_pmu_mutex);
865out_hw_events: 863 list_del(&cpu_pmu->entry);
864 mutex_unlock(&arm_pmu_mutex);
866 free_percpu(cpu_hw_events); 865 free_percpu(cpu_hw_events);
867 return err; 866 return err;
868} 867}
@@ -870,7 +869,9 @@ out_hw_events:
870static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu) 869static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
871{ 870{
872 cpu_pm_pmu_unregister(cpu_pmu); 871 cpu_pm_pmu_unregister(cpu_pmu);
873 unregister_cpu_notifier(&cpu_pmu->hotplug_nb); 872 mutex_lock(&arm_pmu_mutex);
873 list_del(&cpu_pmu->entry);
874 mutex_unlock(&arm_pmu_mutex);
874 free_percpu(cpu_pmu->hw_events); 875 free_percpu(cpu_pmu->hw_events);
875} 876}
876 877
@@ -1061,3 +1062,17 @@ out_free:
1061 kfree(pmu); 1062 kfree(pmu);
1062 return ret; 1063 return ret;
1063} 1064}
1065
1066static int arm_pmu_hp_init(void)
1067{
1068 int ret;
1069
1070 ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_STARTING,
1071 "AP_PERF_ARM_STARTING",
1072 arm_perf_starting_cpu, NULL);
1073 if (ret)
1074 pr_err("CPU hotplug notifier for ARM PMU could not be registered: %d\n",
1075 ret);
1076 return ret;
1077}
1078subsys_initcall(arm_pmu_hp_init);