Commit b14c348e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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
parents eada238f 1bfb425b
......@@ -1076,10 +1076,20 @@ static void cpufreq_policy_free(struct cpufreq_policy *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))
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);
......@@ -1090,6 +1100,8 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_UPDATE_POLICY_CPU, policy);
return 0;
}
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
* by invoking update_policy_cpu().
*/
if (recover_policy && cpu != policy->cpu) {
update_policy_cpu(policy, cpu);
WARN_ON(kobject_move(&policy->kobj, &dev->kobj));
} else {
if (recover_policy && cpu != policy->cpu)
WARN_ON(update_policy_cpu(policy, cpu, dev));
else
policy->cpu = 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);
}
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,
struct subsys_interface *sif)
{
unsigned int cpu = dev->id, cpus;
int new_cpu, ret;
int ret;
unsigned long flags;
struct cpufreq_policy *policy;
......@@ -1380,14 +1363,23 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
if (cpu != policy->cpu) {
sysfs_remove_link(&dev->kobj, "cpufreq");
} else if (cpus > 1) {
new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu);
if (new_cpu >= 0) {
update_policy_cpu(policy, new_cpu);
/* Nominate new CPU */
int new_cpu = cpumask_any_but(policy->cpus, cpu);
struct device *cpu_dev = get_cpu_device(new_cpu);
if (!cpufreq_suspended)
pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
__func__, new_cpu, cpu);
sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
ret = update_policy_cpu(policy, new_cpu, cpu_dev);
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) {
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);
} else {
/* Calculate the next frequency proportional to load */
unsigned int freq_next;
freq_next = load * policy->cpuinfo.max_freq / 100;
unsigned int freq_next, min_f, max_f;
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 */
dbs_info->rate_mult = 1;
if (!od_tuners->powersave_bias) {
__cpufreq_driver_target(policy, freq_next,
CPUFREQ_RELATION_L);
CPUFREQ_RELATION_C);
return;
}
freq_next = od_ops.powersave_bias_target(policy, freq_next,
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,
};
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",
target_freq, relation, policy->cpu);
......@@ -127,6 +127,7 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
suboptimal.frequency = ~0;
break;
case CPUFREQ_RELATION_L:
case CPUFREQ_RELATION_C:
optimal.frequency = ~0;
break;
}
......@@ -168,6 +169,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
}
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) {
......
......@@ -66,10 +66,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
/* scaling up? scale voltage before frequency */
if (new_freq > old_freq) {
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
if (ret) {
dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret);
return ret;
if (!IS_ERR(pu_reg)) {
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
if (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);
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);
ret = 0;
}
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
if (ret) {
dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret);
ret = 0;
if (!IS_ERR(pu_reg)) {
ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0);
if (ret) {
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");
pu_reg = regulator_get(cpu_dev, "pu");
pu_reg = regulator_get_optional(cpu_dev, "pu");
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");
ret = -ENOENT;
goto put_reg;
......@@ -268,9 +272,11 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
if (ret > 0)
transition_latency += ret * 1000;
ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
if (ret > 0)
transition_latency += ret * 1000;
if (!IS_ERR(pu_reg)) {
ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]);
if (ret > 0)
transition_latency += ret * 1000;
}
/*
* 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);
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
regulator_put(arm_reg);
regulator_put(pu_reg);
if (!IS_ERR(pu_reg))
regulator_put(pu_reg);
regulator_put(soc_reg);
clk_put(arm_clk);
clk_put(pll1_sys_clk);
......
This diff is collapsed.
......@@ -55,6 +55,7 @@ static const struct {
unsigned freq;
unsigned mult;
} usual_frequency_table[] = {
{ 350000, 35 }, // 100 * 3.5
{ 400000, 40 }, // 100 * 4
{ 450000, 45 }, // 100 * 4.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_H 1 /* highest frequency below or at target */
#define CPUFREQ_RELATION_C 2 /* closest frequency to target */
struct freq_attr {
struct attribute attr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment