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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) ...@@ -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]); 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) ...@@ -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);
......
This diff is collapsed.
...@@ -55,6 +55,7 @@ static const struct { ...@@ -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) { } ...@@ -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;
......
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