]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/cpufreq/intel_pstate.c
Merge branches 'pm-sleep' and 'pm-cpufreq'
[mirror_ubuntu-bionic-kernel.git] / drivers / cpufreq / intel_pstate.c
index ed215c5592f6245309ee38cc96487fdbf25fbd56..a54d65aa776d064f025036cf9aa35790d83d82e8 100644 (file)
@@ -46,6 +46,7 @@
 
 #ifdef CONFIG_ACPI
 #include <acpi/processor.h>
+#include <acpi/cppc_acpi.h>
 #endif
 
 #define FRAC_BITS 8
@@ -406,14 +407,67 @@ static bool intel_pstate_get_ppc_enable_status(void)
        return acpi_ppc;
 }
 
+#ifdef CONFIG_ACPI_CPPC_LIB
+
+/* The work item is needed to avoid CPU hotplug locking issues */
+static void intel_pstste_sched_itmt_work_fn(struct work_struct *work)
+{
+       sched_set_itmt_support();
+}
+
+static DECLARE_WORK(sched_itmt_work, intel_pstste_sched_itmt_work_fn);
+
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+       struct cppc_perf_caps cppc_perf;
+       static u32 max_highest_perf = 0, min_highest_perf = U32_MAX;
+       int ret;
+
+       ret = cppc_get_perf_caps(cpu, &cppc_perf);
+       if (ret)
+               return;
+
+       /*
+        * The priorities can be set regardless of whether or not
+        * sched_set_itmt_support(true) has been called and it is valid to
+        * update them at any time after it has been called.
+        */
+       sched_set_itmt_core_prio(cppc_perf.highest_perf, cpu);
+
+       if (max_highest_perf <= min_highest_perf) {
+               if (cppc_perf.highest_perf > max_highest_perf)
+                       max_highest_perf = cppc_perf.highest_perf;
+
+               if (cppc_perf.highest_perf < min_highest_perf)
+                       min_highest_perf = cppc_perf.highest_perf;
+
+               if (max_highest_perf > min_highest_perf) {
+                       /*
+                        * This code can be run during CPU online under the
+                        * CPU hotplug locks, so sched_set_itmt_support()
+                        * cannot be called from here.  Queue up a work item
+                        * to invoke it.
+                        */
+                       schedule_work(&sched_itmt_work);
+               }
+       }
+}
+#else
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+}
+#endif
+
 static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
 {
        struct cpudata *cpu;
        int ret;
        int i;
 
-       if (hwp_active)
+       if (hwp_active) {
+               intel_pstate_set_itmt_prio(policy->cpu);
                return;
+       }
 
        if (!intel_pstate_get_ppc_enable_status())
                return;