Merge tag 'char-misc-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[cascardo/linux.git] / arch / x86 / events / intel / cstate.c
index 4c7638b..4f5ac72 100644 (file)
@@ -48,7 +48,8 @@
  *                            Scope: Core
  *     MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
  *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW
+ *                                             SKL,KNL
  *                            Scope: Core
  *     MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
  *                            perf code: 0x03
  *                            Scope: Core
  *     MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
  *                            perf code: 0x00
- *                            Available model: SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SNB,IVB,HSW,BDW,SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
  *                            perf code: 0x01
- *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
  *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW
+ *                                             SKL,KNL
  *                            Scope: Package (physical package)
  *     MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
  *                            perf code: 0x03
@@ -118,6 +120,7 @@ struct cstate_model {
 
 /* Quirk flags */
 #define SLM_PKG_C6_USE_C7_MSR  (1UL << 0)
+#define KNL_CORE_C6_MSR                (1UL << 1)
 
 struct perf_cstate_msr {
        u64     msr;
@@ -366,7 +369,7 @@ static int cstate_pmu_event_add(struct perf_event *event, int mode)
  * Check if exiting cpu is the designated reader. If so migrate the
  * events when there is a valid target available
  */
-static void cstate_cpu_exit(int cpu)
+static int cstate_cpu_exit(unsigned int cpu)
 {
        unsigned int target;
 
@@ -391,9 +394,10 @@ static void cstate_cpu_exit(int cpu)
                        perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
                }
        }
+       return 0;
 }
 
-static void cstate_cpu_init(int cpu)
+static int cstate_cpu_init(unsigned int cpu)
 {
        unsigned int target;
 
@@ -415,31 +419,10 @@ static void cstate_cpu_init(int cpu)
                                 topology_core_cpumask(cpu));
        if (has_cstate_pkg && target >= nr_cpu_ids)
                cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
-}
 
-static int cstate_cpu_notifier(struct notifier_block *self,
-                              unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_STARTING:
-               cstate_cpu_init(cpu);
-               break;
-       case CPU_DOWN_PREPARE:
-               cstate_cpu_exit(cpu);
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
+       return 0;
 }
 
-static struct notifier_block cstate_cpu_nb = {
-       .notifier_call  = cstate_cpu_notifier,
-       .priority       = CPU_PRI_PERF + 1,
-};
-
 static struct pmu cstate_core_pmu = {
        .attr_groups    = core_attr_groups,
        .name           = "cstate_core",
@@ -508,6 +491,18 @@ static const struct cstate_model slm_cstates __initconst = {
        .quirks                 = SLM_PKG_C6_USE_C7_MSR,
 };
 
+
+static const struct cstate_model knl_cstates __initconst = {
+       .core_events            = BIT(PERF_CSTATE_CORE_C6_RES),
+
+       .pkg_events             = BIT(PERF_CSTATE_PKG_C2_RES) |
+                                 BIT(PERF_CSTATE_PKG_C3_RES) |
+                                 BIT(PERF_CSTATE_PKG_C6_RES),
+       .quirks                 = KNL_CORE_C6_MSR,
+};
+
+
+
 #define X86_CSTATES_MODEL(model, states)                               \
        { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) }
 
@@ -543,6 +538,8 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
 
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE,  snb_cstates),
        X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
+
+       X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
        { },
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
@@ -578,6 +575,11 @@ static int __init cstate_probe(const struct cstate_model *cm)
        if (cm->quirks & SLM_PKG_C6_USE_C7_MSR)
                pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
 
+       /* KNL has different MSR for CORE C6 */
+       if (cm->quirks & KNL_CORE_C6_MSR)
+               pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY;
+
+
        has_cstate_core = cstate_probe_msr(cm->core_events,
                                           PERF_CSTATE_CORE_EVENT_MAX,
                                           core_msr, core_events_attrs);
@@ -600,18 +602,20 @@ static inline void cstate_cleanup(void)
 
 static int __init cstate_init(void)
 {
-       int cpu, err;
+       int err;
 
-       cpu_notifier_register_begin();
-       for_each_online_cpu(cpu)
-               cstate_cpu_init(cpu);
+       cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING,
+                         "AP_PERF_X86_CSTATE_STARTING", cstate_cpu_init,
+                         NULL);
+       cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE,
+                         "AP_PERF_X86_CSTATE_ONLINE", NULL, cstate_cpu_exit);
 
        if (has_cstate_core) {
                err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
                if (err) {
                        has_cstate_core = false;
                        pr_info("Failed to register cstate core pmu\n");
-                       goto out;
+                       return err;
                }
        }
 
@@ -621,12 +625,10 @@ static int __init cstate_init(void)
                        has_cstate_pkg = false;
                        pr_info("Failed to register cstate pkg pmu\n");
                        cstate_cleanup();
-                       goto out;
+                       return err;
                }
        }
-       __register_cpu_notifier(&cstate_cpu_nb);
-out:
-       cpu_notifier_register_done();
+
        return err;
 }
 
@@ -652,9 +654,8 @@ module_init(cstate_pmu_init);
 
 static void __exit cstate_pmu_exit(void)
 {
-       cpu_notifier_register_begin();
-       __unregister_cpu_notifier(&cstate_cpu_nb);
+       cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE);
+       cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING);
        cstate_cleanup();
-       cpu_notifier_register_done();
 }
 module_exit(cstate_pmu_exit);