From a5005f20accf44bebbd6ab9dd7ef874308b73e92 Mon Sep 17 00:00:00 2001
From: Anthony Wong <anthony.wong@canonical.com>
Date: Tue, 5 Nov 2013 08:13:08 +0000
Subject: [PATCH] perf/amd/ibs: Re-assign IBS LVT offset after resume from
 suspend

After suspend/resume the register contents get lost and is not
reinitialized anymore. Thus, after resume the apic setup code
detects the offset conflict caused be the reset registers and
throws the [hardware error] message.

Signed-off-by: Anthony Wong <anthony.wong@canonical.com>
---
 arch/x86/kernel/cpu/perf_event_amd_ibs.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 6336bcb..566e0e0 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/apic.h>
 
@@ -637,6 +638,17 @@ static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
 	return ret;
 }
 
+static int force_ibs_eilvt_setup(void);
+
+static void amd_ibs_syscore_resume(void)
+{
+	force_ibs_eilvt_setup();
+}
+
+static struct syscore_ops amd_ibs_syscore_ops = {
+	.resume = amd_ibs_syscore_resume,
+};
+
 static __init int perf_event_ibs_init(void)
 {
 	struct attribute **attr = ibs_op_format_attrs;
@@ -653,6 +665,8 @@ static __init int perf_event_ibs_init(void)
 	perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
 
 	register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
+	register_syscore_ops(&amd_ibs_syscore_ops);
+
 	printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
 
 	return 0;
-- 
1.8.1.2

