Skip to content

Commit

Permalink
perf/x86/amd/uncore: Convert to hotplug state machine
Browse files Browse the repository at this point in the history
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: Chen Yucong <slaoub@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153333.839150380@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Richard Cochran authored and Ingo Molnar committed Jul 14, 2016
1 parent 1a246b9 commit 96b2bd3
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 90 deletions.
122 changes: 32 additions & 90 deletions arch/x86/events/amd/uncore.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ amd_uncore_find_online_sibling(struct amd_uncore *this,
return this;
}

static void amd_uncore_cpu_starting(unsigned int cpu)
static int amd_uncore_cpu_starting(unsigned int cpu)
{
unsigned int eax, ebx, ecx, edx;
struct amd_uncore *uncore;
Expand All @@ -384,6 +384,8 @@ static void amd_uncore_cpu_starting(unsigned int cpu)
uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_l2);
*per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
}

return 0;
}

static void uncore_online(unsigned int cpu,
Expand All @@ -398,13 +400,15 @@ static void uncore_online(unsigned int cpu,
cpumask_set_cpu(cpu, uncore->active_mask);
}

static void amd_uncore_cpu_online(unsigned int cpu)
static int amd_uncore_cpu_online(unsigned int cpu)
{
if (amd_uncore_nb)
uncore_online(cpu, amd_uncore_nb);

if (amd_uncore_l2)
uncore_online(cpu, amd_uncore_l2);

return 0;
}

static void uncore_down_prepare(unsigned int cpu,
Expand Down Expand Up @@ -433,13 +437,15 @@ static void uncore_down_prepare(unsigned int cpu,
}
}

static void amd_uncore_cpu_down_prepare(unsigned int cpu)
static int amd_uncore_cpu_down_prepare(unsigned int cpu)
{
if (amd_uncore_nb)
uncore_down_prepare(cpu, amd_uncore_nb);

if (amd_uncore_l2)
uncore_down_prepare(cpu, amd_uncore_l2);

return 0;
}

static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
Expand All @@ -454,74 +460,19 @@ static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
*per_cpu_ptr(uncores, cpu) = NULL;
}

static void amd_uncore_cpu_dead(unsigned int cpu)
static int amd_uncore_cpu_dead(unsigned int cpu)
{
if (amd_uncore_nb)
uncore_dead(cpu, amd_uncore_nb);

if (amd_uncore_l2)
uncore_dead(cpu, amd_uncore_l2);
}

static int
amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action,
void *hcpu)
{
unsigned int cpu = (long)hcpu;

switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
if (amd_uncore_cpu_up_prepare(cpu))
return notifier_from_errno(-ENOMEM);
break;

case CPU_STARTING:
amd_uncore_cpu_starting(cpu);
break;

case CPU_ONLINE:
amd_uncore_cpu_online(cpu);
break;

case CPU_DOWN_PREPARE:
amd_uncore_cpu_down_prepare(cpu);
break;

case CPU_UP_CANCELED:
case CPU_DEAD:
amd_uncore_cpu_dead(cpu);
break;

default:
break;
}

return NOTIFY_OK;
}

static struct notifier_block amd_uncore_cpu_notifier_block = {
.notifier_call = amd_uncore_cpu_notifier,
.priority = CPU_PRI_PERF + 1,
};

static void __init init_cpu_already_online(void *dummy)
{
unsigned int cpu = smp_processor_id();

amd_uncore_cpu_starting(cpu);
amd_uncore_cpu_online(cpu);
}

static void cleanup_cpu_online(void *dummy)
{
unsigned int cpu = smp_processor_id();

amd_uncore_cpu_dead(cpu);
return 0;
}

static int __init amd_uncore_init(void)
{
unsigned int cpu, cpu2;
int ret = -ENODEV;

if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
Expand Down Expand Up @@ -558,38 +509,29 @@ static int __init amd_uncore_init(void)
ret = 0;
}

if (ret)
goto fail_nodev;

cpu_notifier_register_begin();

/* init cpus already online before registering for hotplug notifier */
for_each_online_cpu(cpu) {
ret = amd_uncore_cpu_up_prepare(cpu);
if (ret)
goto fail_online;
smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
}

__register_cpu_notifier(&amd_uncore_cpu_notifier_block);
cpu_notifier_register_done();

/*
* Install callbacks. Core will call them for each online cpu.
*/
if (cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
"PERF_X86_AMD_UNCORE_PREP",
amd_uncore_cpu_up_prepare, amd_uncore_cpu_dead))
goto fail_l2;

if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
"AP_PERF_X86_AMD_UNCORE_STARTING",
amd_uncore_cpu_starting, NULL))
goto fail_prep;
if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE,
"AP_PERF_X86_AMD_UNCORE_ONLINE",
amd_uncore_cpu_online,
amd_uncore_cpu_down_prepare))
goto fail_start;
return 0;


fail_online:
for_each_online_cpu(cpu2) {
if (cpu2 == cpu)
break;
smp_call_function_single(cpu, cleanup_cpu_online, NULL, 1);
}
cpu_notifier_register_done();

/* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */
amd_uncore_nb = amd_uncore_l2 = NULL;

if (boot_cpu_has(X86_FEATURE_PERFCTR_L2))
perf_pmu_unregister(&amd_l2_pmu);
fail_start:
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
fail_prep:
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
fail_l2:
if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
perf_pmu_unregister(&amd_nb_pmu);
Expand Down
3 changes: 3 additions & 0 deletions include/linux/cpuhotplug.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum cpuhp_state {
CPUHP_PERF_PREPARE,
CPUHP_PERF_X86_PREPARE,
CPUHP_PERF_X86_UNCORE_PREP,
CPUHP_PERF_X86_AMD_UNCORE_PREP,
CPUHP_NOTIFY_PREPARE,
CPUHP_BRINGUP_CPU,
CPUHP_AP_IDLE_DEAD,
Expand All @@ -20,6 +21,7 @@ enum cpuhp_state {
CPUHP_AP_IRQ_BCM2836_STARTING,
CPUHP_AP_ARM_MVEBU_COHERENCY,
CPUHP_AP_PERF_X86_UNCORE_STARTING,
CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
CPUHP_AP_PERF_X86_STARTING,
CPUHP_AP_NOTIFY_STARTING,
CPUHP_AP_ONLINE,
Expand All @@ -30,6 +32,7 @@ enum cpuhp_state {
CPUHP_AP_PERF_ONLINE,
CPUHP_AP_PERF_X86_ONLINE,
CPUHP_AP_PERF_X86_UNCORE_ONLINE,
CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE,
CPUHP_AP_NOTIFY_ONLINE,
CPUHP_AP_ONLINE_DYN,
CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30,
Expand Down

0 comments on commit 96b2bd3

Please sign in to comment.