diff options
author | Richard Cochran <rcochran@linutronix.de> | 2016-07-13 13:16:16 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-14 03:34:35 -0400 |
commit | f07048270423622a2428a9b90929c76e92777caa (patch) | |
tree | ecc2b95abda9fd5645b277842d4491115f15f0cf | |
parent | 8b5b773d6245138c461b3a3e242339fa50fa9c58 (diff) |
perf/x86/intel/cqm: Convert Intel CQM to hotplug state machine
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matt Fleming <matt.fleming@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vikas Shivappa <vikas.shivappa@linux.intel.com>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153334.096956222@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/events/intel/cqm.c | 49 | ||||
-rw-r--r-- | include/linux/cpuhotplug.h | 2 |
2 files changed, 20 insertions, 31 deletions
diff --git a/arch/x86/events/intel/cqm.c b/arch/x86/events/intel/cqm.c index 7b5fd811ef45..783c49ddef29 100644 --- a/arch/x86/events/intel/cqm.c +++ b/arch/x86/events/intel/cqm.c | |||
@@ -1577,7 +1577,7 @@ static inline void cqm_pick_event_reader(int cpu) | |||
1577 | cpumask_set_cpu(cpu, &cqm_cpumask); | 1577 | cpumask_set_cpu(cpu, &cqm_cpumask); |
1578 | } | 1578 | } |
1579 | 1579 | ||
1580 | static void intel_cqm_cpu_starting(unsigned int cpu) | 1580 | static int intel_cqm_cpu_starting(unsigned int cpu) |
1581 | { | 1581 | { |
1582 | struct intel_pqr_state *state = &per_cpu(pqr_state, cpu); | 1582 | struct intel_pqr_state *state = &per_cpu(pqr_state, cpu); |
1583 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 1583 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
@@ -1588,39 +1588,26 @@ static void intel_cqm_cpu_starting(unsigned int cpu) | |||
1588 | 1588 | ||
1589 | WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid); | 1589 | WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid); |
1590 | WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale); | 1590 | WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale); |
1591 | |||
1592 | cqm_pick_event_reader(cpu); | ||
1593 | return 0; | ||
1591 | } | 1594 | } |
1592 | 1595 | ||
1593 | static void intel_cqm_cpu_exit(unsigned int cpu) | 1596 | static int intel_cqm_cpu_exit(unsigned int cpu) |
1594 | { | 1597 | { |
1595 | int target; | 1598 | int target; |
1596 | 1599 | ||
1597 | /* Is @cpu the current cqm reader for this package ? */ | 1600 | /* Is @cpu the current cqm reader for this package ? */ |
1598 | if (!cpumask_test_and_clear_cpu(cpu, &cqm_cpumask)) | 1601 | if (!cpumask_test_and_clear_cpu(cpu, &cqm_cpumask)) |
1599 | return; | 1602 | return 0; |
1600 | 1603 | ||
1601 | /* Find another online reader in this package */ | 1604 | /* Find another online reader in this package */ |
1602 | target = cpumask_any_but(topology_core_cpumask(cpu), cpu); | 1605 | target = cpumask_any_but(topology_core_cpumask(cpu), cpu); |
1603 | 1606 | ||
1604 | if (target < nr_cpu_ids) | 1607 | if (target < nr_cpu_ids) |
1605 | cpumask_set_cpu(target, &cqm_cpumask); | 1608 | cpumask_set_cpu(target, &cqm_cpumask); |
1606 | } | ||
1607 | |||
1608 | static int intel_cqm_cpu_notifier(struct notifier_block *nb, | ||
1609 | unsigned long action, void *hcpu) | ||
1610 | { | ||
1611 | unsigned int cpu = (unsigned long)hcpu; | ||
1612 | |||
1613 | switch (action & ~CPU_TASKS_FROZEN) { | ||
1614 | case CPU_DOWN_PREPARE: | ||
1615 | intel_cqm_cpu_exit(cpu); | ||
1616 | break; | ||
1617 | case CPU_STARTING: | ||
1618 | intel_cqm_cpu_starting(cpu); | ||
1619 | cqm_pick_event_reader(cpu); | ||
1620 | break; | ||
1621 | } | ||
1622 | 1609 | ||
1623 | return NOTIFY_OK; | 1610 | return 0; |
1624 | } | 1611 | } |
1625 | 1612 | ||
1626 | static const struct x86_cpu_id intel_cqm_match[] = { | 1613 | static const struct x86_cpu_id intel_cqm_match[] = { |
@@ -1682,7 +1669,7 @@ out: | |||
1682 | static int __init intel_cqm_init(void) | 1669 | static int __init intel_cqm_init(void) |
1683 | { | 1670 | { |
1684 | char *str = NULL, scale[20]; | 1671 | char *str = NULL, scale[20]; |
1685 | int i, cpu, ret; | 1672 | int cpu, ret; |
1686 | 1673 | ||
1687 | if (x86_match_cpu(intel_cqm_match)) | 1674 | if (x86_match_cpu(intel_cqm_match)) |
1688 | cqm_enabled = true; | 1675 | cqm_enabled = true; |
@@ -1705,8 +1692,7 @@ static int __init intel_cqm_init(void) | |||
1705 | * | 1692 | * |
1706 | * Also, check that the scales match on all cpus. | 1693 | * Also, check that the scales match on all cpus. |
1707 | */ | 1694 | */ |
1708 | cpu_notifier_register_begin(); | 1695 | get_online_cpus(); |
1709 | |||
1710 | for_each_online_cpu(cpu) { | 1696 | for_each_online_cpu(cpu) { |
1711 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 1697 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
1712 | 1698 | ||
@@ -1743,11 +1729,6 @@ static int __init intel_cqm_init(void) | |||
1743 | if (ret) | 1729 | if (ret) |
1744 | goto out; | 1730 | goto out; |
1745 | 1731 | ||
1746 | for_each_online_cpu(i) { | ||
1747 | intel_cqm_cpu_starting(i); | ||
1748 | cqm_pick_event_reader(i); | ||
1749 | } | ||
1750 | |||
1751 | if (mbm_enabled) | 1732 | if (mbm_enabled) |
1752 | ret = intel_mbm_init(); | 1733 | ret = intel_mbm_init(); |
1753 | if (ret && !cqm_enabled) | 1734 | if (ret && !cqm_enabled) |
@@ -1772,12 +1753,18 @@ static int __init intel_cqm_init(void) | |||
1772 | pr_info("Intel MBM enabled\n"); | 1753 | pr_info("Intel MBM enabled\n"); |
1773 | 1754 | ||
1774 | /* | 1755 | /* |
1775 | * Register the hot cpu notifier once we are sure cqm | 1756 | * Setup the hot cpu notifier once we are sure cqm |
1776 | * is enabled to avoid notifier leak. | 1757 | * is enabled to avoid notifier leak. |
1777 | */ | 1758 | */ |
1778 | __perf_cpu_notifier(intel_cqm_cpu_notifier); | 1759 | cpuhp_setup_state(CPUHP_AP_PERF_X86_CQM_STARTING, |
1760 | "AP_PERF_X86_CQM_STARTING", | ||
1761 | intel_cqm_cpu_starting, NULL); | ||
1762 | cpuhp_setup_state(CPUHP_AP_PERF_X86_CQM_ONLINE, "AP_PERF_X86_CQM_ONLINE", | ||
1763 | NULL, intel_cqm_cpu_exit); | ||
1764 | |||
1779 | out: | 1765 | out: |
1780 | cpu_notifier_register_done(); | 1766 | put_online_cpus(); |
1767 | |||
1781 | if (ret) { | 1768 | if (ret) { |
1782 | kfree(str); | 1769 | kfree(str); |
1783 | cqm_cleanup(); | 1770 | cqm_cleanup(); |
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 06d77fd0fda3..f9399eeba263 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -25,6 +25,7 @@ enum cpuhp_state { | |||
25 | CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING, | 25 | CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING, |
26 | CPUHP_AP_PERF_X86_STARTING, | 26 | CPUHP_AP_PERF_X86_STARTING, |
27 | CPUHP_AP_PERF_X86_AMD_IBS_STARTING, | 27 | CPUHP_AP_PERF_X86_AMD_IBS_STARTING, |
28 | CPUHP_AP_PERF_X86_CQM_STARTING, | ||
28 | CPUHP_AP_NOTIFY_STARTING, | 29 | CPUHP_AP_NOTIFY_STARTING, |
29 | CPUHP_AP_ONLINE, | 30 | CPUHP_AP_ONLINE, |
30 | CPUHP_TEARDOWN_CPU, | 31 | CPUHP_TEARDOWN_CPU, |
@@ -36,6 +37,7 @@ enum cpuhp_state { | |||
36 | CPUHP_AP_PERF_X86_UNCORE_ONLINE, | 37 | CPUHP_AP_PERF_X86_UNCORE_ONLINE, |
37 | CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE, | 38 | CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE, |
38 | CPUHP_AP_PERF_X86_RAPL_ONLINE, | 39 | CPUHP_AP_PERF_X86_RAPL_ONLINE, |
40 | CPUHP_AP_PERF_X86_CQM_ONLINE, | ||
39 | CPUHP_AP_NOTIFY_ONLINE, | 41 | CPUHP_AP_NOTIFY_ONLINE, |
40 | CPUHP_AP_ONLINE_DYN, | 42 | CPUHP_AP_ONLINE_DYN, |
41 | CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, | 43 | CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, |