|
@@ -231,10 +231,8 @@ struct global_params {
|
|
* @prev_cummulative_iowait: IO Wait time difference from last and
|
|
* @prev_cummulative_iowait: IO Wait time difference from last and
|
|
* current sample
|
|
* current sample
|
|
* @sample: Storage for storing last Sample data
|
|
* @sample: Storage for storing last Sample data
|
|
- * @min_perf: Minimum capacity limit as a fraction of the maximum
|
|
|
|
- * turbo P-state capacity.
|
|
|
|
- * @max_perf: Maximum capacity limit as a fraction of the maximum
|
|
|
|
- * turbo P-state capacity.
|
|
|
|
|
|
+ * @min_perf_ratio: Minimum capacity in terms of PERF or HWP ratios
|
|
|
|
+ * @max_perf_ratio: Maximum capacity in terms of PERF or HWP ratios
|
|
* @acpi_perf_data: Stores ACPI perf information read from _PSS
|
|
* @acpi_perf_data: Stores ACPI perf information read from _PSS
|
|
* @valid_pss_table: Set to true for valid ACPI _PSS entries found
|
|
* @valid_pss_table: Set to true for valid ACPI _PSS entries found
|
|
* @epp_powersave: Last saved HWP energy performance preference
|
|
* @epp_powersave: Last saved HWP energy performance preference
|
|
@@ -266,8 +264,8 @@ struct cpudata {
|
|
u64 prev_tsc;
|
|
u64 prev_tsc;
|
|
u64 prev_cummulative_iowait;
|
|
u64 prev_cummulative_iowait;
|
|
struct sample sample;
|
|
struct sample sample;
|
|
- int32_t min_perf;
|
|
|
|
- int32_t max_perf;
|
|
|
|
|
|
+ int32_t min_perf_ratio;
|
|
|
|
+ int32_t max_perf_ratio;
|
|
#ifdef CONFIG_ACPI
|
|
#ifdef CONFIG_ACPI
|
|
struct acpi_processor_performance acpi_perf_data;
|
|
struct acpi_processor_performance acpi_perf_data;
|
|
bool valid_pss_table;
|
|
bool valid_pss_table;
|
|
@@ -790,25 +788,32 @@ static struct freq_attr *hwp_cpufreq_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static void intel_pstate_hwp_set(unsigned int cpu)
|
|
|
|
|
|
+static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max,
|
|
|
|
+ int *current_max)
|
|
{
|
|
{
|
|
- struct cpudata *cpu_data = all_cpu_data[cpu];
|
|
|
|
- int min, hw_min, max, hw_max;
|
|
|
|
- u64 value, cap;
|
|
|
|
- s16 epp;
|
|
|
|
|
|
+ u64 cap;
|
|
|
|
|
|
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
|
|
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
|
|
- hw_min = HWP_LOWEST_PERF(cap);
|
|
|
|
if (global.no_turbo)
|
|
if (global.no_turbo)
|
|
- hw_max = HWP_GUARANTEED_PERF(cap);
|
|
|
|
|
|
+ *current_max = HWP_GUARANTEED_PERF(cap);
|
|
else
|
|
else
|
|
- hw_max = HWP_HIGHEST_PERF(cap);
|
|
|
|
|
|
+ *current_max = HWP_HIGHEST_PERF(cap);
|
|
|
|
+
|
|
|
|
+ *phy_max = HWP_HIGHEST_PERF(cap);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void intel_pstate_hwp_set(unsigned int cpu)
|
|
|
|
+{
|
|
|
|
+ struct cpudata *cpu_data = all_cpu_data[cpu];
|
|
|
|
+ int max, min;
|
|
|
|
+ u64 value;
|
|
|
|
+ s16 epp;
|
|
|
|
+
|
|
|
|
+ max = cpu_data->max_perf_ratio;
|
|
|
|
+ min = cpu_data->min_perf_ratio;
|
|
|
|
|
|
- max = fp_ext_toint(hw_max * cpu_data->max_perf);
|
|
|
|
if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE)
|
|
if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE)
|
|
min = max;
|
|
min = max;
|
|
- else
|
|
|
|
- min = fp_ext_toint(hw_max * cpu_data->min_perf);
|
|
|
|
|
|
|
|
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
|
|
rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
|
|
|
|
|
|
@@ -1524,8 +1529,7 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu)
|
|
|
|
|
|
update_turbo_state();
|
|
update_turbo_state();
|
|
pstate = intel_pstate_get_base_pstate(cpu);
|
|
pstate = intel_pstate_get_base_pstate(cpu);
|
|
- pstate = max(cpu->pstate.min_pstate,
|
|
|
|
- fp_ext_toint(pstate * cpu->max_perf));
|
|
|
|
|
|
+ pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio);
|
|
intel_pstate_set_pstate(cpu, pstate);
|
|
intel_pstate_set_pstate(cpu, pstate);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1612,9 +1616,6 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
|
|
int32_t busy_frac, boost;
|
|
int32_t busy_frac, boost;
|
|
int target, avg_pstate;
|
|
int target, avg_pstate;
|
|
|
|
|
|
- if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE)
|
|
|
|
- return cpu->pstate.turbo_pstate;
|
|
|
|
-
|
|
|
|
busy_frac = div_fp(sample->mperf, sample->tsc);
|
|
busy_frac = div_fp(sample->mperf, sample->tsc);
|
|
|
|
|
|
boost = cpu->iowait_boost;
|
|
boost = cpu->iowait_boost;
|
|
@@ -1651,9 +1652,6 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
|
|
int32_t perf_scaled, max_pstate, current_pstate, sample_ratio;
|
|
int32_t perf_scaled, max_pstate, current_pstate, sample_ratio;
|
|
u64 duration_ns;
|
|
u64 duration_ns;
|
|
|
|
|
|
- if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE)
|
|
|
|
- return cpu->pstate.turbo_pstate;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* perf_scaled is the ratio of the average P-state during the last
|
|
* perf_scaled is the ratio of the average P-state during the last
|
|
* sampling period to the P-state requested last time (in percent).
|
|
* sampling period to the P-state requested last time (in percent).
|
|
@@ -1691,9 +1689,8 @@ static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate)
|
|
int max_pstate = intel_pstate_get_base_pstate(cpu);
|
|
int max_pstate = intel_pstate_get_base_pstate(cpu);
|
|
int min_pstate;
|
|
int min_pstate;
|
|
|
|
|
|
- min_pstate = max(cpu->pstate.min_pstate,
|
|
|
|
- fp_ext_toint(max_pstate * cpu->min_perf));
|
|
|
|
- max_pstate = max(min_pstate, fp_ext_toint(max_pstate * cpu->max_perf));
|
|
|
|
|
|
+ min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio);
|
|
|
|
+ max_pstate = max(min_pstate, cpu->max_perf_ratio);
|
|
return clamp_t(int, pstate, min_pstate, max_pstate);
|
|
return clamp_t(int, pstate, min_pstate, max_pstate);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1729,16 +1726,6 @@ static void intel_pstate_adjust_pstate(struct cpudata *cpu, int target_pstate)
|
|
fp_toint(cpu->iowait_boost * 100));
|
|
fp_toint(cpu->iowait_boost * 100));
|
|
}
|
|
}
|
|
|
|
|
|
-static void intel_pstate_update_util_hwp(struct update_util_data *data,
|
|
|
|
- u64 time, unsigned int flags)
|
|
|
|
-{
|
|
|
|
- struct cpudata *cpu = container_of(data, struct cpudata, update_util);
|
|
|
|
- u64 delta_ns = time - cpu->sample.time;
|
|
|
|
-
|
|
|
|
- if ((s64)delta_ns >= INTEL_PSTATE_HWP_SAMPLING_INTERVAL)
|
|
|
|
- intel_pstate_sample(cpu, time);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void intel_pstate_update_util_pid(struct update_util_data *data,
|
|
static void intel_pstate_update_util_pid(struct update_util_data *data,
|
|
u64 time, unsigned int flags)
|
|
u64 time, unsigned int flags)
|
|
{
|
|
{
|
|
@@ -1930,6 +1917,9 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
|
|
{
|
|
{
|
|
struct cpudata *cpu = all_cpu_data[cpu_num];
|
|
struct cpudata *cpu = all_cpu_data[cpu_num];
|
|
|
|
|
|
|
|
+ if (hwp_active)
|
|
|
|
+ return;
|
|
|
|
+
|
|
if (cpu->update_util_set)
|
|
if (cpu->update_util_set)
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -1963,52 +1953,61 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
|
|
{
|
|
{
|
|
int max_freq = intel_pstate_get_max_freq(cpu);
|
|
int max_freq = intel_pstate_get_max_freq(cpu);
|
|
int32_t max_policy_perf, min_policy_perf;
|
|
int32_t max_policy_perf, min_policy_perf;
|
|
|
|
+ int max_state, turbo_max;
|
|
|
|
|
|
- max_policy_perf = div_ext_fp(policy->max, max_freq);
|
|
|
|
- max_policy_perf = clamp_t(int32_t, max_policy_perf, 0, int_ext_tofp(1));
|
|
|
|
|
|
+ /*
|
|
|
|
+ * HWP needs some special consideration, because on BDX the
|
|
|
|
+ * HWP_REQUEST uses abstract value to represent performance
|
|
|
|
+ * rather than pure ratios.
|
|
|
|
+ */
|
|
|
|
+ if (hwp_active) {
|
|
|
|
+ intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state);
|
|
|
|
+ } else {
|
|
|
|
+ max_state = intel_pstate_get_base_pstate(cpu);
|
|
|
|
+ turbo_max = cpu->pstate.turbo_pstate;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ max_policy_perf = max_state * policy->max / max_freq;
|
|
if (policy->max == policy->min) {
|
|
if (policy->max == policy->min) {
|
|
min_policy_perf = max_policy_perf;
|
|
min_policy_perf = max_policy_perf;
|
|
} else {
|
|
} else {
|
|
- min_policy_perf = div_ext_fp(policy->min, max_freq);
|
|
|
|
|
|
+ min_policy_perf = max_state * policy->min / max_freq;
|
|
min_policy_perf = clamp_t(int32_t, min_policy_perf,
|
|
min_policy_perf = clamp_t(int32_t, min_policy_perf,
|
|
0, max_policy_perf);
|
|
0, max_policy_perf);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ pr_debug("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n",
|
|
|
|
+ policy->cpu, max_state,
|
|
|
|
+ min_policy_perf, max_policy_perf);
|
|
|
|
+
|
|
/* Normalize user input to [min_perf, max_perf] */
|
|
/* Normalize user input to [min_perf, max_perf] */
|
|
if (per_cpu_limits) {
|
|
if (per_cpu_limits) {
|
|
- cpu->min_perf = min_policy_perf;
|
|
|
|
- cpu->max_perf = max_policy_perf;
|
|
|
|
|
|
+ cpu->min_perf_ratio = min_policy_perf;
|
|
|
|
+ cpu->max_perf_ratio = max_policy_perf;
|
|
} else {
|
|
} else {
|
|
int32_t global_min, global_max;
|
|
int32_t global_min, global_max;
|
|
|
|
|
|
/* Global limits are in percent of the maximum turbo P-state. */
|
|
/* Global limits are in percent of the maximum turbo P-state. */
|
|
- global_max = percent_ext_fp(global.max_perf_pct);
|
|
|
|
- global_min = percent_ext_fp(global.min_perf_pct);
|
|
|
|
- if (max_freq != cpu->pstate.turbo_freq) {
|
|
|
|
- int32_t turbo_factor;
|
|
|
|
-
|
|
|
|
- turbo_factor = div_ext_fp(cpu->pstate.turbo_pstate,
|
|
|
|
- cpu->pstate.max_pstate);
|
|
|
|
- global_min = mul_ext_fp(global_min, turbo_factor);
|
|
|
|
- global_max = mul_ext_fp(global_max, turbo_factor);
|
|
|
|
- }
|
|
|
|
|
|
+ global_max = DIV_ROUND_UP(turbo_max * global.max_perf_pct, 100);
|
|
|
|
+ global_min = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100);
|
|
global_min = clamp_t(int32_t, global_min, 0, global_max);
|
|
global_min = clamp_t(int32_t, global_min, 0, global_max);
|
|
|
|
|
|
- cpu->min_perf = max(min_policy_perf, global_min);
|
|
|
|
- cpu->min_perf = min(cpu->min_perf, max_policy_perf);
|
|
|
|
- cpu->max_perf = min(max_policy_perf, global_max);
|
|
|
|
- cpu->max_perf = max(min_policy_perf, cpu->max_perf);
|
|
|
|
|
|
+ pr_debug("cpu:%d global_min:%d global_max:%d\n", policy->cpu,
|
|
|
|
+ global_min, global_max);
|
|
|
|
|
|
- /* Make sure min_perf <= max_perf */
|
|
|
|
- cpu->min_perf = min(cpu->min_perf, cpu->max_perf);
|
|
|
|
- }
|
|
|
|
|
|
+ cpu->min_perf_ratio = max(min_policy_perf, global_min);
|
|
|
|
+ cpu->min_perf_ratio = min(cpu->min_perf_ratio, max_policy_perf);
|
|
|
|
+ cpu->max_perf_ratio = min(max_policy_perf, global_max);
|
|
|
|
+ cpu->max_perf_ratio = max(min_policy_perf, cpu->max_perf_ratio);
|
|
|
|
|
|
- cpu->max_perf = round_up(cpu->max_perf, EXT_FRAC_BITS);
|
|
|
|
- cpu->min_perf = round_up(cpu->min_perf, EXT_FRAC_BITS);
|
|
|
|
|
|
+ /* Make sure min_perf <= max_perf */
|
|
|
|
+ cpu->min_perf_ratio = min(cpu->min_perf_ratio,
|
|
|
|
+ cpu->max_perf_ratio);
|
|
|
|
|
|
- pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
|
|
|
|
- fp_ext_toint(cpu->max_perf * 100),
|
|
|
|
- fp_ext_toint(cpu->min_perf * 100));
|
|
|
|
|
|
+ }
|
|
|
|
+ pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", policy->cpu,
|
|
|
|
+ cpu->max_perf_ratio,
|
|
|
|
+ cpu->min_perf_ratio);
|
|
}
|
|
}
|
|
|
|
|
|
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
|
static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
|
@@ -2035,10 +2034,10 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
|
*/
|
|
*/
|
|
intel_pstate_clear_update_util_hook(policy->cpu);
|
|
intel_pstate_clear_update_util_hook(policy->cpu);
|
|
intel_pstate_max_within_limits(cpu);
|
|
intel_pstate_max_within_limits(cpu);
|
|
|
|
+ } else {
|
|
|
|
+ intel_pstate_set_update_util_hook(policy->cpu);
|
|
}
|
|
}
|
|
|
|
|
|
- intel_pstate_set_update_util_hook(policy->cpu);
|
|
|
|
-
|
|
|
|
if (hwp_active)
|
|
if (hwp_active)
|
|
intel_pstate_hwp_set(policy->cpu);
|
|
intel_pstate_hwp_set(policy->cpu);
|
|
|
|
|
|
@@ -2111,8 +2110,8 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
|
cpu = all_cpu_data[policy->cpu];
|
|
cpu = all_cpu_data[policy->cpu];
|
|
|
|
|
|
- cpu->max_perf = int_ext_tofp(1);
|
|
|
|
- cpu->min_perf = 0;
|
|
|
|
|
|
+ cpu->max_perf_ratio = 0xFF;
|
|
|
|
+ cpu->min_perf_ratio = 0;
|
|
|
|
|
|
policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
|
|
policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
|
|
policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
|
|
policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
|
|
@@ -2554,7 +2553,6 @@ static int __init intel_pstate_init(void)
|
|
} else {
|
|
} else {
|
|
hwp_active++;
|
|
hwp_active++;
|
|
intel_pstate.attr = hwp_cpufreq_attrs;
|
|
intel_pstate.attr = hwp_cpufreq_attrs;
|
|
- pstate_funcs.update_util = intel_pstate_update_util_hwp;
|
|
|
|
goto hwp_cpu_matched;
|
|
goto hwp_cpu_matched;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|