aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_ibs.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index e09f0bfb7b8f..4b8e4d3cd6ea 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 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/ptrace.h> 12#include <linux/ptrace.h>
13#include <linux/syscore_ops.h>
13 14
14#include <asm/apic.h> 15#include <asm/apic.h>
15 16
@@ -816,6 +817,18 @@ out:
816 return ret; 817 return ret;
817} 818}
818 819
820static void ibs_eilvt_setup(void)
821{
822 /*
823 * Force LVT offset assignment for family 10h: The offsets are
824 * not assigned by the BIOS for this family, so the OS is
825 * responsible for doing it. If the OS assignment fails, fall
826 * back to BIOS settings and try to setup this.
827 */
828 if (boot_cpu_data.x86 == 0x10)
829 force_ibs_eilvt_setup();
830}
831
819static inline int get_ibs_lvt_offset(void) 832static inline int get_ibs_lvt_offset(void)
820{ 833{
821 u64 val; 834 u64 val;
@@ -851,6 +864,36 @@ static void clear_APIC_ibs(void *dummy)
851 setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); 864 setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
852} 865}
853 866
867#ifdef CONFIG_PM
868
869static int perf_ibs_suspend(void)
870{
871 clear_APIC_ibs(NULL);
872 return 0;
873}
874
875static void perf_ibs_resume(void)
876{
877 ibs_eilvt_setup();
878 setup_APIC_ibs(NULL);
879}
880
881static struct syscore_ops perf_ibs_syscore_ops = {
882 .resume = perf_ibs_resume,
883 .suspend = perf_ibs_suspend,
884};
885
886static void perf_ibs_pm_init(void)
887{
888 register_syscore_ops(&perf_ibs_syscore_ops);
889}
890
891#else
892
893static inline void perf_ibs_pm_init(void) { }
894
895#endif
896
854static int 897static int
855perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) 898perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
856{ 899{
@@ -877,18 +920,12 @@ static __init int amd_ibs_init(void)
877 if (!caps) 920 if (!caps)
878 return -ENODEV; /* ibs not supported by the cpu */ 921 return -ENODEV; /* ibs not supported by the cpu */
879 922
880 /* 923 ibs_eilvt_setup();
881 * Force LVT offset assignment for family 10h: The offsets are
882 * not assigned by the BIOS for this family, so the OS is
883 * responsible for doing it. If the OS assignment fails, fall
884 * back to BIOS settings and try to setup this.
885 */
886 if (boot_cpu_data.x86 == 0x10)
887 force_ibs_eilvt_setup();
888 924
889 if (!ibs_eilvt_valid()) 925 if (!ibs_eilvt_valid())
890 goto out; 926 goto out;
891 927
928 perf_ibs_pm_init();
892 get_online_cpus(); 929 get_online_cpus();
893 ibs_caps = caps; 930 ibs_caps = caps;
894 /* make ibs_caps visible to other cpus: */ 931 /* make ibs_caps visible to other cpus: */