aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-07-13 13:16:10 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-14 03:34:32 -0400
commit95ca792c7582fde2c435f84cbe872616e3c951f6 (patch)
tree6854c753c1567fb9957af9c4f85b0d4b01045fbb
parent00e16c3d68fce504e880f59c9bdf23b2a4759d6d (diff)
perf/x86: Convert the core to the hotplug state machine
Replace the perf_notifier() install mechanism, which invokes magically the callback on the current CPU. Convert the hardware specific callbacks which are invoked from the x86 perf core to return proper error codes instead of totally pointless NOTIFY_BAD return values. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Adam Borowski <kilobyte@angband.pl> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Borislav Petkov <bp@suse.de> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Vince Weaver <vincent.weaver@maine.edu> Cc: rt@linutronix.de Link: http://lkml.kernel.org/r/20160713153333.670720553@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/events/amd/core.c6
-rw-r--r--arch/x86/events/core.c103
-rw-r--r--arch/x86/events/intel/core.c4
-rw-r--r--include/linux/cpuhotplug.h3
4 files changed, 74 insertions, 42 deletions
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index bd3e8421b57c..e07a22bb9308 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -370,13 +370,13 @@ static int amd_pmu_cpu_prepare(int cpu)
370 WARN_ON_ONCE(cpuc->amd_nb); 370 WARN_ON_ONCE(cpuc->amd_nb);
371 371
372 if (!x86_pmu.amd_nb_constraints) 372 if (!x86_pmu.amd_nb_constraints)
373 return NOTIFY_OK; 373 return 0;
374 374
375 cpuc->amd_nb = amd_alloc_nb(cpu); 375 cpuc->amd_nb = amd_alloc_nb(cpu);
376 if (!cpuc->amd_nb) 376 if (!cpuc->amd_nb)
377 return NOTIFY_BAD; 377 return -ENOMEM;
378 378
379 return NOTIFY_OK; 379 return 0;
380} 380}
381 381
382static void amd_pmu_cpu_starting(int cpu) 382static void amd_pmu_cpu_starting(int cpu)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 26ced536005a..4ce3745f26f5 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1477,49 +1477,49 @@ NOKPROBE_SYMBOL(perf_event_nmi_handler);
1477struct event_constraint emptyconstraint; 1477struct event_constraint emptyconstraint;
1478struct event_constraint unconstrained; 1478struct event_constraint unconstrained;
1479 1479
1480static int 1480static int x86_pmu_prepare_cpu(unsigned int cpu)
1481x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
1482{ 1481{
1483 unsigned int cpu = (long)hcpu;
1484 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); 1482 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
1485 int i, ret = NOTIFY_OK; 1483 int i;
1486
1487 switch (action & ~CPU_TASKS_FROZEN) {
1488 case CPU_UP_PREPARE:
1489 for (i = 0 ; i < X86_PERF_KFREE_MAX; i++)
1490 cpuc->kfree_on_online[i] = NULL;
1491 if (x86_pmu.cpu_prepare)
1492 ret = x86_pmu.cpu_prepare(cpu);
1493 break;
1494
1495 case CPU_STARTING:
1496 if (x86_pmu.cpu_starting)
1497 x86_pmu.cpu_starting(cpu);
1498 break;
1499 1484
1500 case CPU_ONLINE: 1485 for (i = 0 ; i < X86_PERF_KFREE_MAX; i++)
1501 for (i = 0 ; i < X86_PERF_KFREE_MAX; i++) { 1486 cpuc->kfree_on_online[i] = NULL;
1502 kfree(cpuc->kfree_on_online[i]); 1487 if (x86_pmu.cpu_prepare)
1503 cpuc->kfree_on_online[i] = NULL; 1488 return x86_pmu.cpu_prepare(cpu);
1504 } 1489 return 0;
1505 break; 1490}
1506 1491
1507 case CPU_DYING: 1492static int x86_pmu_dead_cpu(unsigned int cpu)
1508 if (x86_pmu.cpu_dying) 1493{
1509 x86_pmu.cpu_dying(cpu); 1494 if (x86_pmu.cpu_dead)
1510 break; 1495 x86_pmu.cpu_dead(cpu);
1496 return 0;
1497}
1511 1498
1512 case CPU_UP_CANCELED: 1499static int x86_pmu_online_cpu(unsigned int cpu)
1513 case CPU_DEAD: 1500{
1514 if (x86_pmu.cpu_dead) 1501 struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
1515 x86_pmu.cpu_dead(cpu); 1502 int i;
1516 break;
1517 1503
1518 default: 1504 for (i = 0 ; i < X86_PERF_KFREE_MAX; i++) {
1519 break; 1505 kfree(cpuc->kfree_on_online[i]);
1506 cpuc->kfree_on_online[i] = NULL;
1520 } 1507 }
1508 return 0;
1509}
1521 1510
1522 return ret; 1511static int x86_pmu_starting_cpu(unsigned int cpu)
1512{
1513 if (x86_pmu.cpu_starting)
1514 x86_pmu.cpu_starting(cpu);
1515 return 0;
1516}
1517
1518static int x86_pmu_dying_cpu(unsigned int cpu)
1519{
1520 if (x86_pmu.cpu_dying)
1521 x86_pmu.cpu_dying(cpu);
1522 return 0;
1523} 1523}
1524 1524
1525static void __init pmu_check_apic(void) 1525static void __init pmu_check_apic(void)
@@ -1764,10 +1764,39 @@ static int __init init_hw_perf_events(void)
1764 pr_info("... fixed-purpose events: %d\n", x86_pmu.num_counters_fixed); 1764 pr_info("... fixed-purpose events: %d\n", x86_pmu.num_counters_fixed);
1765 pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl); 1765 pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl);
1766 1766
1767 perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); 1767 /*
1768 perf_cpu_notifier(x86_pmu_notifier); 1768 * Install callbacks. Core will call them for each online
1769 * cpu.
1770 */
1771 err = cpuhp_setup_state(CPUHP_PERF_X86_PREPARE, "PERF_X86_PREPARE",
1772 x86_pmu_prepare_cpu, x86_pmu_dead_cpu);
1773 if (err)
1774 return err;
1775
1776 err = cpuhp_setup_state(CPUHP_AP_PERF_X86_STARTING,
1777 "AP_PERF_X86_STARTING", x86_pmu_starting_cpu,
1778 x86_pmu_dying_cpu);
1779 if (err)
1780 goto out;
1781
1782 err = cpuhp_setup_state(CPUHP_AP_PERF_X86_ONLINE, "AP_PERF_X86_ONLINE",
1783 x86_pmu_online_cpu, NULL);
1784 if (err)
1785 goto out1;
1786
1787 err = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
1788 if (err)
1789 goto out2;
1769 1790
1770 return 0; 1791 return 0;
1792
1793out2:
1794 cpuhp_remove_state(CPUHP_AP_PERF_X86_ONLINE);
1795out1:
1796 cpuhp_remove_state(CPUHP_AP_PERF_X86_STARTING);
1797out:
1798 cpuhp_remove_state(CPUHP_PERF_X86_PREPARE);
1799 return err;
1771} 1800}
1772early_initcall(init_hw_perf_events); 1801early_initcall(init_hw_perf_events);
1773 1802
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 9b4f9d3ce465..6a1441be485b 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3050,7 +3050,7 @@ static int intel_pmu_cpu_prepare(int cpu)
3050 cpuc->excl_thread_id = 0; 3050 cpuc->excl_thread_id = 0;
3051 } 3051 }
3052 3052
3053 return NOTIFY_OK; 3053 return 0;
3054 3054
3055err_constraint_list: 3055err_constraint_list:
3056 kfree(cpuc->constraint_list); 3056 kfree(cpuc->constraint_list);
@@ -3061,7 +3061,7 @@ err_shared_regs:
3061 cpuc->shared_regs = NULL; 3061 cpuc->shared_regs = NULL;
3062 3062
3063err: 3063err:
3064 return NOTIFY_BAD; 3064 return -ENOMEM;
3065} 3065}
3066 3066
3067static void intel_pmu_cpu_starting(int cpu) 3067static void intel_pmu_cpu_starting(int cpu)
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 067082e3fd41..858915f40fb3 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -5,6 +5,7 @@ enum cpuhp_state {
5 CPUHP_OFFLINE, 5 CPUHP_OFFLINE,
6 CPUHP_CREATE_THREADS, 6 CPUHP_CREATE_THREADS,
7 CPUHP_PERF_PREPARE, 7 CPUHP_PERF_PREPARE,
8 CPUHP_PERF_X86_PREPARE,
8 CPUHP_NOTIFY_PREPARE, 9 CPUHP_NOTIFY_PREPARE,
9 CPUHP_BRINGUP_CPU, 10 CPUHP_BRINGUP_CPU,
10 CPUHP_AP_IDLE_DEAD, 11 CPUHP_AP_IDLE_DEAD,
@@ -17,6 +18,7 @@ enum cpuhp_state {
17 CPUHP_AP_IRQ_ARMADA_CASC_STARTING, 18 CPUHP_AP_IRQ_ARMADA_CASC_STARTING,
18 CPUHP_AP_IRQ_BCM2836_STARTING, 19 CPUHP_AP_IRQ_BCM2836_STARTING,
19 CPUHP_AP_ARM_MVEBU_COHERENCY, 20 CPUHP_AP_ARM_MVEBU_COHERENCY,
21 CPUHP_AP_PERF_X86_STARTING,
20 CPUHP_AP_NOTIFY_STARTING, 22 CPUHP_AP_NOTIFY_STARTING,
21 CPUHP_AP_ONLINE, 23 CPUHP_AP_ONLINE,
22 CPUHP_TEARDOWN_CPU, 24 CPUHP_TEARDOWN_CPU,
@@ -24,6 +26,7 @@ enum cpuhp_state {
24 CPUHP_AP_SMPBOOT_THREADS, 26 CPUHP_AP_SMPBOOT_THREADS,
25 CPUHP_AP_X86_VDSO_VMA_ONLINE, 27 CPUHP_AP_X86_VDSO_VMA_ONLINE,
26 CPUHP_AP_PERF_ONLINE, 28 CPUHP_AP_PERF_ONLINE,
29 CPUHP_AP_PERF_X86_ONLINE,
27 CPUHP_AP_NOTIFY_ONLINE, 30 CPUHP_AP_NOTIFY_ONLINE,
28 CPUHP_AP_ONLINE_DYN, 31 CPUHP_AP_ONLINE_DYN,
29 CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, 32 CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30,