OSDN Git Service

cpufreq: amd-pstate: Add boost mode support for AMD P-State
authorHuang Rui <ray.huang@amd.com>
Fri, 24 Dec 2021 01:05:04 +0000 (09:05 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 30 Dec 2021 17:51:39 +0000 (18:51 +0100)
If the sbios supports the boost mode of AMD P-State, let's switch to
boost enabled by default.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/amd-pstate.c

index 63efd5d..9e23efc 100644 (file)
@@ -87,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
 struct amd_cpudata {
        int     cpu;
 
+       struct  freq_qos_request req[2];
        u64     cppc_req_cached;
 
        u32     highest_perf;
@@ -98,6 +99,8 @@ struct amd_cpudata {
        u32     min_freq;
        u32     nominal_freq;
        u32     lowest_nonlinear_freq;
+
+       bool    boost_supported;
 };
 
 static inline int pstate_enable(bool enable)
@@ -374,6 +377,45 @@ static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
        return lowest_nonlinear_freq * 1000;
 }
 
+static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
+{
+       struct amd_cpudata *cpudata = policy->driver_data;
+       int ret;
+
+       if (!cpudata->boost_supported) {
+               pr_err("Boost mode is not supported by this processor or SBIOS\n");
+               return -EINVAL;
+       }
+
+       if (state)
+               policy->cpuinfo.max_freq = cpudata->max_freq;
+       else
+               policy->cpuinfo.max_freq = cpudata->nominal_freq;
+
+       policy->max = policy->cpuinfo.max_freq;
+
+       ret = freq_qos_update_request(&cpudata->req[1],
+                                     policy->cpuinfo.max_freq);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
+{
+       u32 highest_perf, nominal_perf;
+
+       highest_perf = READ_ONCE(cpudata->highest_perf);
+       nominal_perf = READ_ONCE(cpudata->nominal_perf);
+
+       if (highest_perf <= nominal_perf)
+               return;
+
+       cpudata->boost_supported = true;
+       amd_pstate_driver.boost_enabled = true;
+}
+
 static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
 {
        int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
@@ -392,7 +434,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
 
        ret = amd_pstate_init_perf(cpudata);
        if (ret)
-               goto free_cpudata;
+               goto free_cpudata1;
 
        min_freq = amd_get_min_freq(cpudata);
        max_freq = amd_get_max_freq(cpudata);
@@ -403,7 +445,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
                dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
                        min_freq, max_freq);
                ret = -EINVAL;
-               goto free_cpudata;
+               goto free_cpudata1;
        }
 
        policy->cpuinfo.transition_latency = AMD_PSTATE_TRANSITION_LATENCY;
@@ -421,6 +463,20 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
        if (boot_cpu_has(X86_FEATURE_CPPC))
                policy->fast_switch_possible = true;
 
+       ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
+                                  FREQ_QOS_MIN, policy->cpuinfo.min_freq);
+       if (ret < 0) {
+               dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
+               goto free_cpudata1;
+       }
+
+       ret = freq_qos_add_request(&policy->constraints, &cpudata->req[1],
+                                  FREQ_QOS_MAX, policy->cpuinfo.max_freq);
+       if (ret < 0) {
+               dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret);
+               goto free_cpudata2;
+       }
+
        /* Initial processor data capability frequencies */
        cpudata->max_freq = max_freq;
        cpudata->min_freq = min_freq;
@@ -429,9 +485,13 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
 
        policy->driver_data = cpudata;
 
+       amd_pstate_boost_init(cpudata);
+
        return 0;
 
-free_cpudata:
+free_cpudata2:
+       freq_qos_remove_request(&cpudata->req[0]);
+free_cpudata1:
        kfree(cpudata);
        return ret;
 }
@@ -442,6 +502,8 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
 
        cpudata = policy->driver_data;
 
+       freq_qos_remove_request(&cpudata->req[1]);
+       freq_qos_remove_request(&cpudata->req[0]);
        kfree(cpudata);
 
        return 0;
@@ -453,6 +515,7 @@ static struct cpufreq_driver amd_pstate_driver = {
        .target         = amd_pstate_target,
        .init           = amd_pstate_cpu_init,
        .exit           = amd_pstate_cpu_exit,
+       .set_boost      = amd_pstate_set_boost,
        .name           = "amd-pstate",
 };