Merge branch 'pm-cpufreq'

* pm-cpufreq:
  cpufreq / intel_pstate: use vzalloc() instead of vmalloc()/memset(0)
  cpufreq, ondemand: Remove leftover debug line
  cpufreq / kirkwood: don't check resource with devm_ioremap_resource
  cpufreq / intel_pstate: remove #ifdef MODULE compile fence
  cpufreq / intel_pstate: Remove idle mode PID
  cpufreq / intel_pstate: fix ffmpeg regression
  cpufreq / intel_pstate: use lowest requested max performance
  cpufreq / intel_pstate: remove idle time and duration from sample and calculations
  cpufreq: Fix incorrect dependecies for ARM SA11xx drivers
  cpufreq: ARM big LITTLE: Fix Kconfig entries
  cpufreq: cpufreq-cpu0: Free parent node for error cases
  cpufreq: cpufreq-cpu0: defer probe when regulator is not ready
  cpufreq: Issue CPUFREQ_GOV_POLICY_EXIT notifier before dropping policy refcount
  cpufreq: governors: Fix CPUFREQ_GOV_POLICY_{INIT|EXIT} notifiers
  cpufreq: ARM big LITTLE: Improve print message
  cpufreq: ARM big LITTLE: Move cpu_to_cluster() to arm_big_little.h
  cpufreq: ARM big LITTLE DT: Return CPUFREQ_ETERNAL if clock-latency isn't found
  cpufreq: ARM big LITTLE DT: Return correct transition latency
  cpufreq: ARM big LITTLE: Select PM_OPP
This commit is contained in:
Rafael J. Wysocki 2013-05-14 15:11:55 +02:00
commit d5a2fa27ec
12 changed files with 71 additions and 137 deletions

View file

@ -47,7 +47,7 @@ config CPU_FREQ_STAT_DETAILS
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ
default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at

View file

@ -3,16 +3,17 @@
#
config ARM_BIG_LITTLE_CPUFREQ
tristate
depends on ARM_CPU_TOPOLOGY
tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
config ARM_DT_BL_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver probed via DT"
select ARM_BIG_LITTLE_CPUFREQ
depends on OF && HAVE_CLK
tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
depends on ARM_BIG_LITTLE_CPUFREQ && OF
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platform.
This gets frequency tables from DT.
This enables probing via DT for Generic CPUfreq driver for ARM
big.LITTLE platform. This gets frequency tables from DT.
config ARM_EXYNOS_CPUFREQ
bool "SAMSUNG EXYNOS SoCs"

View file

@ -40,11 +40,6 @@ static struct clk *clk[MAX_CLUSTERS];
static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS];
static atomic_t cluster_usage[MAX_CLUSTERS] = {ATOMIC_INIT(0), ATOMIC_INIT(0)};
static int cpu_to_cluster(int cpu)
{
return topology_physical_package_id(cpu);
}
static unsigned int bL_cpufreq_get(unsigned int cpu)
{
u32 cur_cluster = cpu_to_cluster(cpu);
@ -192,7 +187,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
dev_info(cpu_dev, "CPU %d initialized\n", policy->cpu);
dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
return 0;
}

View file

@ -34,6 +34,11 @@ struct cpufreq_arm_bL_ops {
int (*init_opp_table)(struct device *cpu_dev);
};
static inline int cpu_to_cluster(int cpu)
{
return topology_physical_package_id(cpu);
}
int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops);

View file

@ -66,8 +66,8 @@ static int dt_get_transition_latency(struct device *cpu_dev)
parent = of_find_node_by_path("/cpus");
if (!parent) {
pr_err("failed to find OF /cpus\n");
return -ENOENT;
pr_info("Failed to find OF /cpus. Use CPUFREQ_ETERNAL transition latency\n");
return CPUFREQ_ETERNAL;
}
for_each_child_of_node(parent, np) {
@ -78,10 +78,11 @@ static int dt_get_transition_latency(struct device *cpu_dev)
of_node_put(np);
of_node_put(parent);
return 0;
return transition_latency;
}
return -ENODEV;
pr_info("clock-latency isn't found, use CPUFREQ_ETERNAL transition latency\n");
return CPUFREQ_ETERNAL;
}
static struct cpufreq_arm_bL_ops dt_bL_ops = {

View file

@ -189,12 +189,29 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
if (!np) {
pr_err("failed to find cpu0 node\n");
return -ENOENT;
ret = -ENOENT;
goto out_put_parent;
}
cpu_dev = &pdev->dev;
cpu_dev->of_node = np;
cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
if (IS_ERR(cpu_reg)) {
/*
* If cpu0 regulator supply node is present, but regulator is
* not yet registered, we should try defering probe.
*/
if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
dev_err(cpu_dev, "cpu0 regulator not ready, retry\n");
ret = -EPROBE_DEFER;
goto out_put_node;
}
pr_warn("failed to get cpu0 regulator: %ld\n",
PTR_ERR(cpu_reg));
cpu_reg = NULL;
}
cpu_clk = devm_clk_get(cpu_dev, NULL);
if (IS_ERR(cpu_clk)) {
ret = PTR_ERR(cpu_clk);
@ -202,12 +219,6 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
goto out_put_node;
}
cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
if (IS_ERR(cpu_reg)) {
pr_warn("failed to get cpu0 regulator\n");
cpu_reg = NULL;
}
ret = of_init_opp_table(cpu_dev);
if (ret) {
pr_err("failed to init OPP table: %d\n", ret);
@ -264,6 +275,8 @@ out_free_table:
opp_free_cpufreq_table(cpu_dev, &freq_table);
out_put_node:
of_node_put(np);
out_put_parent:
of_node_put(parent);
return ret;
}

View file

@ -1075,14 +1075,14 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
__func__, cpu_dev->id, cpu);
}
if ((cpus == 1) && (cpufreq_driver->target))
__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
cpufreq_cpu_put(data);
/* If cpu is last user of policy, free policy */
if (cpus == 1) {
if (cpufreq_driver->target)
__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
lock_policy_rwsem_read(cpu);
kobj = &data->kobj;
cmp = &data->kobj_unregister;

View file

@ -255,6 +255,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
if (have_governor_per_policy()) {
WARN_ON(dbs_data);
} else if (dbs_data) {
dbs_data->usage_count++;
policy->governor_data = dbs_data;
return 0;
}
@ -266,6 +267,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
}
dbs_data->cdata = cdata;
dbs_data->usage_count = 1;
rc = cdata->init(dbs_data);
if (rc) {
pr_err("%s: POLICY_INIT: init() failed\n", __func__);
@ -294,7 +296,8 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
latency * LATENCY_MULTIPLIER));
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
if ((cdata->governor == GOV_CONSERVATIVE) &&
(!policy->governor->initialized)) {
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
cpufreq_register_notifier(cs_ops->notifier_block,
@ -306,12 +309,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return 0;
case CPUFREQ_GOV_POLICY_EXIT:
if ((policy->governor->initialized == 1) ||
have_governor_per_policy()) {
if (!--dbs_data->usage_count) {
sysfs_remove_group(get_governor_parent_kobj(policy),
get_sysfs_attr(dbs_data));
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
if ((dbs_data->cdata->governor == GOV_CONSERVATIVE) &&
(policy->governor->initialized == 1)) {
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
cpufreq_unregister_notifier(cs_ops->notifier_block,

View file

@ -211,6 +211,7 @@ struct common_dbs_data {
struct dbs_data {
struct common_dbs_data *cdata;
unsigned int min_sampling_rate;
int usage_count;
void *tuners;
/* dbs_mutex protects dbs_enable in governor start/stop */

View file

@ -547,7 +547,6 @@ static int od_init(struct dbs_data *dbs_data)
tuners->io_is_busy = should_io_be_busy();
dbs_data->tuners = tuners;
pr_info("%s: tuners %p\n", __func__, tuners);
mutex_init(&dbs_data->mutex);
return 0;
}

View file

@ -48,12 +48,7 @@ static inline int32_t div_fp(int32_t x, int32_t y)
}
struct sample {
ktime_t start_time;
ktime_t end_time;
int core_pct_busy;
int pstate_pct_busy;
u64 duration_us;
u64 idletime_us;
u64 aperf;
u64 mperf;
int freq;
@ -86,13 +81,9 @@ struct cpudata {
struct pstate_adjust_policy *pstate_policy;
struct pstate_data pstate;
struct _pid pid;
struct _pid idle_pid;
int min_pstate_count;
int idle_mode;
ktime_t prev_sample;
u64 prev_idle_time_us;
u64 prev_aperf;
u64 prev_mperf;
int sample_ptr;
@ -124,6 +115,8 @@ struct perf_limits {
int min_perf_pct;
int32_t max_perf;
int32_t min_perf;
int max_policy_pct;
int max_sysfs_pct;
};
static struct perf_limits limits = {
@ -132,6 +125,8 @@ static struct perf_limits limits = {
.max_perf = int_tofp(1),
.min_perf_pct = 0,
.min_perf = 0,
.max_policy_pct = 100,
.max_sysfs_pct = 100,
};
static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
@ -202,19 +197,6 @@ static inline void intel_pstate_busy_pid_reset(struct cpudata *cpu)
0);
}
static inline void intel_pstate_idle_pid_reset(struct cpudata *cpu)
{
pid_p_gain_set(&cpu->idle_pid, cpu->pstate_policy->p_gain_pct);
pid_d_gain_set(&cpu->idle_pid, cpu->pstate_policy->d_gain_pct);
pid_i_gain_set(&cpu->idle_pid, cpu->pstate_policy->i_gain_pct);
pid_reset(&cpu->idle_pid,
75,
50,
cpu->pstate_policy->deadband,
0);
}
static inline void intel_pstate_reset_all_pid(void)
{
unsigned int cpu;
@ -302,7 +284,8 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
if (ret != 1)
return -EINVAL;
limits.max_perf_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 = div_fp(int_tofp(limits.max_perf_pct), int_tofp(100));
return count;
}
@ -408,9 +391,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
if (pstate == cpu->pstate.current_pstate)
return;
#ifndef MODULE
trace_cpu_frequency(pstate * 100000, cpu->cpu);
#endif
cpu->pstate.current_pstate = pstate;
wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
@ -450,48 +432,26 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,
struct sample *sample)
{
u64 core_pct;
sample->pstate_pct_busy = 100 - div64_u64(
sample->idletime_us * 100,
sample->duration_us);
core_pct = div64_u64(sample->aperf * 100, sample->mperf);
sample->freq = cpu->pstate.max_pstate * core_pct * 1000;
sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct),
100);
sample->core_pct_busy = core_pct;
}
static inline void intel_pstate_sample(struct cpudata *cpu)
{
ktime_t now;
u64 idle_time_us;
u64 aperf, mperf;
now = ktime_get();
idle_time_us = get_cpu_idle_time_us(cpu->cpu, NULL);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
/* for the first sample, don't actually record a sample, just
* set the baseline */
if (cpu->prev_idle_time_us > 0) {
cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
cpu->samples[cpu->sample_ptr].start_time = cpu->prev_sample;
cpu->samples[cpu->sample_ptr].end_time = now;
cpu->samples[cpu->sample_ptr].duration_us =
ktime_us_delta(now, cpu->prev_sample);
cpu->samples[cpu->sample_ptr].idletime_us =
idle_time_us - cpu->prev_idle_time_us;
cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
cpu->samples[cpu->sample_ptr].aperf = aperf;
cpu->samples[cpu->sample_ptr].mperf = mperf;
cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
cpu->samples[cpu->sample_ptr].aperf = aperf;
cpu->samples[cpu->sample_ptr].mperf = mperf;
cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
}
cpu->prev_sample = now;
cpu->prev_idle_time_us = idle_time_us;
cpu->prev_aperf = aperf;
cpu->prev_mperf = mperf;
}
@ -505,16 +465,6 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
mod_timer_pinned(&cpu->timer, jiffies + delay);
}
static inline void intel_pstate_idle_mode(struct cpudata *cpu)
{
cpu->idle_mode = 1;
}
static inline void intel_pstate_normal_mode(struct cpudata *cpu)
{
cpu->idle_mode = 0;
}
static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
{
int32_t busy_scaled;
@ -547,50 +497,21 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
intel_pstate_pstate_decrease(cpu, steps);
}
static inline void intel_pstate_adjust_idle_pstate(struct cpudata *cpu)
{
int busy_scaled;
struct _pid *pid;
int ctl = 0;
int steps;
pid = &cpu->idle_pid;
busy_scaled = intel_pstate_get_scaled_busy(cpu);
ctl = pid_calc(pid, 100 - busy_scaled);
steps = abs(ctl);
if (ctl < 0)
intel_pstate_pstate_decrease(cpu, steps);
else
intel_pstate_pstate_increase(cpu, steps);
if (cpu->pstate.current_pstate == cpu->pstate.min_pstate)
intel_pstate_normal_mode(cpu);
}
static void intel_pstate_timer_func(unsigned long __data)
{
struct cpudata *cpu = (struct cpudata *) __data;
intel_pstate_sample(cpu);
intel_pstate_adjust_busy_pstate(cpu);
if (!cpu->idle_mode)
intel_pstate_adjust_busy_pstate(cpu);
else
intel_pstate_adjust_idle_pstate(cpu);
#if defined(XPERF_FIX)
if (cpu->pstate.current_pstate == cpu->pstate.min_pstate) {
cpu->min_pstate_count++;
if (!(cpu->min_pstate_count % 5)) {
intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
intel_pstate_idle_mode(cpu);
}
} else
cpu->min_pstate_count = 0;
#endif
intel_pstate_set_sample_time(cpu);
}
@ -631,7 +552,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
(unsigned long)cpu;
cpu->timer.expires = jiffies + HZ/100;
intel_pstate_busy_pid_reset(cpu);
intel_pstate_idle_pid_reset(cpu);
intel_pstate_sample(cpu);
intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
@ -675,8 +595,9 @@ 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 = div_fp(int_tofp(limits.min_perf_pct), int_tofp(100));
limits.max_perf_pct = policy->max * 100 / policy->cpuinfo.max_freq;
limits.max_perf_pct = clamp_t(int, limits.max_perf_pct, 0 , 100);
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_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));
return 0;
@ -788,10 +709,9 @@ static int __init intel_pstate_init(void)
pr_info("Intel P-state driver initializing.\n");
all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus());
all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
if (!all_cpu_data)
return -ENOMEM;
memset(all_cpu_data, 0, sizeof(void *) * num_possible_cpus());
rc = cpufreq_register_driver(&intel_pstate_driver);
if (rc)

View file

@ -171,10 +171,6 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
priv.dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Cannot get memory resource\n");
return -ENODEV;
}
priv.base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv.base))
return PTR_ERR(priv.base);