Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9744f7b7 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Ingo Molnar
Browse files

perf/x86/amd/ibs: Convert 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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAnna-Maria Gleixner <anna-maria@linutronix.de>
Reviewed-by: default avatarSebastian 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: Vince Weaver <vincent.weaver@maine.edu>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153333.921401190@linutronix.de


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 96b2bd38
Loading
Loading
Loading
Loading
+28 −36
Original line number Diff line number Diff line
@@ -721,13 +721,10 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
	return ret;
}

static __init int perf_event_ibs_init(void)
static __init void perf_event_ibs_init(void)
{
	struct attribute **attr = ibs_op_format_attrs;

	if (!ibs_caps)
		return -ENODEV;	/* ibs not supported by the cpu */

	perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");

	if (ibs_caps & IBS_CAPS_OPCNT) {
@@ -738,13 +735,11 @@ static __init int perf_event_ibs_init(void)

	register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
	pr_info("perf: AMD IBS detected (0x%08x)\n", ibs_caps);

	return 0;
}

#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */

static __init int perf_event_ibs_init(void) { return 0; }
static __init void perf_event_ibs_init(void) { }

#endif

@@ -921,7 +916,7 @@ static inline int get_ibs_lvt_offset(void)
	return val & IBSCTL_LVT_OFFSET_MASK;
}

static void setup_APIC_ibs(void *dummy)
static void setup_APIC_ibs(void)
{
	int offset;

@@ -936,7 +931,7 @@ static void setup_APIC_ibs(void *dummy)
		smp_processor_id());
}

static void clear_APIC_ibs(void *dummy)
static void clear_APIC_ibs(void)
{
	int offset;

@@ -945,18 +940,24 @@ static void clear_APIC_ibs(void *dummy)
		setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
}

static int x86_pmu_amd_ibs_starting_cpu(unsigned int cpu)
{
	setup_APIC_ibs();
	return 0;
}

#ifdef CONFIG_PM

static int perf_ibs_suspend(void)
{
	clear_APIC_ibs(NULL);
	clear_APIC_ibs();
	return 0;
}

static void perf_ibs_resume(void)
{
	ibs_eilvt_setup();
	setup_APIC_ibs(NULL);
	setup_APIC_ibs();
}

static struct syscore_ops perf_ibs_syscore_ops = {
@@ -975,27 +976,15 @@ static inline void perf_ibs_pm_init(void) { }

#endif

static int
perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
static int x86_pmu_amd_ibs_dying_cpu(unsigned int cpu)
{
	switch (action & ~CPU_TASKS_FROZEN) {
	case CPU_STARTING:
		setup_APIC_ibs(NULL);
		break;
	case CPU_DYING:
		clear_APIC_ibs(NULL);
		break;
	default:
		break;
	}

	return NOTIFY_OK;
	clear_APIC_ibs();
	return 0;
}

static __init int amd_ibs_init(void)
{
	u32 caps;
	int ret = -EINVAL;

	caps = __get_ibs_caps();
	if (!caps)
@@ -1004,22 +993,25 @@ static __init int amd_ibs_init(void)
	ibs_eilvt_setup();

	if (!ibs_eilvt_valid())
		goto out;
		return -EINVAL;

	perf_ibs_pm_init();
	cpu_notifier_register_begin();

	ibs_caps = caps;
	/* make ibs_caps visible to other cpus: */
	smp_mb();
	smp_call_function(setup_APIC_ibs, NULL, 1);
	__perf_cpu_notifier(perf_ibs_cpu_notifier);
	cpu_notifier_register_done();
	/*
	 * x86_pmu_amd_ibs_starting_cpu will be called from core on
	 * all online cpus.
	 */
	cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
			  "AP_PERF_X86_AMD_IBS_STARTING",
			  x86_pmu_amd_ibs_starting_cpu,
			  x86_pmu_amd_ibs_dying_cpu);

	ret = perf_event_ibs_init();
out:
	if (ret)
		pr_err("Failed to setup IBS, %d\n", ret);
	return ret;
	perf_event_ibs_init();

	return 0;
}

/* Since we need the pci subsystem to init ibs we can't do this earlier: */
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ enum cpuhp_state {
	CPUHP_AP_PERF_X86_UNCORE_STARTING,
	CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
	CPUHP_AP_PERF_X86_STARTING,
	CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
	CPUHP_AP_NOTIFY_STARTING,
	CPUHP_AP_ONLINE,
	CPUHP_TEARDOWN_CPU,