Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: move policy kobj to update_policy_cpu() cpufreq: propagate error returned by kobject_move() cpufreq: don't restore policy->cpus on failure to move kobj powernow-k6: support 350MHz CPU cpufreq: ondemand: Eliminate the deadband effect cpufreq: Introduce new relation for freq selection cpufreq: imx6: remove pu regulator dependency for SOCs with no PU regulator cpufreq: intel_pstate: Remove core_pct rounding cpufreq: intel_pstate: Simplify P state adjustment logic. cpufreq: intel_pstate: Keep values in aperf/mperf in full precision cpufreq: intel_pstate: Disable interrupts during MSRs reading cpufreq: intel_pstate: Align multiple lines to open parenthesis cpufreq: intel_pstate: Remove unnecessary intermediate variable sample_time cpufreq: intel_pstate: Cleanup parentheses cpufreq: intel_pstate: Fit code in a single line where possible cpufreq: intel_pstate: Add missing blank lines after declarations cpufreq: intel_pstate: Remove unnecessary type casting in div_s64() call cpufreq: intel_pstate: Make intel_pstate_kobject and debugfs_parent locals
This commit is contained in:
commit
b14c348e8d
|
@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
||||||
kfree(policy);
|
kfree(policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
|
static int update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu,
|
||||||
|
struct device *cpu_dev)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (WARN_ON(cpu == policy->cpu))
|
if (WARN_ON(cpu == policy->cpu))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
|
/* Move kobject to the new policy->cpu */
|
||||||
|
ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
down_write(&policy->rwsem);
|
down_write(&policy->rwsem);
|
||||||
|
|
||||||
|
@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
|
||||||
|
|
||||||
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
||||||
CPUFREQ_UPDATE_POLICY_CPU, policy);
|
CPUFREQ_UPDATE_POLICY_CPU, policy);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
|
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
|
||||||
|
@ -1153,12 +1165,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
|
||||||
* the creation of a brand new one. So we need to perform this update
|
* the creation of a brand new one. So we need to perform this update
|
||||||
* by invoking update_policy_cpu().
|
* by invoking update_policy_cpu().
|
||||||
*/
|
*/
|
||||||
if (recover_policy && cpu != policy->cpu) {
|
if (recover_policy && cpu != policy->cpu)
|
||||||
update_policy_cpu(policy, cpu);
|
WARN_ON(update_policy_cpu(policy, cpu, dev));
|
||||||
WARN_ON(kobject_move(&policy->kobj, &dev->kobj));
|
else
|
||||||
} else {
|
|
||||||
policy->cpu = cpu;
|
policy->cpu = cpu;
|
||||||
}
|
|
||||||
|
|
||||||
cpumask_copy(policy->cpus, cpumask_of(cpu));
|
cpumask_copy(policy->cpus, cpumask_of(cpu));
|
||||||
|
|
||||||
|
@ -1309,38 +1319,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
|
||||||
return __cpufreq_add_dev(dev, sif);
|
return __cpufreq_add_dev(dev, sif);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
|
|
||||||
unsigned int old_cpu)
|
|
||||||
{
|
|
||||||
struct device *cpu_dev;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* first sibling now owns the new sysfs dir */
|
|
||||||
cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
|
|
||||||
|
|
||||||
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
|
|
||||||
ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
|
|
||||||
|
|
||||||
down_write(&policy->rwsem);
|
|
||||||
cpumask_set_cpu(old_cpu, policy->cpus);
|
|
||||||
up_write(&policy->rwsem);
|
|
||||||
|
|
||||||
ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
|
|
||||||
"cpufreq");
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cpu_dev->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __cpufreq_remove_dev_prepare(struct device *dev,
|
static int __cpufreq_remove_dev_prepare(struct device *dev,
|
||||||
struct subsys_interface *sif)
|
struct subsys_interface *sif)
|
||||||
{
|
{
|
||||||
unsigned int cpu = dev->id, cpus;
|
unsigned int cpu = dev->id, cpus;
|
||||||
int new_cpu, ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct cpufreq_policy *policy;
|
struct cpufreq_policy *policy;
|
||||||
|
|
||||||
|
@ -1380,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
|
||||||
if (cpu != policy->cpu) {
|
if (cpu != policy->cpu) {
|
||||||
sysfs_remove_link(&dev->kobj, "cpufreq");
|
sysfs_remove_link(&dev->kobj, "cpufreq");
|
||||||
} else if (cpus > 1) {
|
} else if (cpus > 1) {
|
||||||
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
|
/* Nominate new CPU */
|
||||||
if (new_cpu >= 0) {
|
int new_cpu = cpumask_any_but(policy->cpus, cpu);
|
||||||
update_policy_cpu(policy, new_cpu);
|
struct device *cpu_dev = get_cpu_device(new_cpu);
|
||||||
|
|
||||||
if (!cpufreq_suspended)
|
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
|
||||||
pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
|
ret = update_policy_cpu(policy, new_cpu, cpu_dev);
|
||||||
__func__, new_cpu, cpu);
|
if (ret) {
|
||||||
|
if (sysfs_create_link(&cpu_dev->kobj, &policy->kobj,
|
||||||
|
"cpufreq"))
|
||||||
|
pr_err("%s: Failed to restore kobj link to cpu:%d\n",
|
||||||
|
__func__, cpu_dev->id);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cpufreq_suspended)
|
||||||
|
pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
|
||||||
|
__func__, new_cpu, cpu);
|
||||||
} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
|
} else if (cpufreq_driver->stop_cpu && cpufreq_driver->setpolicy) {
|
||||||
cpufreq_driver->stop_cpu(policy);
|
cpufreq_driver->stop_cpu(policy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,21 +170,24 @@ static void od_check_cpu(int cpu, unsigned int load)
|
||||||
dbs_freq_increase(policy, policy->max);
|
dbs_freq_increase(policy, policy->max);
|
||||||
} else {
|
} else {
|
||||||
/* Calculate the next frequency proportional to load */
|
/* Calculate the next frequency proportional to load */
|
||||||
unsigned int freq_next;
|
unsigned int freq_next, min_f, max_f;
|
||||||
freq_next = load * policy->cpuinfo.max_freq / 100;
|
|
||||||
|
min_f = policy->cpuinfo.min_freq;
|
||||||
|
max_f = policy->cpuinfo.max_freq;
|
||||||
|
freq_next = min_f + load * (max_f - min_f) / 100;
|
||||||
|
|
||||||
/* No longer fully busy, reset rate_mult */
|
/* No longer fully busy, reset rate_mult */
|
||||||
dbs_info->rate_mult = 1;
|
dbs_info->rate_mult = 1;
|
||||||
|
|
||||||
if (!od_tuners->powersave_bias) {
|
if (!od_tuners->powersave_bias) {
|
||||||
__cpufreq_driver_target(policy, freq_next,
|
__cpufreq_driver_target(policy, freq_next,
|
||||||
CPUFREQ_RELATION_L);
|
CPUFREQ_RELATION_C);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
freq_next = od_ops.powersave_bias_target(policy, freq_next,
|
freq_next = od_ops.powersave_bias_target(policy, freq_next,
|
||||||
CPUFREQ_RELATION_L);
|
CPUFREQ_RELATION_L);
|
||||||
__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
|
__cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||||
.frequency = 0,
|
.frequency = 0,
|
||||||
};
|
};
|
||||||
struct cpufreq_frequency_table *pos;
|
struct cpufreq_frequency_table *pos;
|
||||||
unsigned int freq, i = 0;
|
unsigned int freq, diff, i = 0;
|
||||||
|
|
||||||
pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
|
pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
|
||||||
target_freq, relation, policy->cpu);
|
target_freq, relation, policy->cpu);
|
||||||
|
@ -127,6 +127,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||||
suboptimal.frequency = ~0;
|
suboptimal.frequency = ~0;
|
||||||
break;
|
break;
|
||||||
case CPUFREQ_RELATION_L:
|
case CPUFREQ_RELATION_L:
|
||||||
|
case CPUFREQ_RELATION_C:
|
||||||
optimal.frequency = ~0;
|
optimal.frequency = ~0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,6 +169,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CPUFREQ_RELATION_C:
|
||||||
|
diff = abs(freq - target_freq);
|
||||||
|
if (diff < optimal.frequency ||
|
||||||
|
(diff == optimal.frequency &&
|
||||||
|
freq > table[optimal.driver_data].frequency)) {
|
||||||
|
optimal.frequency = diff;
|
||||||
|
optimal.driver_data = i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optimal.driver_data > i) {
|
if (optimal.driver_data > i) {
|
||||||
|
|
|
@ -66,10 +66,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
|
|
||||||
/* scaling up? scale voltage before frequency */
|
/* scaling up? scale voltage before frequency */
|
||||||
if (new_freq > old_freq) {
|
if (new_freq > old_freq) {
|
||||||
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
|
if (!IS_ERR(pu_reg)) {
|
||||||
if (ret) {
|
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
|
||||||
dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
|
if (ret) {
|
||||||
return ret;
|
dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
|
ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -121,10 +123,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||||
dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
|
dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
|
if (!IS_ERR(pu_reg)) {
|
||||||
if (ret) {
|
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
|
||||||
dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
|
if (ret) {
|
||||||
ret = 0;
|
dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +186,9 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_reg = regulator_get(cpu_dev, "arm");
|
arm_reg = regulator_get(cpu_dev, "arm");
|
||||||
pu_reg = regulator_get(cpu_dev, "pu");
|
pu_reg = regulator_get_optional(cpu_dev, "pu");
|
||||||
soc_reg = regulator_get(cpu_dev, "soc");
|
soc_reg = regulator_get(cpu_dev, "soc");
|
||||||
if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) {
|
if (IS_ERR(arm_reg) || IS_ERR(soc_reg)) {
|
||||||
dev_err(cpu_dev, "failed to get regulators\n");
|
dev_err(cpu_dev, "failed to get regulators\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto put_reg;
|
goto put_reg;
|
||||||
|
@ -268,9 +272,11 @@ soc_opp_out:
|
||||||
ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
|
ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
transition_latency += ret * 1000;
|
transition_latency += ret * 1000;
|
||||||
ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
|
if (!IS_ERR(pu_reg)) {
|
||||||
if (ret > 0)
|
ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
|
||||||
transition_latency += ret * 1000;
|
if (ret > 0)
|
||||||
|
transition_latency += ret * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OPP is maintained in order of increasing frequency, and
|
* OPP is maintained in order of increasing frequency, and
|
||||||
|
@ -327,7 +333,8 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev)
|
||||||
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
|
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
|
||||||
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
|
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
|
||||||
regulator_put(arm_reg);
|
regulator_put(arm_reg);
|
||||||
regulator_put(pu_reg);
|
if (!IS_ERR(pu_reg))
|
||||||
|
regulator_put(pu_reg);
|
||||||
regulator_put(soc_reg);
|
regulator_put(soc_reg);
|
||||||
clk_put(arm_clk);
|
clk_put(arm_clk);
|
||||||
clk_put(pll1_sys_clk);
|
clk_put(pll1_sys_clk);
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#define BYT_TURBO_RATIOS 0x66c
|
#define BYT_TURBO_RATIOS 0x66c
|
||||||
#define BYT_TURBO_VIDS 0x66d
|
#define BYT_TURBO_VIDS 0x66d
|
||||||
|
|
||||||
|
|
||||||
#define FRAC_BITS 8
|
#define FRAC_BITS 8
|
||||||
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
|
#define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
|
||||||
#define fp_toint(X) ((X) >> FRAC_BITS)
|
#define fp_toint(X) ((X) >> FRAC_BITS)
|
||||||
|
@ -50,7 +49,7 @@ static inline int32_t mul_fp(int32_t x, int32_t y)
|
||||||
|
|
||||||
static inline int32_t div_fp(int32_t x, int32_t y)
|
static inline int32_t div_fp(int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
|
return div_s64((int64_t)x << FRAC_BITS, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sample {
|
struct sample {
|
||||||
|
@ -148,7 +147,7 @@ static struct perf_limits limits = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
|
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
|
||||||
int deadband, int integral) {
|
int deadband, int integral) {
|
||||||
pid->setpoint = setpoint;
|
pid->setpoint = setpoint;
|
||||||
pid->deadband = deadband;
|
pid->deadband = deadband;
|
||||||
pid->integral = int_tofp(integral);
|
pid->integral = int_tofp(integral);
|
||||||
|
@ -167,7 +166,6 @@ static inline void pid_i_gain_set(struct _pid *pid, int percent)
|
||||||
|
|
||||||
static inline void pid_d_gain_set(struct _pid *pid, int percent)
|
static inline void pid_d_gain_set(struct _pid *pid, int percent)
|
||||||
{
|
{
|
||||||
|
|
||||||
pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
|
pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,16 +205,13 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
|
||||||
pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
|
pid_d_gain_set(&cpu->pid, pid_params.d_gain_pct);
|
||||||
pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
|
pid_i_gain_set(&cpu->pid, pid_params.i_gain_pct);
|
||||||
|
|
||||||
pid_reset(&cpu->pid,
|
pid_reset(&cpu->pid, pid_params.setpoint, 100, pid_params.deadband, 0);
|
||||||
pid_params.setpoint,
|
|
||||||
100,
|
|
||||||
pid_params.deadband,
|
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void intel_pstate_reset_all_pid(void)
|
static inline void intel_pstate_reset_all_pid(void)
|
||||||
{
|
{
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
|
||||||
for_each_online_cpu(cpu) {
|
for_each_online_cpu(cpu) {
|
||||||
if (all_cpu_data[cpu])
|
if (all_cpu_data[cpu])
|
||||||
intel_pstate_busy_pid_reset(all_cpu_data[cpu]);
|
intel_pstate_busy_pid_reset(all_cpu_data[cpu]);
|
||||||
|
@ -230,13 +225,13 @@ static int pid_param_set(void *data, u64 val)
|
||||||
intel_pstate_reset_all_pid();
|
intel_pstate_reset_all_pid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pid_param_get(void *data, u64 *val)
|
static int pid_param_get(void *data, u64 *val)
|
||||||
{
|
{
|
||||||
*val = *(u32 *)data;
|
*val = *(u32 *)data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get,
|
DEFINE_SIMPLE_ATTRIBUTE(fops_pid_param, pid_param_get, pid_param_set, "%llu\n");
|
||||||
pid_param_set, "%llu\n");
|
|
||||||
|
|
||||||
struct pid_param {
|
struct pid_param {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -253,9 +248,9 @@ static struct pid_param pid_files[] = {
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dentry *debugfs_parent;
|
static void __init intel_pstate_debug_expose_params(void)
|
||||||
static void intel_pstate_debug_expose_params(void)
|
|
||||||
{
|
{
|
||||||
|
struct dentry *debugfs_parent;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
|
debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
|
||||||
|
@ -263,8 +258,8 @@ static void intel_pstate_debug_expose_params(void)
|
||||||
return;
|
return;
|
||||||
while (pid_files[i].name) {
|
while (pid_files[i].name) {
|
||||||
debugfs_create_file(pid_files[i].name, 0660,
|
debugfs_create_file(pid_files[i].name, 0660,
|
||||||
debugfs_parent, pid_files[i].value,
|
debugfs_parent, pid_files[i].value,
|
||||||
&fops_pid_param);
|
&fops_pid_param);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,10 +275,11 @@ static void intel_pstate_debug_expose_params(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
|
static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
unsigned int input;
|
unsigned int input;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sscanf(buf, "%u", &input);
|
ret = sscanf(buf, "%u", &input);
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -296,10 +292,11 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
|
static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
unsigned int input;
|
unsigned int input;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sscanf(buf, "%u", &input);
|
ret = sscanf(buf, "%u", &input);
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -307,14 +304,16 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
|
||||||
limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
|
limits.max_sysfs_pct = clamp_t(int, input, 0 , 100);
|
||||||
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
|
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
|
||||||
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
|
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
|
static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
unsigned int input;
|
unsigned int input;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = sscanf(buf, "%u", &input);
|
ret = sscanf(buf, "%u", &input);
|
||||||
if (ret != 1)
|
if (ret != 1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -342,17 +341,16 @@ static struct attribute *intel_pstate_attributes[] = {
|
||||||
static struct attribute_group intel_pstate_attr_group = {
|
static struct attribute_group intel_pstate_attr_group = {
|
||||||
.attrs = intel_pstate_attributes,
|
.attrs = intel_pstate_attributes,
|
||||||
};
|
};
|
||||||
static struct kobject *intel_pstate_kobject;
|
|
||||||
|
|
||||||
static void intel_pstate_sysfs_expose_params(void)
|
static void __init intel_pstate_sysfs_expose_params(void)
|
||||||
{
|
{
|
||||||
|
struct kobject *intel_pstate_kobject;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
intel_pstate_kobject = kobject_create_and_add("intel_pstate",
|
intel_pstate_kobject = kobject_create_and_add("intel_pstate",
|
||||||
&cpu_subsys.dev_root->kobj);
|
&cpu_subsys.dev_root->kobj);
|
||||||
BUG_ON(!intel_pstate_kobject);
|
BUG_ON(!intel_pstate_kobject);
|
||||||
rc = sysfs_create_group(intel_pstate_kobject,
|
rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
|
||||||
&intel_pstate_attr_group);
|
|
||||||
BUG_ON(rc);
|
BUG_ON(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,6 +358,7 @@ static void intel_pstate_sysfs_expose_params(void)
|
||||||
static int byt_get_min_pstate(void)
|
static int byt_get_min_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(BYT_RATIOS, value);
|
rdmsrl(BYT_RATIOS, value);
|
||||||
return (value >> 8) & 0x7F;
|
return (value >> 8) & 0x7F;
|
||||||
}
|
}
|
||||||
|
@ -367,6 +366,7 @@ static int byt_get_min_pstate(void)
|
||||||
static int byt_get_max_pstate(void)
|
static int byt_get_max_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(BYT_RATIOS, value);
|
rdmsrl(BYT_RATIOS, value);
|
||||||
return (value >> 16) & 0x7F;
|
return (value >> 16) & 0x7F;
|
||||||
}
|
}
|
||||||
|
@ -374,6 +374,7 @@ static int byt_get_max_pstate(void)
|
||||||
static int byt_get_turbo_pstate(void)
|
static int byt_get_turbo_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(BYT_TURBO_RATIOS, value);
|
rdmsrl(BYT_TURBO_RATIOS, value);
|
||||||
return value & 0x7F;
|
return value & 0x7F;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +408,6 @@ static void byt_get_vid(struct cpudata *cpudata)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
|
|
||||||
rdmsrl(BYT_VIDS, value);
|
rdmsrl(BYT_VIDS, value);
|
||||||
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
|
cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
|
||||||
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
|
cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
|
||||||
|
@ -420,10 +420,10 @@ static void byt_get_vid(struct cpudata *cpudata)
|
||||||
cpudata->vid.turbo = value & 0x7f;
|
cpudata->vid.turbo = value & 0x7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int core_get_min_pstate(void)
|
static int core_get_min_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(MSR_PLATFORM_INFO, value);
|
rdmsrl(MSR_PLATFORM_INFO, value);
|
||||||
return (value >> 40) & 0xFF;
|
return (value >> 40) & 0xFF;
|
||||||
}
|
}
|
||||||
|
@ -431,6 +431,7 @@ static int core_get_min_pstate(void)
|
||||||
static int core_get_max_pstate(void)
|
static int core_get_max_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
|
|
||||||
rdmsrl(MSR_PLATFORM_INFO, value);
|
rdmsrl(MSR_PLATFORM_INFO, value);
|
||||||
return (value >> 8) & 0xFF;
|
return (value >> 8) & 0xFF;
|
||||||
}
|
}
|
||||||
|
@ -439,9 +440,10 @@ static int core_get_turbo_pstate(void)
|
||||||
{
|
{
|
||||||
u64 value;
|
u64 value;
|
||||||
int nont, ret;
|
int nont, ret;
|
||||||
|
|
||||||
rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
|
rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
|
||||||
nont = core_get_max_pstate();
|
nont = core_get_max_pstate();
|
||||||
ret = ((value) & 255);
|
ret = (value) & 255;
|
||||||
if (ret <= nont)
|
if (ret <= nont)
|
||||||
ret = nont;
|
ret = nont;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -493,12 +495,12 @@ static struct cpu_defaults byt_params = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
||||||
{
|
{
|
||||||
int max_perf = cpu->pstate.turbo_pstate;
|
int max_perf = cpu->pstate.turbo_pstate;
|
||||||
int max_perf_adj;
|
int max_perf_adj;
|
||||||
int min_perf;
|
int min_perf;
|
||||||
|
|
||||||
if (limits.no_turbo)
|
if (limits.no_turbo)
|
||||||
max_perf = cpu->pstate.max_pstate;
|
max_perf = cpu->pstate.max_pstate;
|
||||||
|
|
||||||
|
@ -507,8 +509,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
||||||
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
|
cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
|
||||||
|
|
||||||
min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
|
min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
|
||||||
*min = clamp_t(int, min_perf,
|
*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
|
||||||
cpu->pstate.min_pstate, max_perf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
||||||
|
@ -529,21 +530,6 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
||||||
pstate_funcs.set(cpu, pstate);
|
pstate_funcs.set(cpu, pstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
|
|
||||||
{
|
|
||||||
int target;
|
|
||||||
target = cpu->pstate.current_pstate + steps;
|
|
||||||
|
|
||||||
intel_pstate_set_pstate(cpu, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void intel_pstate_pstate_decrease(struct cpudata *cpu, int steps)
|
|
||||||
{
|
|
||||||
int target;
|
|
||||||
target = cpu->pstate.current_pstate - steps;
|
|
||||||
intel_pstate_set_pstate(cpu, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
|
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
|
||||||
{
|
{
|
||||||
cpu->pstate.min_pstate = pstate_funcs.get_min();
|
cpu->pstate.min_pstate = pstate_funcs.get_min();
|
||||||
|
@ -559,13 +545,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
|
||||||
{
|
{
|
||||||
struct sample *sample = &cpu->sample;
|
struct sample *sample = &cpu->sample;
|
||||||
int64_t core_pct;
|
int64_t core_pct;
|
||||||
int32_t rem;
|
|
||||||
|
|
||||||
core_pct = int_tofp(sample->aperf) * int_tofp(100);
|
core_pct = int_tofp(sample->aperf) * int_tofp(100);
|
||||||
core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
|
core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
|
||||||
|
|
||||||
if ((rem << 1) >= int_tofp(sample->mperf))
|
|
||||||
core_pct += 1;
|
|
||||||
|
|
||||||
sample->freq = fp_toint(
|
sample->freq = fp_toint(
|
||||||
mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
|
mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
|
||||||
|
@ -576,12 +558,12 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
|
||||||
static inline void intel_pstate_sample(struct cpudata *cpu)
|
static inline void intel_pstate_sample(struct cpudata *cpu)
|
||||||
{
|
{
|
||||||
u64 aperf, mperf;
|
u64 aperf, mperf;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
rdmsrl(MSR_IA32_APERF, aperf);
|
rdmsrl(MSR_IA32_APERF, aperf);
|
||||||
rdmsrl(MSR_IA32_MPERF, mperf);
|
rdmsrl(MSR_IA32_MPERF, mperf);
|
||||||
|
local_irq_restore(flags);
|
||||||
aperf = aperf >> FRAC_BITS;
|
|
||||||
mperf = mperf >> FRAC_BITS;
|
|
||||||
|
|
||||||
cpu->last_sample_time = cpu->sample.time;
|
cpu->last_sample_time = cpu->sample.time;
|
||||||
cpu->sample.time = ktime_get();
|
cpu->sample.time = ktime_get();
|
||||||
|
@ -598,10 +580,9 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
|
||||||
|
|
||||||
static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
|
static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
|
||||||
{
|
{
|
||||||
int sample_time, delay;
|
int delay;
|
||||||
|
|
||||||
sample_time = pid_params.sample_rate_ms;
|
delay = msecs_to_jiffies(pid_params.sample_rate_ms);
|
||||||
delay = msecs_to_jiffies(sample_time);
|
|
||||||
mod_timer_pinned(&cpu->timer, jiffies + delay);
|
mod_timer_pinned(&cpu->timer, jiffies + delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,12 +597,12 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
|
||||||
current_pstate = int_tofp(cpu->pstate.current_pstate);
|
current_pstate = int_tofp(cpu->pstate.current_pstate);
|
||||||
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
|
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
|
||||||
|
|
||||||
sample_time = (pid_params.sample_rate_ms * USEC_PER_MSEC);
|
sample_time = pid_params.sample_rate_ms * USEC_PER_MSEC;
|
||||||
duration_us = (u32) ktime_us_delta(cpu->sample.time,
|
duration_us = (u32) ktime_us_delta(cpu->sample.time,
|
||||||
cpu->last_sample_time);
|
cpu->last_sample_time);
|
||||||
if (duration_us > sample_time * 3) {
|
if (duration_us > sample_time * 3) {
|
||||||
sample_ratio = div_fp(int_tofp(sample_time),
|
sample_ratio = div_fp(int_tofp(sample_time),
|
||||||
int_tofp(duration_us));
|
int_tofp(duration_us));
|
||||||
core_busy = mul_fp(core_busy, sample_ratio);
|
core_busy = mul_fp(core_busy, sample_ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,20 +613,15 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
|
||||||
{
|
{
|
||||||
int32_t busy_scaled;
|
int32_t busy_scaled;
|
||||||
struct _pid *pid;
|
struct _pid *pid;
|
||||||
signed int ctl = 0;
|
signed int ctl;
|
||||||
int steps;
|
|
||||||
|
|
||||||
pid = &cpu->pid;
|
pid = &cpu->pid;
|
||||||
busy_scaled = intel_pstate_get_scaled_busy(cpu);
|
busy_scaled = intel_pstate_get_scaled_busy(cpu);
|
||||||
|
|
||||||
ctl = pid_calc(pid, busy_scaled);
|
ctl = pid_calc(pid, busy_scaled);
|
||||||
|
|
||||||
steps = abs(ctl);
|
/* Negative values of ctl increase the pstate and vice versa */
|
||||||
|
intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl);
|
||||||
if (ctl < 0)
|
|
||||||
intel_pstate_pstate_increase(cpu, steps);
|
|
||||||
else
|
|
||||||
intel_pstate_pstate_decrease(cpu, steps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_pstate_timer_func(unsigned long __data)
|
static void intel_pstate_timer_func(unsigned long __data)
|
||||||
|
@ -705,8 +681,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
|
||||||
|
|
||||||
init_timer_deferrable(&cpu->timer);
|
init_timer_deferrable(&cpu->timer);
|
||||||
cpu->timer.function = intel_pstate_timer_func;
|
cpu->timer.function = intel_pstate_timer_func;
|
||||||
cpu->timer.data =
|
cpu->timer.data = (unsigned long)cpu;
|
||||||
(unsigned long)cpu;
|
|
||||||
cpu->timer.expires = jiffies + HZ/100;
|
cpu->timer.expires = jiffies + HZ/100;
|
||||||
intel_pstate_busy_pid_reset(cpu);
|
intel_pstate_busy_pid_reset(cpu);
|
||||||
intel_pstate_sample(cpu);
|
intel_pstate_sample(cpu);
|
||||||
|
@ -751,7 +726,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
|
||||||
limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
|
limits.min_perf_pct = clamp_t(int, limits.min_perf_pct, 0 , 100);
|
||||||
limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
|
limits.min_perf = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
|
||||||
|
|
||||||
limits.max_policy_pct = policy->max * 100 / policy->cpuinfo.max_freq;
|
limits.max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
|
||||||
limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
|
limits.max_policy_pct = clamp_t(int, limits.max_policy_pct, 0 , 100);
|
||||||
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
|
limits.max_perf_pct = min(limits.max_policy_pct, limits.max_sysfs_pct);
|
||||||
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
|
limits.max_perf = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
|
||||||
|
@ -763,8 +738,8 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
cpufreq_verify_within_cpu_limits(policy);
|
cpufreq_verify_within_cpu_limits(policy);
|
||||||
|
|
||||||
if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
|
if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
|
||||||
(policy->policy != CPUFREQ_POLICY_PERFORMANCE))
|
policy->policy != CPUFREQ_POLICY_PERFORMANCE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -797,7 +772,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
|
rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
|
||||||
if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
|
if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
|
||||||
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
|
cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
|
||||||
limits.turbo_disabled = 1;
|
limits.turbo_disabled = 1;
|
||||||
limits.no_turbo = 1;
|
limits.no_turbo = 1;
|
||||||
}
|
}
|
||||||
|
@ -839,8 +814,8 @@ static int intel_pstate_msrs_not_valid(void)
|
||||||
rdmsrl(MSR_IA32_MPERF, mperf);
|
rdmsrl(MSR_IA32_MPERF, mperf);
|
||||||
|
|
||||||
if (!pstate_funcs.get_max() ||
|
if (!pstate_funcs.get_max() ||
|
||||||
!pstate_funcs.get_min() ||
|
!pstate_funcs.get_min() ||
|
||||||
!pstate_funcs.get_turbo())
|
!pstate_funcs.get_turbo())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
rdmsrl(MSR_IA32_APERF, tmp);
|
rdmsrl(MSR_IA32_APERF, tmp);
|
||||||
|
@ -922,14 +897,14 @@ static bool intel_pstate_platform_pwr_mgmt_exists(void)
|
||||||
struct acpi_table_header hdr;
|
struct acpi_table_header hdr;
|
||||||
struct hw_vendor_info *v_info;
|
struct hw_vendor_info *v_info;
|
||||||
|
|
||||||
if (acpi_disabled
|
if (acpi_disabled ||
|
||||||
|| ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
|
ACPI_FAILURE(acpi_get_table_header(ACPI_SIG_FADT, 0, &hdr)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (v_info = vendor_info; v_info->valid; v_info++) {
|
for (v_info = vendor_info; v_info->valid; v_info++) {
|
||||||
if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE)
|
if (!strncmp(hdr.oem_id, v_info->oem_id, ACPI_OEM_ID_SIZE) &&
|
||||||
&& !strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE)
|
!strncmp(hdr.oem_table_id, v_info->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
|
||||||
&& intel_pstate_no_acpi_pss())
|
intel_pstate_no_acpi_pss())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ static const struct {
|
||||||
unsigned freq;
|
unsigned freq;
|
||||||
unsigned mult;
|
unsigned mult;
|
||||||
} usual_frequency_table[] = {
|
} usual_frequency_table[] = {
|
||||||
|
{ 350000, 35 }, // 100 * 3.5
|
||||||
{ 400000, 40 }, // 100 * 4
|
{ 400000, 40 }, // 100 * 4
|
||||||
{ 450000, 45 }, // 100 * 4.5
|
{ 450000, 45 }, // 100 * 4.5
|
||||||
{ 475000, 50 }, // 95 * 5
|
{ 475000, 50 }, // 95 * 5
|
||||||
|
|
|
@ -176,6 +176,7 @@ static inline void disable_cpufreq(void) { }
|
||||||
|
|
||||||
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */
|
#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */
|
||||||
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */
|
#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */
|
||||||
|
#define CPUFREQ_RELATION_C 2 /* closest frequency to target */
|
||||||
|
|
||||||
struct freq_attr {
|
struct freq_attr {
|
||||||
struct attribute attr;
|
struct attribute attr;
|
||||||
|
|
Loading…
Reference in New Issue