Skip to content

Commit

Permalink
Merge branch 'pm-cpufreq'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Rafael J. Wysocki committed Aug 5, 2014
2 parents eada238 + 1bfb425 commit b14c348
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 138 deletions.
74 changes: 33 additions & 41 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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)
Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down
11 changes: 7 additions & 4 deletions drivers/cpufreq/cpufreq_ondemand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
12 changes: 11 additions & 1 deletion drivers/cpufreq/freq_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down
35 changes: 21 additions & 14 deletions drivers/cpufreq/imx6q-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit b14c348

Please sign in to comment.