提交 8ced6789 编写于 作者: R Rafael J. Wysocki

Merge branch 'pm-cpufreq'

* pm-cpufreq: (37 commits)
  cpufreq: dt: allow driver to boot automatically
  intel_pstate: Fix overflow in busy_scaled due to long delay
  cpufreq: qoriq: optimize the CPU frequency switching time
  cpufreq: gx-suspmod: Fix two typos in two comments
  cpufreq: nforce2: Fix typo in comment to function nforce2_init()
  cpufreq: governor: Serialize governor callbacks
  cpufreq: governor: split cpufreq_governor_dbs()
  cpufreq: governor: register notifier from cs_init()
  cpufreq: Remove cpufreq_update_policy()
  cpufreq: Restart governor as soon as possible
  cpufreq: Call cpufreq_policy_put_kobj() from cpufreq_policy_free()
  cpufreq: Initialize policy->kobj while allocating policy
  cpufreq: Stop migrating sysfs files on hotplug
  cpufreq: Don't allow updating inactive policies from sysfs
  intel_pstate: Force setting target pstate when required
  intel_pstate: change some inconsistent debug information
  cpufreq: Track cpu managing sysfs kobjects separately
  cpufreq: Fix for typos in two comments
  cpufreq: Mark policy->governor = NULL for inactive policies
  cpufreq: Manage governor usage history with 'policy->last_governor'
  ...
...@@ -196,8 +196,6 @@ affected_cpus : List of Online CPUs that require software ...@@ -196,8 +196,6 @@ affected_cpus : List of Online CPUs that require software
related_cpus : List of Online + Offline CPUs that need software related_cpus : List of Online + Offline CPUs that need software
coordination of frequency. coordination of frequency.
scaling_driver : Hardware driver for cpufreq.
scaling_cur_freq : Current frequency of the CPU as determined by scaling_cur_freq : Current frequency of the CPU as determined by
the governor and cpufreq core, in KHz. This is the governor and cpufreq core, in KHz. This is
the frequency the kernel thinks the CPU runs the frequency the kernel thinks the CPU runs
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# big LITTLE core layer and glue drivers # big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver" tristate "Generic ARM big LITTLE CPUfreq driver"
depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK depends on (ARM_CPU_TOPOLOGY || ARM64) && HAVE_CLK
select PM_OPP select PM_OPP
help help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/bL_switcher.h>
#include "arm_big_little.h" #include "arm_big_little.h"
...@@ -41,12 +40,16 @@ ...@@ -41,12 +40,16 @@
#define MAX_CLUSTERS 2 #define MAX_CLUSTERS 2
#ifdef CONFIG_BL_SWITCHER #ifdef CONFIG_BL_SWITCHER
#include <asm/bL_switcher.h>
static bool bL_switching_enabled; static bool bL_switching_enabled;
#define is_bL_switching_enabled() bL_switching_enabled #define is_bL_switching_enabled() bL_switching_enabled
#define set_switching_enabled(x) (bL_switching_enabled = (x)) #define set_switching_enabled(x) (bL_switching_enabled = (x))
#else #else
#define is_bL_switching_enabled() false #define is_bL_switching_enabled() false
#define set_switching_enabled(x) do { } while (0) #define set_switching_enabled(x) do { } while (0)
#define bL_switch_request(...) do { } while (0)
#define bL_switcher_put_enabled() do { } while (0)
#define bL_switcher_get_enabled() do { } while (0)
#endif #endif
#define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq)
...@@ -186,6 +189,15 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) ...@@ -186,6 +189,15 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
mutex_unlock(&cluster_lock[old_cluster]); mutex_unlock(&cluster_lock[old_cluster]);
} }
/*
* FIXME: clk_set_rate has to handle the case where clk_change_rate
* can fail due to hardware or firmware issues. Until the clk core
* layer is fixed, we can check here. In most of the cases we will
* be reading only the cached value anyway. This needs to be removed
* once clk core is fixed.
*/
if (bL_cpufreq_get_rate(cpu) != new_rate)
return -EIO;
return 0; return 0;
} }
...@@ -322,7 +334,6 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev) ...@@ -322,7 +334,6 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
static int _get_cluster_clk_and_freq_table(struct device *cpu_dev) static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
{ {
u32 cluster = raw_cpu_to_cluster(cpu_dev->id); u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
char name[14] = "cpu-cluster.";
int ret; int ret;
if (freq_table[cluster]) if (freq_table[cluster])
...@@ -342,8 +353,7 @@ static int _get_cluster_clk_and_freq_table(struct device *cpu_dev) ...@@ -342,8 +353,7 @@ static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
goto free_opp_table; goto free_opp_table;
} }
name[12] = cluster + '0'; clk[cluster] = clk_get(cpu_dev, NULL);
clk[cluster] = clk_get(cpu_dev, name);
if (!IS_ERR(clk[cluster])) { if (!IS_ERR(clk[cluster])) {
dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n", dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n",
__func__, clk[cluster], freq_table[cluster], __func__, clk[cluster], freq_table[cluster],
...@@ -506,6 +516,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { ...@@ -506,6 +516,7 @@ static struct cpufreq_driver bL_cpufreq_driver = {
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
#ifdef CONFIG_BL_SWITCHER
static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb, static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb,
unsigned long action, void *_arg) unsigned long action, void *_arg)
{ {
...@@ -538,6 +549,20 @@ static struct notifier_block bL_switcher_notifier = { ...@@ -538,6 +549,20 @@ static struct notifier_block bL_switcher_notifier = {
.notifier_call = bL_cpufreq_switcher_notifier, .notifier_call = bL_cpufreq_switcher_notifier,
}; };
static int __bLs_register_notifier(void)
{
return bL_switcher_register_notifier(&bL_switcher_notifier);
}
static int __bLs_unregister_notifier(void)
{
return bL_switcher_unregister_notifier(&bL_switcher_notifier);
}
#else
static int __bLs_register_notifier(void) { return 0; }
static int __bLs_unregister_notifier(void) { return 0; }
#endif
int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
{ {
int ret, i; int ret, i;
...@@ -555,8 +580,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) ...@@ -555,8 +580,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
arm_bL_ops = ops; arm_bL_ops = ops;
ret = bL_switcher_get_enabled(); set_switching_enabled(bL_switcher_get_enabled());
set_switching_enabled(ret);
for (i = 0; i < MAX_CLUSTERS; i++) for (i = 0; i < MAX_CLUSTERS; i++)
mutex_init(&cluster_lock[i]); mutex_init(&cluster_lock[i]);
...@@ -567,7 +591,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) ...@@ -567,7 +591,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
__func__, ops->name, ret); __func__, ops->name, ret);
arm_bL_ops = NULL; arm_bL_ops = NULL;
} else { } else {
ret = bL_switcher_register_notifier(&bL_switcher_notifier); ret = __bLs_register_notifier();
if (ret) { if (ret) {
cpufreq_unregister_driver(&bL_cpufreq_driver); cpufreq_unregister_driver(&bL_cpufreq_driver);
arm_bL_ops = NULL; arm_bL_ops = NULL;
...@@ -591,7 +615,7 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops) ...@@ -591,7 +615,7 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops)
} }
bL_switcher_get_enabled(); bL_switcher_get_enabled();
bL_switcher_unregister_notifier(&bL_switcher_notifier); __bLs_unregister_notifier();
cpufreq_unregister_driver(&bL_cpufreq_driver); cpufreq_unregister_driver(&bL_cpufreq_driver);
bL_switcher_put_enabled(); bL_switcher_put_enabled();
pr_info("%s: Un-registered platform driver: %s\n", __func__, pr_info("%s: Un-registered platform driver: %s\n", __func__,
......
...@@ -416,6 +416,7 @@ static struct platform_driver dt_cpufreq_platdrv = { ...@@ -416,6 +416,7 @@ static struct platform_driver dt_cpufreq_platdrv = {
}; };
module_platform_driver(dt_cpufreq_platdrv); module_platform_driver(dt_cpufreq_platdrv);
MODULE_ALIAS("platform:cpufreq-dt");
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
MODULE_DESCRIPTION("Generic cpufreq driver"); MODULE_DESCRIPTION("Generic cpufreq driver");
......
...@@ -414,7 +414,7 @@ static int nforce2_detect_chipset(void) ...@@ -414,7 +414,7 @@ static int nforce2_detect_chipset(void)
* nforce2_init - initializes the nForce2 CPUFreq driver * nforce2_init - initializes the nForce2 CPUFreq driver
* *
* Initializes the nForce2 FSB support. Returns -ENODEV on unsupported * Initializes the nForce2 FSB support. Returns -ENODEV on unsupported
* devices, -EINVAL on problems during initiatization, and zero on * devices, -EINVAL on problems during initialization, and zero on
* success. * success.
*/ */
static int __init nforce2_init(void) static int __init nforce2_init(void)
......
此差异已折叠。
...@@ -148,6 +148,10 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -148,6 +148,10 @@ static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
return 0; return 0;
} }
static struct notifier_block cs_cpufreq_notifier_block = {
.notifier_call = dbs_cpufreq_notifier,
};
/************************** sysfs interface ************************/ /************************** sysfs interface ************************/
static struct common_dbs_data cs_dbs_cdata; static struct common_dbs_data cs_dbs_cdata;
...@@ -317,7 +321,7 @@ static struct attribute_group cs_attr_group_gov_pol = { ...@@ -317,7 +321,7 @@ static struct attribute_group cs_attr_group_gov_pol = {
/************************** sysfs end ************************/ /************************** sysfs end ************************/
static int cs_init(struct dbs_data *dbs_data) static int cs_init(struct dbs_data *dbs_data, bool notify)
{ {
struct cs_dbs_tuners *tuners; struct cs_dbs_tuners *tuners;
...@@ -336,25 +340,25 @@ static int cs_init(struct dbs_data *dbs_data) ...@@ -336,25 +340,25 @@ static int cs_init(struct dbs_data *dbs_data)
dbs_data->tuners = tuners; dbs_data->tuners = tuners;
dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
jiffies_to_usecs(10); jiffies_to_usecs(10);
mutex_init(&dbs_data->mutex);
if (notify)
cpufreq_register_notifier(&cs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
return 0; return 0;
} }
static void cs_exit(struct dbs_data *dbs_data) static void cs_exit(struct dbs_data *dbs_data, bool notify)
{ {
if (notify)
cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
kfree(dbs_data->tuners); kfree(dbs_data->tuners);
} }
define_get_cpu_dbs_routines(cs_cpu_dbs_info); define_get_cpu_dbs_routines(cs_cpu_dbs_info);
static struct notifier_block cs_cpufreq_notifier_block = {
.notifier_call = dbs_cpufreq_notifier,
};
static struct cs_ops cs_ops = {
.notifier_block = &cs_cpufreq_notifier_block,
};
static struct common_dbs_data cs_dbs_cdata = { static struct common_dbs_data cs_dbs_cdata = {
.governor = GOV_CONSERVATIVE, .governor = GOV_CONSERVATIVE,
.attr_group_gov_sys = &cs_attr_group_gov_sys, .attr_group_gov_sys = &cs_attr_group_gov_sys,
...@@ -363,9 +367,9 @@ static struct common_dbs_data cs_dbs_cdata = { ...@@ -363,9 +367,9 @@ static struct common_dbs_data cs_dbs_cdata = {
.get_cpu_dbs_info_s = get_cpu_dbs_info_s, .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
.gov_dbs_timer = cs_dbs_timer, .gov_dbs_timer = cs_dbs_timer,
.gov_check_cpu = cs_check_cpu, .gov_check_cpu = cs_check_cpu,
.gov_ops = &cs_ops,
.init = cs_init, .init = cs_init,
.exit = cs_exit, .exit = cs_exit,
.mutex = __MUTEX_INITIALIZER(cs_dbs_cdata.mutex),
}; };
static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
......
...@@ -239,211 +239,242 @@ static void set_sampling_rate(struct dbs_data *dbs_data, ...@@ -239,211 +239,242 @@ static void set_sampling_rate(struct dbs_data *dbs_data,
} }
} }
int cpufreq_governor_dbs(struct cpufreq_policy *policy, static int cpufreq_governor_init(struct cpufreq_policy *policy,
struct common_dbs_data *cdata, unsigned int event) struct dbs_data *dbs_data,
struct common_dbs_data *cdata)
{ {
struct dbs_data *dbs_data; unsigned int latency;
struct od_cpu_dbs_info_s *od_dbs_info = NULL; int ret;
struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
struct od_ops *od_ops = NULL;
struct od_dbs_tuners *od_tuners = NULL;
struct cs_dbs_tuners *cs_tuners = NULL;
struct cpu_dbs_common_info *cpu_cdbs;
unsigned int sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
int io_busy = 0;
int rc;
if (have_governor_per_policy())
dbs_data = policy->governor_data;
else
dbs_data = cdata->gdbs_data;
WARN_ON(!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT));
switch (event) {
case CPUFREQ_GOV_POLICY_INIT:
if (have_governor_per_policy()) {
WARN_ON(dbs_data);
} else if (dbs_data) {
dbs_data->usage_count++;
policy->governor_data = dbs_data;
return 0;
}
dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL);
if (!dbs_data) {
pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);
return -ENOMEM;
}
dbs_data->cdata = cdata; if (dbs_data) {
dbs_data->usage_count = 1; if (WARN_ON(have_governor_per_policy()))
rc = cdata->init(dbs_data); return -EINVAL;
if (rc) { dbs_data->usage_count++;
pr_err("%s: POLICY_INIT: init() failed\n", __func__); policy->governor_data = dbs_data;
kfree(dbs_data); return 0;
return rc; }
}
if (!have_governor_per_policy()) dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL);
WARN_ON(cpufreq_get_global_kobject()); if (!dbs_data)
return -ENOMEM;
rc = sysfs_create_group(get_governor_parent_kobj(policy), dbs_data->cdata = cdata;
get_sysfs_attr(dbs_data)); dbs_data->usage_count = 1;
if (rc) {
cdata->exit(dbs_data);
kfree(dbs_data);
return rc;
}
policy->governor_data = dbs_data; ret = cdata->init(dbs_data, !policy->governor->initialized);
if (ret)
goto free_dbs_data;
/* policy latency is in ns. Convert it to us first */ /* policy latency is in ns. Convert it to us first */
latency = policy->cpuinfo.transition_latency / 1000; latency = policy->cpuinfo.transition_latency / 1000;
if (latency == 0) if (latency == 0)
latency = 1; latency = 1;
/* Bring kernel and HW constraints together */ /* Bring kernel and HW constraints together */
dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate, dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
MIN_LATENCY_MULTIPLIER * latency); MIN_LATENCY_MULTIPLIER * latency);
set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate, set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
latency * LATENCY_MULTIPLIER)); latency * LATENCY_MULTIPLIER));
if ((cdata->governor == GOV_CONSERVATIVE) && if (!have_governor_per_policy()) {
(!policy->governor->initialized)) { if (WARN_ON(cpufreq_get_global_kobject())) {
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; ret = -EINVAL;
goto cdata_exit;
cpufreq_register_notifier(cs_ops->notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
} }
cdata->gdbs_data = dbs_data;
}
if (!have_governor_per_policy()) ret = sysfs_create_group(get_governor_parent_kobj(policy),
cdata->gdbs_data = dbs_data; get_sysfs_attr(dbs_data));
if (ret)
goto put_kobj;
return 0; policy->governor_data = dbs_data;
case CPUFREQ_GOV_POLICY_EXIT:
if (!--dbs_data->usage_count) {
sysfs_remove_group(get_governor_parent_kobj(policy),
get_sysfs_attr(dbs_data));
if (!have_governor_per_policy()) return 0;
cpufreq_put_global_kobject();
if ((dbs_data->cdata->governor == GOV_CONSERVATIVE) && put_kobj:
(policy->governor->initialized == 1)) { if (!have_governor_per_policy()) {
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; cdata->gdbs_data = NULL;
cpufreq_put_global_kobject();
}
cdata_exit:
cdata->exit(dbs_data, !policy->governor->initialized);
free_dbs_data:
kfree(dbs_data);
return ret;
}
static void cpufreq_governor_exit(struct cpufreq_policy *policy,
struct dbs_data *dbs_data)
{
struct common_dbs_data *cdata = dbs_data->cdata;
cpufreq_unregister_notifier(cs_ops->notifier_block, policy->governor_data = NULL;
CPUFREQ_TRANSITION_NOTIFIER); if (!--dbs_data->usage_count) {
} sysfs_remove_group(get_governor_parent_kobj(policy),
get_sysfs_attr(dbs_data));
cdata->exit(dbs_data); if (!have_governor_per_policy()) {
kfree(dbs_data);
cdata->gdbs_data = NULL; cdata->gdbs_data = NULL;
cpufreq_put_global_kobject();
} }
policy->governor_data = NULL; cdata->exit(dbs_data, policy->governor->initialized == 1);
return 0; kfree(dbs_data);
} }
}
cpu_cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); static int cpufreq_governor_start(struct cpufreq_policy *policy,
struct dbs_data *dbs_data)
{
struct common_dbs_data *cdata = dbs_data->cdata;
unsigned int sampling_rate, ignore_nice, j, cpu = policy->cpu;
struct cpu_dbs_common_info *cpu_cdbs = cdata->get_cpu_cdbs(cpu);
int io_busy = 0;
if (!policy->cur)
return -EINVAL;
if (cdata->governor == GOV_CONSERVATIVE) {
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
cs_tuners = dbs_data->tuners;
cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
sampling_rate = cs_tuners->sampling_rate; sampling_rate = cs_tuners->sampling_rate;
ignore_nice = cs_tuners->ignore_nice_load; ignore_nice = cs_tuners->ignore_nice_load;
} else { } else {
od_tuners = dbs_data->tuners; struct od_dbs_tuners *od_tuners = dbs_data->tuners;
od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu);
sampling_rate = od_tuners->sampling_rate; sampling_rate = od_tuners->sampling_rate;
ignore_nice = od_tuners->ignore_nice_load; ignore_nice = od_tuners->ignore_nice_load;
od_ops = dbs_data->cdata->gov_ops;
io_busy = od_tuners->io_is_busy; io_busy = od_tuners->io_is_busy;
} }
switch (event) { for_each_cpu(j, policy->cpus) {
case CPUFREQ_GOV_START: struct cpu_dbs_common_info *j_cdbs = cdata->get_cpu_cdbs(j);
if (!policy->cur) unsigned int prev_load;
return -EINVAL;
mutex_lock(&dbs_data->mutex); j_cdbs->cpu = j;
j_cdbs->cur_policy = policy;
j_cdbs->prev_cpu_idle =
get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall, io_busy);
for_each_cpu(j, policy->cpus) { prev_load = (unsigned int)(j_cdbs->prev_cpu_wall -
struct cpu_dbs_common_info *j_cdbs = j_cdbs->prev_cpu_idle);
dbs_data->cdata->get_cpu_cdbs(j); j_cdbs->prev_load = 100 * prev_load /
unsigned int prev_load; (unsigned int)j_cdbs->prev_cpu_wall;
j_cdbs->cpu = j; if (ignore_nice)
j_cdbs->cur_policy = policy; j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
&j_cdbs->prev_cpu_wall, io_busy);
prev_load = (unsigned int) mutex_init(&j_cdbs->timer_mutex);
(j_cdbs->prev_cpu_wall - j_cdbs->prev_cpu_idle); INIT_DEFERRABLE_WORK(&j_cdbs->work, cdata->gov_dbs_timer);
j_cdbs->prev_load = 100 * prev_load / }
(unsigned int) j_cdbs->prev_cpu_wall;
if (ignore_nice) if (cdata->governor == GOV_CONSERVATIVE) {
j_cdbs->prev_cpu_nice = struct cs_cpu_dbs_info_s *cs_dbs_info =
kcpustat_cpu(j).cpustat[CPUTIME_NICE]; cdata->get_cpu_dbs_info_s(cpu);
mutex_init(&j_cdbs->timer_mutex); cs_dbs_info->down_skip = 0;
INIT_DEFERRABLE_WORK(&j_cdbs->work, cs_dbs_info->enable = 1;
dbs_data->cdata->gov_dbs_timer); cs_dbs_info->requested_freq = policy->cur;
} } else {
struct od_ops *od_ops = cdata->gov_ops;
struct od_cpu_dbs_info_s *od_dbs_info = cdata->get_cpu_dbs_info_s(cpu);
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { od_dbs_info->rate_mult = 1;
cs_dbs_info->down_skip = 0; od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
cs_dbs_info->enable = 1; od_ops->powersave_bias_init_cpu(cpu);
cs_dbs_info->requested_freq = policy->cur; }
} else {
od_dbs_info->rate_mult = 1;
od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
od_ops->powersave_bias_init_cpu(cpu);
}
mutex_unlock(&dbs_data->mutex); /* Initiate timer time stamp */
cpu_cdbs->time_stamp = ktime_get();
/* Initiate timer time stamp */ gov_queue_work(dbs_data, policy, delay_for_sampling_rate(sampling_rate),
cpu_cdbs->time_stamp = ktime_get(); true);
return 0;
}
gov_queue_work(dbs_data, policy, static void cpufreq_governor_stop(struct cpufreq_policy *policy,
delay_for_sampling_rate(sampling_rate), true); struct dbs_data *dbs_data)
break; {
struct common_dbs_data *cdata = dbs_data->cdata;
unsigned int cpu = policy->cpu;
struct cpu_dbs_common_info *cpu_cdbs = cdata->get_cpu_cdbs(cpu);
case CPUFREQ_GOV_STOP: if (cdata->governor == GOV_CONSERVATIVE) {
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) struct cs_cpu_dbs_info_s *cs_dbs_info =
cs_dbs_info->enable = 0; cdata->get_cpu_dbs_info_s(cpu);
gov_cancel_work(dbs_data, policy); cs_dbs_info->enable = 0;
}
mutex_lock(&dbs_data->mutex); gov_cancel_work(dbs_data, policy);
mutex_destroy(&cpu_cdbs->timer_mutex);
cpu_cdbs->cur_policy = NULL;
mutex_unlock(&dbs_data->mutex); mutex_destroy(&cpu_cdbs->timer_mutex);
cpu_cdbs->cur_policy = NULL;
}
break; static void cpufreq_governor_limits(struct cpufreq_policy *policy,
struct dbs_data *dbs_data)
{
struct common_dbs_data *cdata = dbs_data->cdata;
unsigned int cpu = policy->cpu;
struct cpu_dbs_common_info *cpu_cdbs = cdata->get_cpu_cdbs(cpu);
if (!cpu_cdbs->cur_policy)
return;
mutex_lock(&cpu_cdbs->timer_mutex);
if (policy->max < cpu_cdbs->cur_policy->cur)
__cpufreq_driver_target(cpu_cdbs->cur_policy, policy->max,
CPUFREQ_RELATION_H);
else if (policy->min > cpu_cdbs->cur_policy->cur)
__cpufreq_driver_target(cpu_cdbs->cur_policy, policy->min,
CPUFREQ_RELATION_L);
dbs_check_cpu(dbs_data, cpu);
mutex_unlock(&cpu_cdbs->timer_mutex);
}
int cpufreq_governor_dbs(struct cpufreq_policy *policy,
struct common_dbs_data *cdata, unsigned int event)
{
struct dbs_data *dbs_data;
int ret = 0;
/* Lock governor to block concurrent initialization of governor */
mutex_lock(&cdata->mutex);
if (have_governor_per_policy())
dbs_data = policy->governor_data;
else
dbs_data = cdata->gdbs_data;
if (WARN_ON(!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT))) {
ret = -EINVAL;
goto unlock;
}
switch (event) {
case CPUFREQ_GOV_POLICY_INIT:
ret = cpufreq_governor_init(policy, dbs_data, cdata);
break;
case CPUFREQ_GOV_POLICY_EXIT:
cpufreq_governor_exit(policy, dbs_data);
break;
case CPUFREQ_GOV_START:
ret = cpufreq_governor_start(policy, dbs_data);
break;
case CPUFREQ_GOV_STOP:
cpufreq_governor_stop(policy, dbs_data);
break;
case CPUFREQ_GOV_LIMITS: case CPUFREQ_GOV_LIMITS:
mutex_lock(&dbs_data->mutex); cpufreq_governor_limits(policy, dbs_data);
if (!cpu_cdbs->cur_policy) {
mutex_unlock(&dbs_data->mutex);
break;
}
mutex_lock(&cpu_cdbs->timer_mutex);
if (policy->max < cpu_cdbs->cur_policy->cur)
__cpufreq_driver_target(cpu_cdbs->cur_policy,
policy->max, CPUFREQ_RELATION_H);
else if (policy->min > cpu_cdbs->cur_policy->cur)
__cpufreq_driver_target(cpu_cdbs->cur_policy,
policy->min, CPUFREQ_RELATION_L);
dbs_check_cpu(dbs_data, cpu);
mutex_unlock(&cpu_cdbs->timer_mutex);
mutex_unlock(&dbs_data->mutex);
break; break;
} }
return 0;
unlock:
mutex_unlock(&cdata->mutex);
return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_governor_dbs); EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
...@@ -208,11 +208,16 @@ struct common_dbs_data { ...@@ -208,11 +208,16 @@ struct common_dbs_data {
void *(*get_cpu_dbs_info_s)(int cpu); void *(*get_cpu_dbs_info_s)(int cpu);
void (*gov_dbs_timer)(struct work_struct *work); void (*gov_dbs_timer)(struct work_struct *work);
void (*gov_check_cpu)(int cpu, unsigned int load); void (*gov_check_cpu)(int cpu, unsigned int load);
int (*init)(struct dbs_data *dbs_data); int (*init)(struct dbs_data *dbs_data, bool notify);
void (*exit)(struct dbs_data *dbs_data); void (*exit)(struct dbs_data *dbs_data, bool notify);
/* Governor specific ops, see below */ /* Governor specific ops, see below */
void *gov_ops; void *gov_ops;
/*
* Protects governor's data (struct dbs_data and struct common_dbs_data)
*/
struct mutex mutex;
}; };
/* Governor Per policy data */ /* Governor Per policy data */
...@@ -221,9 +226,6 @@ struct dbs_data { ...@@ -221,9 +226,6 @@ struct dbs_data {
unsigned int min_sampling_rate; unsigned int min_sampling_rate;
int usage_count; int usage_count;
void *tuners; void *tuners;
/* dbs_mutex protects dbs_enable in governor start/stop */
struct mutex mutex;
}; };
/* Governor specific ops, will be passed to dbs_data->gov_ops */ /* Governor specific ops, will be passed to dbs_data->gov_ops */
...@@ -234,10 +236,6 @@ struct od_ops { ...@@ -234,10 +236,6 @@ struct od_ops {
void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq); void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq);
}; };
struct cs_ops {
struct notifier_block *notifier_block;
};
static inline int delay_for_sampling_rate(unsigned int sampling_rate) static inline int delay_for_sampling_rate(unsigned int sampling_rate)
{ {
int delay = usecs_to_jiffies(sampling_rate); int delay = usecs_to_jiffies(sampling_rate);
......
...@@ -475,7 +475,7 @@ static struct attribute_group od_attr_group_gov_pol = { ...@@ -475,7 +475,7 @@ static struct attribute_group od_attr_group_gov_pol = {
/************************** sysfs end ************************/ /************************** sysfs end ************************/
static int od_init(struct dbs_data *dbs_data) static int od_init(struct dbs_data *dbs_data, bool notify)
{ {
struct od_dbs_tuners *tuners; struct od_dbs_tuners *tuners;
u64 idle_time; u64 idle_time;
...@@ -513,11 +513,10 @@ static int od_init(struct dbs_data *dbs_data) ...@@ -513,11 +513,10 @@ static int od_init(struct dbs_data *dbs_data)
tuners->io_is_busy = should_io_be_busy(); tuners->io_is_busy = should_io_be_busy();
dbs_data->tuners = tuners; dbs_data->tuners = tuners;
mutex_init(&dbs_data->mutex);
return 0; return 0;
} }
static void od_exit(struct dbs_data *dbs_data) static void od_exit(struct dbs_data *dbs_data, bool notify)
{ {
kfree(dbs_data->tuners); kfree(dbs_data->tuners);
} }
...@@ -541,6 +540,7 @@ static struct common_dbs_data od_dbs_cdata = { ...@@ -541,6 +540,7 @@ static struct common_dbs_data od_dbs_cdata = {
.gov_ops = &od_ops, .gov_ops = &od_ops,
.init = od_init, .init = od_init,
.exit = od_exit, .exit = od_exit,
.mutex = __MUTEX_INITIALIZER(od_dbs_cdata.mutex),
}; };
static void od_set_powersave_bias(unsigned int powersave_bias) static void od_set_powersave_bias(unsigned int powersave_bias)
......
...@@ -144,7 +144,7 @@ module_param(max_duration, int, 0444); ...@@ -144,7 +144,7 @@ module_param(max_duration, int, 0444);
/** /**
* we can detect a core multipiler from dir0_lsb * we can detect a core multiplier from dir0_lsb
* from GX1 datasheet p.56, * from GX1 datasheet p.56,
* MULT[3:0]: * MULT[3:0]:
* 0000 = SYSCLK multiplied by 4 (test only) * 0000 = SYSCLK multiplied by 4 (test only)
...@@ -346,7 +346,7 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy) ...@@ -346,7 +346,7 @@ static int cpufreq_gx_verify(struct cpufreq_policy *policy)
/* it needs to be assured that at least one supported frequency is /* it needs to be assured that at least one supported frequency is
* within policy->min and policy->max. If it is not, policy->max * within policy->min and policy->max. If it is not, policy->max
* needs to be increased until one freuqency is supported. * needs to be increased until one frequency is supported.
* policy->min may not be decreased, though. This way we guarantee a * policy->min may not be decreased, though. This way we guarantee a
* specific processing capacity. * specific processing capacity.
*/ */
......
...@@ -48,9 +48,9 @@ static inline int32_t mul_fp(int32_t x, int32_t y) ...@@ -48,9 +48,9 @@ static inline int32_t mul_fp(int32_t x, int32_t y)
return ((int64_t)x * (int64_t)y) >> FRAC_BITS; return ((int64_t)x * (int64_t)y) >> FRAC_BITS;
} }
static inline int32_t div_fp(int32_t x, int32_t y) static inline int32_t div_fp(s64 x, s64 y)
{ {
return div_s64((int64_t)x << FRAC_BITS, y); return div64_s64((int64_t)x << FRAC_BITS, y);
} }
static inline int ceiling_fp(int32_t x) static inline int ceiling_fp(int32_t x)
...@@ -68,6 +68,7 @@ struct sample { ...@@ -68,6 +68,7 @@ struct sample {
int32_t core_pct_busy; int32_t core_pct_busy;
u64 aperf; u64 aperf;
u64 mperf; u64 mperf;
u64 tsc;
int freq; int freq;
ktime_t time; ktime_t time;
}; };
...@@ -109,6 +110,7 @@ struct cpudata { ...@@ -109,6 +110,7 @@ struct cpudata {
ktime_t last_sample_time; ktime_t last_sample_time;
u64 prev_aperf; u64 prev_aperf;
u64 prev_mperf; u64 prev_mperf;
u64 prev_tsc;
struct sample sample; struct sample sample;
}; };
...@@ -396,7 +398,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, ...@@ -396,7 +398,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
update_turbo_state(); update_turbo_state();
if (limits.turbo_disabled) { if (limits.turbo_disabled) {
pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); pr_warn("intel_pstate: Turbo disabled by BIOS or unavailable on processor\n");
return -EPERM; return -EPERM;
} }
...@@ -484,7 +486,7 @@ static void __init intel_pstate_sysfs_expose_params(void) ...@@ -484,7 +486,7 @@ static void __init intel_pstate_sysfs_expose_params(void)
static void intel_pstate_hwp_enable(void) static void intel_pstate_hwp_enable(void)
{ {
hwp_active++; hwp_active++;
pr_info("intel_pstate HWP enabled\n"); pr_info("intel_pstate: HWP enabled\n");
wrmsrl( MSR_PM_ENABLE, 0x1); wrmsrl( MSR_PM_ENABLE, 0x1);
} }
...@@ -535,7 +537,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) ...@@ -535,7 +537,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
val |= vid; val |= vid;
wrmsrl(MSR_IA32_PERF_CTL, val); wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
} }
#define BYT_BCLK_FREQS 5 #define BYT_BCLK_FREQS 5
...@@ -704,19 +706,20 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max) ...@@ -704,19 +706,20 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf); *min = clamp_t(int, min_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, bool force)
{ {
int max_perf, min_perf; int max_perf, min_perf;
update_turbo_state(); if (force) {
update_turbo_state();
intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
pstate = clamp_t(int, pstate, min_perf, max_perf); intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
if (pstate == cpu->pstate.current_pstate) pstate = clamp_t(int, pstate, min_perf, max_perf);
return;
if (pstate == cpu->pstate.current_pstate)
return;
}
trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
cpu->pstate.current_pstate = pstate; cpu->pstate.current_pstate = pstate;
...@@ -733,7 +736,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) ...@@ -733,7 +736,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
if (pstate_funcs.get_vid) if (pstate_funcs.get_vid)
pstate_funcs.get_vid(cpu); pstate_funcs.get_vid(cpu);
intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate, false);
} }
static inline void intel_pstate_calc_busy(struct cpudata *cpu) static inline void intel_pstate_calc_busy(struct cpudata *cpu)
...@@ -756,23 +759,28 @@ static inline void intel_pstate_sample(struct cpudata *cpu) ...@@ -756,23 +759,28 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
{ {
u64 aperf, mperf; u64 aperf, mperf;
unsigned long flags; unsigned long flags;
u64 tsc;
local_irq_save(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);
tsc = native_read_tsc();
local_irq_restore(flags); local_irq_restore(flags);
cpu->last_sample_time = cpu->sample.time; cpu->last_sample_time = cpu->sample.time;
cpu->sample.time = ktime_get(); cpu->sample.time = ktime_get();
cpu->sample.aperf = aperf; cpu->sample.aperf = aperf;
cpu->sample.mperf = mperf; cpu->sample.mperf = mperf;
cpu->sample.tsc = tsc;
cpu->sample.aperf -= cpu->prev_aperf; cpu->sample.aperf -= cpu->prev_aperf;
cpu->sample.mperf -= cpu->prev_mperf; cpu->sample.mperf -= cpu->prev_mperf;
cpu->sample.tsc -= cpu->prev_tsc;
intel_pstate_calc_busy(cpu); intel_pstate_calc_busy(cpu);
cpu->prev_aperf = aperf; cpu->prev_aperf = aperf;
cpu->prev_mperf = mperf; cpu->prev_mperf = mperf;
cpu->prev_tsc = tsc;
} }
static inline void intel_hwp_set_sample_time(struct cpudata *cpu) static inline void intel_hwp_set_sample_time(struct cpudata *cpu)
...@@ -794,7 +802,7 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) ...@@ -794,7 +802,7 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
{ {
int32_t core_busy, max_pstate, current_pstate, sample_ratio; int32_t core_busy, max_pstate, current_pstate, sample_ratio;
u32 duration_us; s64 duration_us;
u32 sample_time; u32 sample_time;
/* /*
...@@ -821,8 +829,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) ...@@ -821,8 +829,8 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
* to adjust our busyness. * to adjust our busyness.
*/ */
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 = 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));
...@@ -837,6 +845,10 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) ...@@ -837,6 +845,10 @@ 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; signed int ctl;
int from;
struct sample *sample;
from = cpu->pstate.current_pstate;
pid = &cpu->pid; pid = &cpu->pid;
busy_scaled = intel_pstate_get_scaled_busy(cpu); busy_scaled = intel_pstate_get_scaled_busy(cpu);
...@@ -844,7 +856,17 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) ...@@ -844,7 +856,17 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
ctl = pid_calc(pid, busy_scaled); ctl = pid_calc(pid, busy_scaled);
/* Negative values of ctl increase the pstate and vice versa */ /* Negative values of ctl increase the pstate and vice versa */
intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl); intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl, true);
sample = &cpu->sample;
trace_pstate_sample(fp_toint(sample->core_pct_busy),
fp_toint(busy_scaled),
from,
cpu->pstate.current_pstate,
sample->mperf,
sample->aperf,
sample->tsc,
sample->freq);
} }
static void intel_hwp_timer_func(unsigned long __data) static void intel_hwp_timer_func(unsigned long __data)
...@@ -858,21 +880,11 @@ static void intel_hwp_timer_func(unsigned long __data) ...@@ -858,21 +880,11 @@ static void intel_hwp_timer_func(unsigned long __data)
static void intel_pstate_timer_func(unsigned long __data) static void intel_pstate_timer_func(unsigned long __data)
{ {
struct cpudata *cpu = (struct cpudata *) __data; struct cpudata *cpu = (struct cpudata *) __data;
struct sample *sample;
intel_pstate_sample(cpu); intel_pstate_sample(cpu);
sample = &cpu->sample;
intel_pstate_adjust_busy_pstate(cpu); intel_pstate_adjust_busy_pstate(cpu);
trace_pstate_sample(fp_toint(sample->core_pct_busy),
fp_toint(intel_pstate_get_scaled_busy(cpu)),
cpu->pstate.current_pstate,
sample->mperf,
sample->aperf,
sample->freq);
intel_pstate_set_sample_time(cpu); intel_pstate_set_sample_time(cpu);
} }
...@@ -935,7 +947,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum) ...@@ -935,7 +947,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
add_timer_on(&cpu->timer, cpunum); add_timer_on(&cpu->timer, cpunum);
pr_debug("Intel pstate controlling: cpu %d\n", cpunum); pr_debug("intel_pstate: controlling: cpu %d\n", cpunum);
return 0; return 0;
} }
...@@ -1001,13 +1013,13 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy) ...@@ -1001,13 +1013,13 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
int cpu_num = policy->cpu; int cpu_num = policy->cpu;
struct cpudata *cpu = all_cpu_data[cpu_num]; struct cpudata *cpu = all_cpu_data[cpu_num];
pr_info("intel_pstate CPU %d exiting\n", cpu_num); pr_debug("intel_pstate: CPU %d exiting\n", cpu_num);
del_timer_sync(&all_cpu_data[cpu_num]->timer); del_timer_sync(&all_cpu_data[cpu_num]->timer);
if (hwp_active) if (hwp_active)
return; return;
intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate); intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate, false);
} }
static int intel_pstate_cpu_init(struct cpufreq_policy *policy) static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
......
...@@ -56,7 +56,7 @@ module_param(pxa27x_maxfreq, uint, 0); ...@@ -56,7 +56,7 @@ module_param(pxa27x_maxfreq, uint, 0);
MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz" MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"
"(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)"); "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)");
typedef struct { struct pxa_freqs {
unsigned int khz; unsigned int khz;
unsigned int membus; unsigned int membus;
unsigned int cccr; unsigned int cccr;
...@@ -64,7 +64,7 @@ typedef struct { ...@@ -64,7 +64,7 @@ typedef struct {
unsigned int cclkcfg; unsigned int cclkcfg;
int vmin; int vmin;
int vmax; int vmax;
} pxa_freqs_t; };
/* Define the refresh period in mSec for the SDRAM and the number of rows */ /* Define the refresh period in mSec for the SDRAM and the number of rows */
#define SDRAM_TREF 64 /* standard 64ms SDRAM */ #define SDRAM_TREF 64 /* standard 64ms SDRAM */
...@@ -86,7 +86,7 @@ static unsigned int sdram_rows; ...@@ -86,7 +86,7 @@ static unsigned int sdram_rows;
/* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ /* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */
#define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS #define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS
static pxa_freqs_t pxa255_run_freqs[] = static const struct pxa_freqs pxa255_run_freqs[] =
{ {
/* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */
{ 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */
...@@ -98,7 +98,7 @@ static pxa_freqs_t pxa255_run_freqs[] = ...@@ -98,7 +98,7 @@ static pxa_freqs_t pxa255_run_freqs[] =
}; };
/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
static pxa_freqs_t pxa255_turbo_freqs[] = static const struct pxa_freqs pxa255_turbo_freqs[] =
{ {
/* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */
{ 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */
...@@ -153,7 +153,7 @@ MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table ...@@ -153,7 +153,7 @@ MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table
((HT) ? CCLKCFG_HALFTURBO : 0) | \ ((HT) ? CCLKCFG_HALFTURBO : 0) | \
((T) ? CCLKCFG_TURBO : 0)) ((T) ? CCLKCFG_TURBO : 0))
static pxa_freqs_t pxa27x_freqs[] = { static struct pxa_freqs pxa27x_freqs[] = {
{104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 }, {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 },
{156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 }, {156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 },
{208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 }, {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
...@@ -171,7 +171,7 @@ extern unsigned get_clk_frequency_khz(int info); ...@@ -171,7 +171,7 @@ extern unsigned get_clk_frequency_khz(int info);
#ifdef CONFIG_REGULATOR #ifdef CONFIG_REGULATOR
static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq)
{ {
int ret = 0; int ret = 0;
int vmin, vmax; int vmin, vmax;
...@@ -202,7 +202,7 @@ static void __init pxa_cpufreq_init_voltages(void) ...@@ -202,7 +202,7 @@ static void __init pxa_cpufreq_init_voltages(void)
} }
} }
#else #else
static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) static int pxa_cpufreq_change_voltage(struct pxa_freqs *pxa_freq)
{ {
return 0; return 0;
} }
...@@ -211,7 +211,7 @@ static void __init pxa_cpufreq_init_voltages(void) { } ...@@ -211,7 +211,7 @@ static void __init pxa_cpufreq_init_voltages(void) { }
#endif #endif
static void find_freq_tables(struct cpufreq_frequency_table **freq_table, static void find_freq_tables(struct cpufreq_frequency_table **freq_table,
pxa_freqs_t **pxa_freqs) const struct pxa_freqs **pxa_freqs)
{ {
if (cpu_is_pxa25x()) { if (cpu_is_pxa25x()) {
if (!pxa255_turbo_table) { if (!pxa255_turbo_table) {
...@@ -270,7 +270,7 @@ static unsigned int pxa_cpufreq_get(unsigned int cpu) ...@@ -270,7 +270,7 @@ static unsigned int pxa_cpufreq_get(unsigned int cpu)
static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)
{ {
struct cpufreq_frequency_table *pxa_freqs_table; struct cpufreq_frequency_table *pxa_freqs_table;
pxa_freqs_t *pxa_freq_settings; const struct pxa_freqs *pxa_freq_settings;
unsigned long flags; unsigned long flags;
unsigned int new_freq_cpu, new_freq_mem; unsigned int new_freq_cpu, new_freq_mem;
unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
...@@ -361,7 +361,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) ...@@ -361,7 +361,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
int i; int i;
unsigned int freq; unsigned int freq;
struct cpufreq_frequency_table *pxa255_freq_table; struct cpufreq_frequency_table *pxa255_freq_table;
pxa_freqs_t *pxa255_freqs; const struct pxa_freqs *pxa255_freqs;
/* try to guess pxa27x cpu */ /* try to guess pxa27x cpu */
if (cpu_is_pxa27x()) if (cpu_is_pxa27x())
......
...@@ -27,11 +27,11 @@ ...@@ -27,11 +27,11 @@
/** /**
* struct cpu_data * struct cpu_data
* @parent: the parent node of cpu clock * @pclk: the parent clock of cpu
* @table: frequency table * @table: frequency table
*/ */
struct cpu_data { struct cpu_data {
struct device_node *parent; struct clk **pclk;
struct cpufreq_frequency_table *table; struct cpufreq_frequency_table *table;
}; };
...@@ -196,7 +196,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, ...@@ -196,7 +196,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
{ {
struct device_node *np; struct device_node *np, *pnode;
int i, count, ret; int i, count, ret;
u32 freq, mask; u32 freq, mask;
struct clk *clk; struct clk *clk;
...@@ -219,17 +219,23 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -219,17 +219,23 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
goto err_nomem2; goto err_nomem2;
} }
data->parent = of_parse_phandle(np, "clocks", 0); pnode = of_parse_phandle(np, "clocks", 0);
if (!data->parent) { if (!pnode) {
pr_err("%s: could not get clock information\n", __func__); pr_err("%s: could not get clock information\n", __func__);
goto err_nomem2; goto err_nomem2;
} }
count = of_property_count_strings(data->parent, "clock-names"); count = of_property_count_strings(pnode, "clock-names");
data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
if (!data->pclk) {
pr_err("%s: no memory\n", __func__);
goto err_node;
}
table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
if (!table) { if (!table) {
pr_err("%s: no memory\n", __func__); pr_err("%s: no memory\n", __func__);
goto err_node; goto err_pclk;
} }
if (fmask) if (fmask)
...@@ -238,7 +244,8 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -238,7 +244,8 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
mask = 0x0; mask = 0x0;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
clk = of_clk_get(data->parent, i); clk = of_clk_get(pnode, i);
data->pclk[i] = clk;
freq = clk_get_rate(clk); freq = clk_get_rate(clk);
/* /*
* the clock is valid if its frequency is not masked * the clock is valid if its frequency is not masked
...@@ -273,13 +280,16 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -273,13 +280,16 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = u64temp + 1; policy->cpuinfo.transition_latency = u64temp + 1;
of_node_put(np); of_node_put(np);
of_node_put(pnode);
return 0; return 0;
err_nomem1: err_nomem1:
kfree(table); kfree(table);
err_pclk:
kfree(data->pclk);
err_node: err_node:
of_node_put(data->parent); of_node_put(pnode);
err_nomem2: err_nomem2:
policy->driver_data = NULL; policy->driver_data = NULL;
kfree(data); kfree(data);
...@@ -293,7 +303,7 @@ static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -293,7 +303,7 @@ static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{ {
struct cpu_data *data = policy->driver_data; struct cpu_data *data = policy->driver_data;
of_node_put(data->parent); kfree(data->pclk);
kfree(data->table); kfree(data->table);
kfree(data); kfree(data);
policy->driver_data = NULL; policy->driver_data = NULL;
...@@ -307,7 +317,7 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, ...@@ -307,7 +317,7 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
struct clk *parent; struct clk *parent;
struct cpu_data *data = policy->driver_data; struct cpu_data *data = policy->driver_data;
parent = of_clk_get(data->parent, data->table[index].driver_data); parent = data->pclk[data->table[index].driver_data];
return clk_set_parent(policy->clk, parent); return clk_set_parent(policy->clk, parent);
} }
......
...@@ -65,7 +65,9 @@ struct cpufreq_policy { ...@@ -65,7 +65,9 @@ struct cpufreq_policy {
unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs
should set cpufreq */ should set cpufreq */
unsigned int cpu; /* cpu nr of CPU managing this policy */ unsigned int cpu; /* cpu managing this policy, must be online */
unsigned int kobj_cpu; /* cpu managing sysfs files, can be offline */
struct clk *clk; struct clk *clk;
struct cpufreq_cpuinfo cpuinfo;/* see above */ struct cpufreq_cpuinfo cpuinfo;/* see above */
...@@ -80,6 +82,7 @@ struct cpufreq_policy { ...@@ -80,6 +82,7 @@ struct cpufreq_policy {
struct cpufreq_governor *governor; /* see below */ struct cpufreq_governor *governor; /* see below */
void *governor_data; void *governor_data;
bool governor_enabled; /* governor start/stop flag */ bool governor_enabled; /* governor start/stop flag */
char last_governor[CPUFREQ_NAME_LEN]; /* last governor used */
struct work_struct update; /* if update_policy() needs to be struct work_struct update; /* if update_policy() needs to be
* called, but you're in IRQ context */ * called, but you're in IRQ context */
......
...@@ -42,45 +42,54 @@ TRACE_EVENT(pstate_sample, ...@@ -42,45 +42,54 @@ TRACE_EVENT(pstate_sample,
TP_PROTO(u32 core_busy, TP_PROTO(u32 core_busy,
u32 scaled_busy, u32 scaled_busy,
u32 state, u32 from,
u32 to,
u64 mperf, u64 mperf,
u64 aperf, u64 aperf,
u64 tsc,
u32 freq u32 freq
), ),
TP_ARGS(core_busy, TP_ARGS(core_busy,
scaled_busy, scaled_busy,
state, from,
to,
mperf, mperf,
aperf, aperf,
tsc,
freq freq
), ),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(u32, core_busy) __field(u32, core_busy)
__field(u32, scaled_busy) __field(u32, scaled_busy)
__field(u32, state) __field(u32, from)
__field(u32, to)
__field(u64, mperf) __field(u64, mperf)
__field(u64, aperf) __field(u64, aperf)
__field(u64, tsc)
__field(u32, freq) __field(u32, freq)
),
),
TP_fast_assign( TP_fast_assign(
__entry->core_busy = core_busy; __entry->core_busy = core_busy;
__entry->scaled_busy = scaled_busy; __entry->scaled_busy = scaled_busy;
__entry->state = state; __entry->from = from;
__entry->to = to;
__entry->mperf = mperf; __entry->mperf = mperf;
__entry->aperf = aperf; __entry->aperf = aperf;
__entry->tsc = tsc;
__entry->freq = freq; __entry->freq = freq;
), ),
TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu freq=%lu ", TP_printk("core_busy=%lu scaled=%lu from=%lu to=%lu mperf=%llu aperf=%llu tsc=%llu freq=%lu ",
(unsigned long)__entry->core_busy, (unsigned long)__entry->core_busy,
(unsigned long)__entry->scaled_busy, (unsigned long)__entry->scaled_busy,
(unsigned long)__entry->state, (unsigned long)__entry->from,
(unsigned long)__entry->to,
(unsigned long long)__entry->mperf, (unsigned long long)__entry->mperf,
(unsigned long long)__entry->aperf, (unsigned long long)__entry->aperf,
(unsigned long long)__entry->tsc,
(unsigned long)__entry->freq (unsigned long)__entry->freq
) )
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部