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

Merge back earlier cpufreq changes for v4.8.

parents 5edb5649 f6709b8a
...@@ -96,7 +96,7 @@ new - new frequency ...@@ -96,7 +96,7 @@ new - new frequency
For details about OPP, see Documentation/power/opp.txt For details about OPP, see Documentation/power/opp.txt
dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
cpufreq_frequency_table_cpuinfo which is provided with the list of cpufreq_table_validate_and_show() which is provided with the list of
frequencies that are available for operation. This function provides frequencies that are available for operation. This function provides
a ready to use conversion routine to translate the OPP layer's internal a ready to use conversion routine to translate the OPP layer's internal
information about the available frequencies into a format readily information about the available frequencies into a format readily
...@@ -110,7 +110,7 @@ dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with ...@@ -110,7 +110,7 @@ dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
/* Do things */ /* Do things */
r = dev_pm_opp_init_cpufreq_table(dev, &freq_table); r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
if (!r) if (!r)
cpufreq_frequency_table_cpuinfo(policy, freq_table); cpufreq_table_validate_and_show(policy, freq_table);
/* Do other things */ /* Do other things */
} }
......
...@@ -231,7 +231,7 @@ if you want to skip one entry in the table, set the frequency to ...@@ -231,7 +231,7 @@ if you want to skip one entry in the table, set the frequency to
CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending CPUFREQ_ENTRY_INVALID. The entries don't need to be in ascending
order. order.
By calling cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, By calling cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table); struct cpufreq_frequency_table *table);
the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and the cpuinfo.min_freq and cpuinfo.max_freq values are detected, and
policy->min and policy->max are set to the same values. This is policy->min and policy->max are set to the same values. This is
...@@ -244,14 +244,12 @@ policy->max, and all other criteria are met. This is helpful for the ...@@ -244,14 +244,12 @@ policy->max, and all other criteria are met. This is helpful for the
->verify call. ->verify call.
int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation, unsigned int relation);
unsigned int *index);
is the corresponding frequency table helper for the ->target is the corresponding frequency table helper for the ->target
stage. Just pass the values to this function, and the unsigned int stage. Just pass the values to this function, and this function
index returns the number of the frequency table entry which contains returns the number of the frequency table entry which contains
the frequency the CPU shall be set to. the frequency the CPU shall be set to.
The following macros can be used as iterators over cpufreq_frequency_table: The following macros can be used as iterators over cpufreq_frequency_table:
......
...@@ -85,27 +85,21 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info) ...@@ -85,27 +85,21 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
cancel_delayed_work_sync(&info->work); cancel_delayed_work_sync(&info->work);
} }
static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) static int spu_gov_start(struct cpufreq_policy *policy)
{ {
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct spu_gov_info_struct *info, *affected_info; struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
struct spu_gov_info_struct *affected_info;
int i; int i;
int ret = 0;
info = &per_cpu(spu_gov_info, cpu);
switch (event) {
case CPUFREQ_GOV_START:
if (!cpu_online(cpu)) { if (!cpu_online(cpu)) {
printk(KERN_ERR "cpu %d is not online\n", cpu); printk(KERN_ERR "cpu %d is not online\n", cpu);
ret = -EINVAL; return -EINVAL;
break;
} }
if (!policy->cur) { if (!policy->cur) {
printk(KERN_ERR "no cpu specified in policy\n"); printk(KERN_ERR "no cpu specified in policy\n");
ret = -EINVAL; return -EINVAL;
break;
} }
/* initialize spu_gov_info for all affected cpus */ /* initialize spu_gov_info for all affected cpus */
...@@ -119,9 +113,15 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) ...@@ -119,9 +113,15 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
/* setup timer */ /* setup timer */
spu_gov_init_work(info); spu_gov_init_work(info);
break; return 0;
}
static void spu_gov_stop(struct cpufreq_policy *policy)
{
unsigned int cpu = policy->cpu;
struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
int i;
case CPUFREQ_GOV_STOP:
/* cancel timer */ /* cancel timer */
spu_gov_cancel_work(info); spu_gov_cancel_work(info);
...@@ -130,16 +130,12 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) ...@@ -130,16 +130,12 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
info = &per_cpu(spu_gov_info, i); info = &per_cpu(spu_gov_info, i);
info->policy = NULL; info->policy = NULL;
} }
break;
}
return ret;
} }
static struct cpufreq_governor spu_governor = { static struct cpufreq_governor spu_governor = {
.name = "spudemand", .name = "spudemand",
.governor = spu_gov_govern, .start = spu_gov_start,
.stop = spu_gov_stop,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW ...@@ -31,23 +31,18 @@ config CPU_FREQ_BOOST_SW
depends on THERMAL depends on THERMAL
config CPU_FREQ_STAT config CPU_FREQ_STAT
tristate "CPU frequency translation statistics" bool "CPU frequency transition statistics"
default y default y
help help
This driver exports CPU frequency statistics information through sysfs Export CPU frequency statistics information through sysfs.
file system.
To compile this driver as a module, choose M here: the
module will be called cpufreq_stats.
If in doubt, say N. If in doubt, say N.
config CPU_FREQ_STAT_DETAILS config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details" bool "CPU frequency transition statistics details"
depends on CPU_FREQ_STAT depends on CPU_FREQ_STAT
help help
This will show detail CPU frequency translation table in sysfs file Show detailed CPU frequency transition table in sysfs.
system.
If in doubt, say N. If in doubt, say N.
......
...@@ -48,9 +48,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy, ...@@ -48,9 +48,8 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
struct dbs_data *od_data = policy_dbs->dbs_data; struct dbs_data *od_data = policy_dbs->dbs_data;
struct od_dbs_tuners *od_tuners = od_data->tuners; struct od_dbs_tuners *od_tuners = od_data->tuners;
struct od_policy_dbs_info *od_info = to_dbs_info(policy_dbs);
if (!od_info->freq_table) if (!policy->freq_table)
return freq_next; return freq_next;
rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, rdmsr_on_cpu(policy->cpu, MSR_AMD64_FREQ_SENSITIVITY_ACTUAL,
...@@ -92,10 +91,9 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy, ...@@ -92,10 +91,9 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
else { else {
unsigned int index; unsigned int index;
cpufreq_frequency_table_target(policy, index = cpufreq_frequency_table_target(policy,
od_info->freq_table, policy->cur - 1, policy->cur - 1, CPUFREQ_RELATION_H);
CPUFREQ_RELATION_H, &index); freq_next = policy->freq_table[index].frequency;
freq_next = od_info->freq_table[index].frequency;
} }
data->freq_prev = freq_next; data->freq_prev = freq_next;
......
...@@ -74,19 +74,12 @@ static inline bool has_target(void) ...@@ -74,19 +74,12 @@ static inline bool has_target(void)
} }
/* internal prototypes */ /* internal prototypes */
static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static unsigned int __cpufreq_get(struct cpufreq_policy *policy); static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
static int cpufreq_init_governor(struct cpufreq_policy *policy);
static void cpufreq_exit_governor(struct cpufreq_policy *policy);
static int cpufreq_start_governor(struct cpufreq_policy *policy); static int cpufreq_start_governor(struct cpufreq_policy *policy);
static void cpufreq_stop_governor(struct cpufreq_policy *policy);
static inline void cpufreq_exit_governor(struct cpufreq_policy *policy) static void cpufreq_governor_limits(struct cpufreq_policy *policy);
{
(void)cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
}
static inline void cpufreq_stop_governor(struct cpufreq_policy *policy)
{
(void)cpufreq_governor(policy, CPUFREQ_GOV_STOP);
}
/** /**
* Two notifier lists: the "policy" list is involved in the * Two notifier lists: the "policy" list is involved in the
...@@ -133,15 +126,6 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) ...@@ -133,15 +126,6 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
} }
EXPORT_SYMBOL_GPL(get_governor_parent_kobj); EXPORT_SYMBOL_GPL(get_governor_parent_kobj);
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
return policy && !policy_is_inactive(policy) ?
policy->freq_table : NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
{ {
u64 idle_time; u64 idle_time;
...@@ -354,6 +338,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -354,6 +338,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
pr_debug("FREQ: %lu - CPU: %lu\n", pr_debug("FREQ: %lu - CPU: %lu\n",
(unsigned long)freqs->new, (unsigned long)freqs->cpu); (unsigned long)freqs->new, (unsigned long)freqs->cpu);
trace_cpu_frequency(freqs->new, freqs->cpu); trace_cpu_frequency(freqs->new, freqs->cpu);
cpufreq_stats_record_transition(policy, freqs->new);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list, srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs); CPUFREQ_POSTCHANGE, freqs);
if (likely(policy) && likely(policy->cpu == freqs->cpu)) if (likely(policy) && likely(policy->cpu == freqs->cpu))
...@@ -1115,6 +1100,7 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify) ...@@ -1115,6 +1100,7 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy, bool notify)
CPUFREQ_REMOVE_POLICY, policy); CPUFREQ_REMOVE_POLICY, policy);
down_write(&policy->rwsem); down_write(&policy->rwsem);
cpufreq_stats_free_table(policy);
cpufreq_remove_dev_symlink(policy); cpufreq_remove_dev_symlink(policy);
kobj = &policy->kobj; kobj = &policy->kobj;
cmp = &policy->kobj_unregister; cmp = &policy->kobj_unregister;
...@@ -1265,13 +1251,12 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1265,13 +1251,12 @@ static int cpufreq_online(unsigned int cpu)
} }
} }
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy);
if (new_policy) { if (new_policy) {
ret = cpufreq_add_dev_interface(policy); ret = cpufreq_add_dev_interface(policy);
if (ret) if (ret)
goto out_exit_policy; goto out_exit_policy;
cpufreq_stats_create_table(policy);
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_CREATE_POLICY, policy); CPUFREQ_CREATE_POLICY, policy);
...@@ -1280,6 +1265,9 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1280,6 +1265,9 @@ static int cpufreq_online(unsigned int cpu)
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
} }
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy);
ret = cpufreq_init_policy(policy); ret = cpufreq_init_policy(policy);
if (ret) { if (ret) {
pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n", pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n",
...@@ -1864,14 +1852,17 @@ static int __target_intermediate(struct cpufreq_policy *policy, ...@@ -1864,14 +1852,17 @@ static int __target_intermediate(struct cpufreq_policy *policy,
return ret; return ret;
} }
static int __target_index(struct cpufreq_policy *policy, static int __target_index(struct cpufreq_policy *policy, int index)
struct cpufreq_frequency_table *freq_table, int index)
{ {
struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0}; struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0};
unsigned int intermediate_freq = 0; unsigned int intermediate_freq = 0;
unsigned int newfreq = policy->freq_table[index].frequency;
int retval = -EINVAL; int retval = -EINVAL;
bool notify; bool notify;
if (newfreq == policy->cur)
return 0;
notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION);
if (notify) { if (notify) {
/* Handle switching to intermediate frequency */ /* Handle switching to intermediate frequency */
...@@ -1886,7 +1877,7 @@ static int __target_index(struct cpufreq_policy *policy, ...@@ -1886,7 +1877,7 @@ static int __target_index(struct cpufreq_policy *policy,
freqs.old = freqs.new; freqs.old = freqs.new;
} }
freqs.new = freq_table[index].frequency; freqs.new = newfreq;
pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
__func__, policy->cpu, freqs.old, freqs.new); __func__, policy->cpu, freqs.old, freqs.new);
...@@ -1923,17 +1914,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1923,17 +1914,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
unsigned int relation) unsigned int relation)
{ {
unsigned int old_target_freq = target_freq; unsigned int old_target_freq = target_freq;
struct cpufreq_frequency_table *freq_table; int index;
int index, retval;
if (cpufreq_disabled()) if (cpufreq_disabled())
return -ENODEV; return -ENODEV;
/* Make sure that target_freq is within supported range */ /* Make sure that target_freq is within supported range */
if (target_freq > policy->max) target_freq = clamp_val(target_freq, policy->min, policy->max);
target_freq = policy->max;
if (target_freq < policy->min)
target_freq = policy->min;
pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
policy->cpu, target_freq, relation, old_target_freq); policy->cpu, target_freq, relation, old_target_freq);
...@@ -1956,23 +1943,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1956,23 +1943,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
if (!cpufreq_driver->target_index) if (!cpufreq_driver->target_index)
return -EINVAL; return -EINVAL;
freq_table = cpufreq_frequency_get_table(policy->cpu); index = cpufreq_frequency_table_target(policy, target_freq, relation);
if (unlikely(!freq_table)) {
pr_err("%s: Unable to find freq_table\n", __func__);
return -EINVAL;
}
retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
relation, &index);
if (unlikely(retval)) {
pr_err("%s: Unable to find matching freq\n", __func__);
return retval;
}
if (freq_table[index].frequency == policy->cur)
return 0;
return __target_index(policy, freq_table, index); return __target_index(policy, index);
} }
EXPORT_SYMBOL_GPL(__cpufreq_driver_target); EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
...@@ -1997,7 +1970,7 @@ __weak struct cpufreq_governor *cpufreq_fallback_governor(void) ...@@ -1997,7 +1970,7 @@ __weak struct cpufreq_governor *cpufreq_fallback_governor(void)
return NULL; return NULL;
} }
static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) static int cpufreq_init_governor(struct cpufreq_policy *policy)
{ {
int ret; int ret;
...@@ -2025,36 +1998,82 @@ static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) ...@@ -2025,36 +1998,82 @@ static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
} }
} }
if (event == CPUFREQ_GOV_POLICY_INIT)
if (!try_module_get(policy->governor->owner)) if (!try_module_get(policy->governor->owner))
return -EINVAL; return -EINVAL;
pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event); pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
ret = policy->governor->governor(policy, event); if (policy->governor->init) {
ret = policy->governor->init(policy);
if (event == CPUFREQ_GOV_POLICY_INIT) { if (ret) {
if (ret)
module_put(policy->governor->owner);
else
policy->governor->initialized++;
} else if (event == CPUFREQ_GOV_POLICY_EXIT) {
policy->governor->initialized--;
module_put(policy->governor->owner); module_put(policy->governor->owner);
return ret;
}
} }
return ret; return 0;
}
static void cpufreq_exit_governor(struct cpufreq_policy *policy)
{
if (cpufreq_suspended || !policy->governor)
return;
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
if (policy->governor->exit)
policy->governor->exit(policy);
module_put(policy->governor->owner);
} }
static int cpufreq_start_governor(struct cpufreq_policy *policy) static int cpufreq_start_governor(struct cpufreq_policy *policy)
{ {
int ret; int ret;
if (cpufreq_suspended)
return 0;
if (!policy->governor)
return -EINVAL;
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
cpufreq_update_current_freq(policy); cpufreq_update_current_freq(policy);
ret = cpufreq_governor(policy, CPUFREQ_GOV_START); if (policy->governor->start) {
return ret ? ret : cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); ret = policy->governor->start(policy);
if (ret)
return ret;
}
if (policy->governor->limits)
policy->governor->limits(policy);
return 0;
}
static void cpufreq_stop_governor(struct cpufreq_policy *policy)
{
if (cpufreq_suspended || !policy->governor)
return;
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
if (policy->governor->stop)
policy->governor->stop(policy);
}
static void cpufreq_governor_limits(struct cpufreq_policy *policy)
{
if (cpufreq_suspended || !policy->governor)
return;
pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
if (policy->governor->limits)
policy->governor->limits(policy);
} }
int cpufreq_register_governor(struct cpufreq_governor *governor) int cpufreq_register_governor(struct cpufreq_governor *governor)
...@@ -2069,7 +2088,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) ...@@ -2069,7 +2088,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
mutex_lock(&cpufreq_governor_mutex); mutex_lock(&cpufreq_governor_mutex);
governor->initialized = 0;
err = -EBUSY; err = -EBUSY;
if (!find_governor(governor->name)) { if (!find_governor(governor->name)) {
err = 0; err = 0;
...@@ -2195,7 +2213,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2195,7 +2213,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
if (new_policy->governor == policy->governor) { if (new_policy->governor == policy->governor) {
pr_debug("cpufreq: governor limits update\n"); pr_debug("cpufreq: governor limits update\n");
return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); cpufreq_governor_limits(policy);
return 0;
} }
pr_debug("governor switch\n"); pr_debug("governor switch\n");
...@@ -2210,7 +2229,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2210,7 +2229,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
/* start new governor */ /* start new governor */
policy->governor = new_policy->governor; policy->governor = new_policy->governor;
ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); ret = cpufreq_init_governor(policy);
if (!ret) { if (!ret) {
ret = cpufreq_start_governor(policy); ret = cpufreq_start_governor(policy);
if (!ret) { if (!ret) {
...@@ -2224,7 +2243,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2224,7 +2243,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
pr_debug("starting governor %s failed\n", policy->governor->name); pr_debug("starting governor %s failed\n", policy->governor->name);
if (old_gov) { if (old_gov) {
policy->governor = old_gov; policy->governor = old_gov;
if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) if (cpufreq_init_governor(policy))
policy->governor = NULL; policy->governor = NULL;
else else
cpufreq_start_governor(policy); cpufreq_start_governor(policy);
...@@ -2305,15 +2324,15 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = { ...@@ -2305,15 +2324,15 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
*********************************************************************/ *********************************************************************/
static int cpufreq_boost_set_sw(int state) static int cpufreq_boost_set_sw(int state)
{ {
struct cpufreq_frequency_table *freq_table;
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
int ret = -EINVAL; int ret = -EINVAL;
for_each_active_policy(policy) { for_each_active_policy(policy) {
freq_table = cpufreq_frequency_get_table(policy->cpu); if (!policy->freq_table)
if (freq_table) { continue;
ret = cpufreq_frequency_table_cpuinfo(policy, ret = cpufreq_frequency_table_cpuinfo(policy,
freq_table); policy->freq_table);
if (ret) { if (ret) {
pr_err("%s: Policy frequency update failed\n", pr_err("%s: Policy frequency update failed\n",
__func__); __func__);
...@@ -2322,10 +2341,9 @@ static int cpufreq_boost_set_sw(int state) ...@@ -2322,10 +2341,9 @@ static int cpufreq_boost_set_sw(int state)
down_write(&policy->rwsem); down_write(&policy->rwsem);
policy->user_policy.max = policy->max; policy->user_policy.max = policy->max;
cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); cpufreq_governor_limits(policy);
up_write(&policy->rwsem); up_write(&policy->rwsem);
} }
}
return ret; return ret;
} }
......
...@@ -127,7 +127,6 @@ static struct notifier_block cs_cpufreq_notifier_block = { ...@@ -127,7 +127,6 @@ static struct notifier_block cs_cpufreq_notifier_block = {
}; };
/************************** sysfs interface ************************/ /************************** sysfs interface ************************/
static struct dbs_governor cs_dbs_gov;
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set, static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -255,6 +254,13 @@ static struct attribute *cs_attributes[] = { ...@@ -255,6 +254,13 @@ static struct attribute *cs_attributes[] = {
/************************** sysfs end ************************/ /************************** sysfs end ************************/
struct cs_governor {
struct dbs_governor dbs_gov;
unsigned int usage_count;
};
static struct cs_governor cs_gov;
static struct policy_dbs_info *cs_alloc(void) static struct policy_dbs_info *cs_alloc(void)
{ {
struct cs_policy_dbs_info *dbs_info; struct cs_policy_dbs_info *dbs_info;
...@@ -268,15 +274,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs) ...@@ -268,15 +274,13 @@ static void cs_free(struct policy_dbs_info *policy_dbs)
kfree(to_dbs_info(policy_dbs)); kfree(to_dbs_info(policy_dbs));
} }
static int cs_init(struct dbs_data *dbs_data, bool notify) static int cs_init(struct dbs_data *dbs_data)
{ {
struct cs_dbs_tuners *tuners; struct cs_dbs_tuners *tuners;
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
if (!tuners) { if (!tuners)
pr_err("%s: kzalloc failed\n", __func__);
return -ENOMEM; return -ENOMEM;
}
tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD; tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
tuners->freq_step = DEF_FREQUENCY_STEP; tuners->freq_step = DEF_FREQUENCY_STEP;
...@@ -288,16 +292,22 @@ static int cs_init(struct dbs_data *dbs_data, bool notify) ...@@ -288,16 +292,22 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
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);
if (notify) /*
* This function and cs_exit() are only called under gov_dbs_data_mutex
* which is global, so the cs_gov.usage_count accesses are guaranteed
* to be serialized.
*/
if (!cs_gov.usage_count++)
cpufreq_register_notifier(&cs_cpufreq_notifier_block, cpufreq_register_notifier(&cs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
return 0; return 0;
} }
static void cs_exit(struct dbs_data *dbs_data, bool notify) static void cs_exit(struct dbs_data *dbs_data)
{ {
if (notify) /* Protected by gov_dbs_data_mutex - see the comment in cs_init(). */
if (!--cs_gov.usage_count)
cpufreq_unregister_notifier(&cs_cpufreq_notifier_block, cpufreq_unregister_notifier(&cs_cpufreq_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER); CPUFREQ_TRANSITION_NOTIFIER);
...@@ -312,13 +322,9 @@ static void cs_start(struct cpufreq_policy *policy) ...@@ -312,13 +322,9 @@ static void cs_start(struct cpufreq_policy *policy)
dbs_info->requested_freq = policy->cur; dbs_info->requested_freq = policy->cur;
} }
static struct dbs_governor cs_dbs_gov = { static struct cs_governor cs_gov = {
.gov = { .dbs_gov = {
.name = "conservative", .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
},
.kobj_type = { .default_attrs = cs_attributes }, .kobj_type = { .default_attrs = cs_attributes },
.gov_dbs_timer = cs_dbs_timer, .gov_dbs_timer = cs_dbs_timer,
.alloc = cs_alloc, .alloc = cs_alloc,
...@@ -326,9 +332,10 @@ static struct dbs_governor cs_dbs_gov = { ...@@ -326,9 +332,10 @@ static struct dbs_governor cs_dbs_gov = {
.init = cs_init, .init = cs_init,
.exit = cs_exit, .exit = cs_exit,
.start = cs_start, .start = cs_start,
},
}; };
#define CPU_FREQ_GOV_CONSERVATIVE (&cs_dbs_gov.gov) #define CPU_FREQ_GOV_CONSERVATIVE (&cs_gov.dbs_gov.gov)
static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data) void *data)
......
...@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy) ...@@ -336,17 +336,6 @@ static inline void gov_clear_update_util(struct cpufreq_policy *policy)
synchronize_sched(); synchronize_sched();
} }
static void gov_cancel_work(struct cpufreq_policy *policy)
{
struct policy_dbs_info *policy_dbs = policy->governor_data;
gov_clear_update_util(policy_dbs->policy);
irq_work_sync(&policy_dbs->irq_work);
cancel_work_sync(&policy_dbs->work);
atomic_set(&policy_dbs->work_count, 0);
policy_dbs->work_in_progress = false;
}
static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy, static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
struct dbs_governor *gov) struct dbs_governor *gov)
{ {
...@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs, ...@@ -389,7 +378,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
gov->free(policy_dbs); gov->free(policy_dbs);
} }
static int cpufreq_governor_init(struct cpufreq_policy *policy) int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
{ {
struct dbs_governor *gov = dbs_governor_of(policy); struct dbs_governor *gov = dbs_governor_of(policy);
struct dbs_data *dbs_data; struct dbs_data *dbs_data;
...@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -429,7 +418,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list); gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list);
ret = gov->init(dbs_data, !policy->governor->initialized); ret = gov->init(dbs_data);
if (ret) if (ret)
goto free_policy_dbs_info; goto free_policy_dbs_info;
...@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -458,13 +447,13 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
goto out; goto out;
/* Failure, so roll back. */ /* Failure, so roll back. */
pr_err("cpufreq: Governor initialization failed (dbs_data kobject init error %d)\n", ret); pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
policy->governor_data = NULL; policy->governor_data = NULL;
if (!have_governor_per_policy()) if (!have_governor_per_policy())
gov->gdbs_data = NULL; gov->gdbs_data = NULL;
gov->exit(dbs_data, !policy->governor->initialized); gov->exit(dbs_data);
kfree(dbs_data); kfree(dbs_data);
free_policy_dbs_info: free_policy_dbs_info:
...@@ -474,8 +463,9 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy) ...@@ -474,8 +463,9 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
mutex_unlock(&gov_dbs_data_mutex); mutex_unlock(&gov_dbs_data_mutex);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_init);
static int cpufreq_governor_exit(struct cpufreq_policy *policy) void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy)
{ {
struct dbs_governor *gov = dbs_governor_of(policy); struct dbs_governor *gov = dbs_governor_of(policy);
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
...@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy) ...@@ -493,17 +483,17 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
if (!have_governor_per_policy()) if (!have_governor_per_policy())
gov->gdbs_data = NULL; gov->gdbs_data = NULL;
gov->exit(dbs_data, policy->governor->initialized == 1); gov->exit(dbs_data);
kfree(dbs_data); kfree(dbs_data);
} }
free_policy_dbs_info(policy_dbs, gov); free_policy_dbs_info(policy_dbs, gov);
mutex_unlock(&gov_dbs_data_mutex); mutex_unlock(&gov_dbs_data_mutex);
return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_exit);
static int cpufreq_governor_start(struct cpufreq_policy *policy) int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
{ {
struct dbs_governor *gov = dbs_governor_of(policy); struct dbs_governor *gov = dbs_governor_of(policy);
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
...@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy) ...@@ -539,47 +529,28 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
gov_set_update_util(policy_dbs, sampling_rate); gov_set_update_util(policy_dbs, sampling_rate);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_start);
static int cpufreq_governor_stop(struct cpufreq_policy *policy) void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy)
{ {
gov_cancel_work(policy); struct policy_dbs_info *policy_dbs = policy->governor_data;
return 0;
gov_clear_update_util(policy_dbs->policy);
irq_work_sync(&policy_dbs->irq_work);
cancel_work_sync(&policy_dbs->work);
atomic_set(&policy_dbs->work_count, 0);
policy_dbs->work_in_progress = false;
} }
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
static int cpufreq_governor_limits(struct cpufreq_policy *policy) void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{ {
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
mutex_lock(&policy_dbs->timer_mutex); mutex_lock(&policy_dbs->timer_mutex);
cpufreq_policy_apply_limits(policy);
if (policy->max < policy->cur)
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
else if (policy->min > policy->cur)
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
gov_update_sample_delay(policy_dbs, 0); gov_update_sample_delay(policy_dbs, 0);
mutex_unlock(&policy_dbs->timer_mutex); mutex_unlock(&policy_dbs->timer_mutex);
return 0;
}
int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
{
if (event == CPUFREQ_GOV_POLICY_INIT) {
return cpufreq_governor_init(policy);
} else if (policy->governor_data) {
switch (event) {
case CPUFREQ_GOV_POLICY_EXIT:
return cpufreq_governor_exit(policy);
case CPUFREQ_GOV_START:
return cpufreq_governor_start(policy);
case CPUFREQ_GOV_STOP:
return cpufreq_governor_stop(policy);
case CPUFREQ_GOV_LIMITS:
return cpufreq_governor_limits(policy);
}
}
return -EINVAL;
} }
EXPORT_SYMBOL_GPL(cpufreq_governor_dbs); EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
...@@ -138,8 +138,8 @@ struct dbs_governor { ...@@ -138,8 +138,8 @@ struct dbs_governor {
unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy); unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
struct policy_dbs_info *(*alloc)(void); struct policy_dbs_info *(*alloc)(void);
void (*free)(struct policy_dbs_info *policy_dbs); void (*free)(struct policy_dbs_info *policy_dbs);
int (*init)(struct dbs_data *dbs_data, bool notify); int (*init)(struct dbs_data *dbs_data);
void (*exit)(struct dbs_data *dbs_data, bool notify); void (*exit)(struct dbs_data *dbs_data);
void (*start)(struct cpufreq_policy *policy); void (*start)(struct cpufreq_policy *policy);
}; };
...@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy ...@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
return container_of(policy->governor, struct dbs_governor, gov); return container_of(policy->governor, struct dbs_governor, gov);
} }
/* Governor callback routines */
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \
{ \
.name = _name_, \
.max_transition_latency = TRANSITION_LATENCY_LIMIT, \
.owner = THIS_MODULE, \
.init = cpufreq_dbs_governor_init, \
.exit = cpufreq_dbs_governor_exit, \
.start = cpufreq_dbs_governor_start, \
.stop = cpufreq_dbs_governor_stop, \
.limits = cpufreq_dbs_governor_limits, \
}
/* Governor specific operations */ /* Governor specific operations */
struct od_ops { struct od_ops {
unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
...@@ -155,7 +174,6 @@ struct od_ops { ...@@ -155,7 +174,6 @@ struct od_ops {
}; };
unsigned int dbs_update(struct cpufreq_policy *policy); unsigned int dbs_update(struct cpufreq_policy *policy);
int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
void od_register_powersave_bias_handler(unsigned int (*f) void od_register_powersave_bias_handler(unsigned int (*f)
(struct cpufreq_policy *, unsigned int, unsigned int), (struct cpufreq_policy *, unsigned int, unsigned int),
unsigned int powersave_bias); unsigned int powersave_bias);
......
...@@ -65,34 +65,32 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy, ...@@ -65,34 +65,32 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
{ {
unsigned int freq_req, freq_reduc, freq_avg; unsigned int freq_req, freq_reduc, freq_avg;
unsigned int freq_hi, freq_lo; unsigned int freq_hi, freq_lo;
unsigned int index = 0; unsigned int index;
unsigned int delay_hi_us; unsigned int delay_hi_us;
struct policy_dbs_info *policy_dbs = policy->governor_data; struct policy_dbs_info *policy_dbs = policy->governor_data;
struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs); struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
struct dbs_data *dbs_data = policy_dbs->dbs_data; struct dbs_data *dbs_data = policy_dbs->dbs_data;
struct od_dbs_tuners *od_tuners = dbs_data->tuners; struct od_dbs_tuners *od_tuners = dbs_data->tuners;
struct cpufreq_frequency_table *freq_table = policy->freq_table;
if (!dbs_info->freq_table) { if (!freq_table) {
dbs_info->freq_lo = 0; dbs_info->freq_lo = 0;
dbs_info->freq_lo_delay_us = 0; dbs_info->freq_lo_delay_us = 0;
return freq_next; return freq_next;
} }
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, index = cpufreq_frequency_table_target(policy, freq_next, relation);
relation, &index); freq_req = freq_table[index].frequency;
freq_req = dbs_info->freq_table[index].frequency;
freq_reduc = freq_req * od_tuners->powersave_bias / 1000; freq_reduc = freq_req * od_tuners->powersave_bias / 1000;
freq_avg = freq_req - freq_reduc; freq_avg = freq_req - freq_reduc;
/* Find freq bounds for freq_avg in freq_table */ /* Find freq bounds for freq_avg in freq_table */
index = 0; index = cpufreq_frequency_table_target(policy, freq_avg,
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, CPUFREQ_RELATION_H);
CPUFREQ_RELATION_H, &index); freq_lo = freq_table[index].frequency;
freq_lo = dbs_info->freq_table[index].frequency; index = cpufreq_frequency_table_target(policy, freq_avg,
index = 0; CPUFREQ_RELATION_L);
cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, freq_hi = freq_table[index].frequency;
CPUFREQ_RELATION_L, &index);
freq_hi = dbs_info->freq_table[index].frequency;
/* Find out how long we have to be in hi and lo freqs */ /* Find out how long we have to be in hi and lo freqs */
if (freq_hi == freq_lo) { if (freq_hi == freq_lo) {
...@@ -113,7 +111,6 @@ static void ondemand_powersave_bias_init(struct cpufreq_policy *policy) ...@@ -113,7 +111,6 @@ static void ondemand_powersave_bias_init(struct cpufreq_policy *policy)
{ {
struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data); struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
dbs_info->freq_table = cpufreq_frequency_get_table(policy->cpu);
dbs_info->freq_lo = 0; dbs_info->freq_lo = 0;
} }
...@@ -361,17 +358,15 @@ static void od_free(struct policy_dbs_info *policy_dbs) ...@@ -361,17 +358,15 @@ static void od_free(struct policy_dbs_info *policy_dbs)
kfree(to_dbs_info(policy_dbs)); kfree(to_dbs_info(policy_dbs));
} }
static int od_init(struct dbs_data *dbs_data, bool notify) static int od_init(struct dbs_data *dbs_data)
{ {
struct od_dbs_tuners *tuners; struct od_dbs_tuners *tuners;
u64 idle_time; u64 idle_time;
int cpu; int cpu;
tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); tuners = kzalloc(sizeof(*tuners), GFP_KERNEL);
if (!tuners) { if (!tuners)
pr_err("%s: kzalloc failed\n", __func__);
return -ENOMEM; return -ENOMEM;
}
cpu = get_cpu(); cpu = get_cpu();
idle_time = get_cpu_idle_time_us(cpu, NULL); idle_time = get_cpu_idle_time_us(cpu, NULL);
...@@ -402,7 +397,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify) ...@@ -402,7 +397,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
return 0; return 0;
} }
static void od_exit(struct dbs_data *dbs_data, bool notify) static void od_exit(struct dbs_data *dbs_data)
{ {
kfree(dbs_data->tuners); kfree(dbs_data->tuners);
} }
...@@ -420,12 +415,7 @@ static struct od_ops od_ops = { ...@@ -420,12 +415,7 @@ static struct od_ops od_ops = {
}; };
static struct dbs_governor od_dbs_gov = { static struct dbs_governor od_dbs_gov = {
.gov = { .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
.name = "ondemand",
.governor = cpufreq_governor_dbs,
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
.owner = THIS_MODULE,
},
.kobj_type = { .default_attrs = od_attributes }, .kobj_type = { .default_attrs = od_attributes },
.gov_dbs_timer = od_dbs_timer, .gov_dbs_timer = od_dbs_timer,
.alloc = od_alloc, .alloc = od_alloc,
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
struct od_policy_dbs_info { struct od_policy_dbs_info {
struct policy_dbs_info policy_dbs; struct policy_dbs_info policy_dbs;
struct cpufreq_frequency_table *freq_table;
unsigned int freq_lo; unsigned int freq_lo;
unsigned int freq_lo_delay_us; unsigned int freq_lo_delay_us;
unsigned int freq_hi_delay_us; unsigned int freq_hi_delay_us;
......
...@@ -16,27 +16,16 @@ ...@@ -16,27 +16,16 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
static int cpufreq_governor_performance(struct cpufreq_policy *policy, static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
unsigned int event)
{ {
switch (event) { pr_debug("setting to %u kHz\n", policy->max);
case CPUFREQ_GOV_START: __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
case CPUFREQ_GOV_LIMITS:
pr_debug("setting to %u kHz because of event %u\n",
policy->max, event);
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
break;
default:
break;
}
return 0;
} }
static struct cpufreq_governor cpufreq_gov_performance = { static struct cpufreq_governor cpufreq_gov_performance = {
.name = "performance", .name = "performance",
.governor = cpufreq_governor_performance,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.limits = cpufreq_gov_performance_limits,
}; };
static int __init cpufreq_gov_performance_init(void) static int __init cpufreq_gov_performance_init(void)
......
...@@ -16,26 +16,15 @@ ...@@ -16,26 +16,15 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
static int cpufreq_governor_powersave(struct cpufreq_policy *policy, static void cpufreq_gov_powersave_limits(struct cpufreq_policy *policy)
unsigned int event)
{ {
switch (event) { pr_debug("setting to %u kHz\n", policy->min);
case CPUFREQ_GOV_START: __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
case CPUFREQ_GOV_LIMITS:
pr_debug("setting to %u kHz because of event %u\n",
policy->min, event);
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
break;
default:
break;
}
return 0;
} }
static struct cpufreq_governor cpufreq_gov_powersave = { static struct cpufreq_governor cpufreq_gov_powersave = {
.name = "powersave", .name = "powersave",
.governor = cpufreq_governor_powersave, .limits = cpufreq_gov_powersave_limits,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cputime.h> #include <linux/cputime.h>
static spinlock_t cpufreq_stats_lock; static DEFINE_SPINLOCK(cpufreq_stats_lock);
struct cpufreq_stats { struct cpufreq_stats {
unsigned int total_trans; unsigned int total_trans;
...@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) ...@@ -52,6 +52,9 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0; ssize_t len = 0;
int i; int i;
if (policy->fast_switch_enabled)
return 0;
cpufreq_stats_update(stats); cpufreq_stats_update(stats);
for (i = 0; i < stats->state_num; i++) { for (i = 0; i < stats->state_num; i++) {
len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i],
...@@ -68,6 +71,9 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) ...@@ -68,6 +71,9 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0; ssize_t len = 0;
int i, j; int i, j;
if (policy->fast_switch_enabled)
return 0;
len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
len += snprintf(buf + len, PAGE_SIZE - len, " : "); len += snprintf(buf + len, PAGE_SIZE - len, " : ");
for (i = 0; i < stats->state_num; i++) { for (i = 0; i < stats->state_num; i++) {
...@@ -130,7 +136,7 @@ static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq) ...@@ -130,7 +136,7 @@ static int freq_table_get_index(struct cpufreq_stats *stats, unsigned int freq)
return -1; return -1;
} }
static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) void cpufreq_stats_free_table(struct cpufreq_policy *policy)
{ {
struct cpufreq_stats *stats = policy->stats; struct cpufreq_stats *stats = policy->stats;
...@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy) ...@@ -146,39 +152,25 @@ static void __cpufreq_stats_free_table(struct cpufreq_policy *policy)
policy->stats = NULL; policy->stats = NULL;
} }
static void cpufreq_stats_free_table(unsigned int cpu) void cpufreq_stats_create_table(struct cpufreq_policy *policy)
{
struct cpufreq_policy *policy;
policy = cpufreq_cpu_get(cpu);
if (!policy)
return;
__cpufreq_stats_free_table(policy);
cpufreq_cpu_put(policy);
}
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
{ {
unsigned int i = 0, count = 0, ret = -ENOMEM; unsigned int i = 0, count = 0, ret = -ENOMEM;
struct cpufreq_stats *stats; struct cpufreq_stats *stats;
unsigned int alloc_size; unsigned int alloc_size;
unsigned int cpu = policy->cpu;
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table;
/* We need cpufreq table for creating stats table */ /* We need cpufreq table for creating stats table */
table = cpufreq_frequency_get_table(cpu); table = policy->freq_table;
if (unlikely(!table)) if (unlikely(!table))
return 0; return;
/* stats already initialized */ /* stats already initialized */
if (policy->stats) if (policy->stats)
return -EEXIST; return;
stats = kzalloc(sizeof(*stats), GFP_KERNEL); stats = kzalloc(sizeof(*stats), GFP_KERNEL);
if (!stats) if (!stats)
return -ENOMEM; return;
/* Find total allocation size */ /* Find total allocation size */
cpufreq_for_each_valid_entry(pos, table) cpufreq_for_each_valid_entry(pos, table)
...@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) ...@@ -215,80 +207,32 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
policy->stats = stats; policy->stats = stats;
ret = sysfs_create_group(&policy->kobj, &stats_attr_group); ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
if (!ret) if (!ret)
return 0; return;
/* We failed, release resources */ /* We failed, release resources */
policy->stats = NULL; policy->stats = NULL;
kfree(stats->time_in_state); kfree(stats->time_in_state);
free_stat: free_stat:
kfree(stats); kfree(stats);
return ret;
}
static void cpufreq_stats_create_table(unsigned int cpu)
{
struct cpufreq_policy *policy;
/*
* "likely(!policy)" because normally cpufreq_stats will be registered
* before cpufreq driver
*/
policy = cpufreq_cpu_get(cpu);
if (likely(!policy))
return;
__cpufreq_stats_create_table(policy);
cpufreq_cpu_put(policy);
} }
static int cpufreq_stat_notifier_policy(struct notifier_block *nb, void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
unsigned long val, void *data) unsigned int new_freq)
{ {
int ret = 0; struct cpufreq_stats *stats = policy->stats;
struct cpufreq_policy *policy = data;
if (val == CPUFREQ_CREATE_POLICY)
ret = __cpufreq_stats_create_table(policy);
else if (val == CPUFREQ_REMOVE_POLICY)
__cpufreq_stats_free_table(policy);
return ret;
}
static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
unsigned long val, void *data)
{
struct cpufreq_freqs *freq = data;
struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu);
struct cpufreq_stats *stats;
int old_index, new_index; int old_index, new_index;
if (!policy) { if (!stats) {
pr_err("%s: No policy found\n", __func__);
return 0;
}
if (val != CPUFREQ_POSTCHANGE)
goto put_policy;
if (!policy->stats) {
pr_debug("%s: No stats found\n", __func__); pr_debug("%s: No stats found\n", __func__);
goto put_policy; return;
} }
stats = policy->stats;
old_index = stats->last_index; old_index = stats->last_index;
new_index = freq_table_get_index(stats, freq->new); new_index = freq_table_get_index(stats, new_freq);
/* We can't do stats->time_in_state[-1]= .. */ /* We can't do stats->time_in_state[-1]= .. */
if (old_index == -1 || new_index == -1) if (old_index == -1 || new_index == -1 || old_index == new_index)
goto put_policy; return;
if (old_index == new_index)
goto put_policy;
cpufreq_stats_update(stats); cpufreq_stats_update(stats);
...@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, ...@@ -297,61 +241,4 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
stats->trans_table[old_index * stats->max_state + new_index]++; stats->trans_table[old_index * stats->max_state + new_index]++;
#endif #endif
stats->total_trans++; stats->total_trans++;
put_policy:
cpufreq_cpu_put(policy);
return 0;
} }
static struct notifier_block notifier_policy_block = {
.notifier_call = cpufreq_stat_notifier_policy
};
static struct notifier_block notifier_trans_block = {
.notifier_call = cpufreq_stat_notifier_trans
};
static int __init cpufreq_stats_init(void)
{
int ret;
unsigned int cpu;
spin_lock_init(&cpufreq_stats_lock);
ret = cpufreq_register_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
if (ret)
return ret;
for_each_online_cpu(cpu)
cpufreq_stats_create_table(cpu);
ret = cpufreq_register_notifier(&notifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
cpufreq_unregister_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
for_each_online_cpu(cpu)
cpufreq_stats_free_table(cpu);
return ret;
}
return 0;
}
static void __exit cpufreq_stats_exit(void)
{
unsigned int cpu;
cpufreq_unregister_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
cpufreq_unregister_notifier(&notifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
for_each_online_cpu(cpu)
cpufreq_stats_free_table(cpu);
}
MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
MODULE_DESCRIPTION("Export cpufreq stats via sysfs");
MODULE_LICENSE("GPL");
module_init(cpufreq_stats_init);
module_exit(cpufreq_stats_exit);
...@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy) ...@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int cpufreq_governor_userspace(struct cpufreq_policy *policy, static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
unsigned int event)
{ {
unsigned int *setspeed = policy->governor_data;
unsigned int cpu = policy->cpu;
int rc = 0;
if (event == CPUFREQ_GOV_POLICY_INIT)
return cpufreq_userspace_policy_init(policy);
if (!setspeed)
return -EINVAL;
switch (event) {
case CPUFREQ_GOV_POLICY_EXIT:
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
kfree(policy->governor_data);
policy->governor_data = NULL; policy->governor_data = NULL;
kfree(setspeed);
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; }
case CPUFREQ_GOV_START:
static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
BUG_ON(!policy->cur); BUG_ON(!policy->cur);
pr_debug("started managing cpu %u\n", cpu); pr_debug("started managing cpu %u\n", policy->cpu);
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
per_cpu(cpu_is_managed, cpu) = 1; per_cpu(cpu_is_managed, policy->cpu) = 1;
*setspeed = policy->cur; *setspeed = policy->cur;
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; return 0;
case CPUFREQ_GOV_STOP: }
pr_debug("managing cpu %u stopped\n", cpu);
static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
pr_debug("managing cpu %u stopped\n", policy->cpu);
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
per_cpu(cpu_is_managed, cpu) = 0; per_cpu(cpu_is_managed, policy->cpu) = 0;
*setspeed = 0; *setspeed = 0;
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break; }
case CPUFREQ_GOV_LIMITS:
static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
{
unsigned int *setspeed = policy->governor_data;
mutex_lock(&userspace_mutex); mutex_lock(&userspace_mutex);
pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
cpu, policy->min, policy->max, policy->cur, *setspeed); policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
if (policy->max < *setspeed) if (policy->max < *setspeed)
__cpufreq_driver_target(policy, policy->max, __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
CPUFREQ_RELATION_H);
else if (policy->min > *setspeed) else if (policy->min > *setspeed)
__cpufreq_driver_target(policy, policy->min, __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
CPUFREQ_RELATION_L);
else else
__cpufreq_driver_target(policy, *setspeed, __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
CPUFREQ_RELATION_L);
mutex_unlock(&userspace_mutex); mutex_unlock(&userspace_mutex);
break;
}
return rc;
} }
static struct cpufreq_governor cpufreq_gov_userspace = { static struct cpufreq_governor cpufreq_gov_userspace = {
.name = "userspace", .name = "userspace",
.governor = cpufreq_governor_userspace, .init = cpufreq_userspace_policy_init,
.exit = cpufreq_userspace_policy_exit,
.start = cpufreq_userspace_policy_start,
.stop = cpufreq_userspace_policy_stop,
.limits = cpufreq_userspace_policy_limits,
.store_setspeed = cpufreq_set, .store_setspeed = cpufreq_set,
.show_setspeed = show_speed, .show_setspeed = show_speed,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -38,26 +38,6 @@ struct davinci_cpufreq { ...@@ -38,26 +38,6 @@ struct davinci_cpufreq {
}; };
static struct davinci_cpufreq cpufreq; static struct davinci_cpufreq cpufreq;
static int davinci_verify_speed(struct cpufreq_policy *policy)
{
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
struct cpufreq_frequency_table *freq_table = pdata->freq_table;
struct clk *armclk = cpufreq.armclk;
if (freq_table)
return cpufreq_frequency_table_verify(policy, freq_table);
if (policy->cpu)
return -EINVAL;
cpufreq_verify_within_cpu_limits(policy);
policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
policy->cpuinfo.max_freq);
return 0;
}
static int davinci_target(struct cpufreq_policy *policy, unsigned int idx) static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
{ {
struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
...@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy) ...@@ -121,7 +101,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
static struct cpufreq_driver davinci_driver = { static struct cpufreq_driver davinci_driver = {
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
.verify = davinci_verify_speed, .verify = cpufreq_generic_frequency_table_verify,
.target_index = davinci_target, .target_index = davinci_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = davinci_cpu_init, .init = davinci_cpu_init,
......
...@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, ...@@ -63,8 +63,6 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
else else
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table) struct cpufreq_frequency_table *table)
...@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); ...@@ -108,20 +106,16 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
*/ */
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
{ {
struct cpufreq_frequency_table *table = if (!policy->freq_table)
cpufreq_frequency_get_table(policy->cpu);
if (!table)
return -ENODEV; return -ENODEV;
return cpufreq_frequency_table_verify(policy, table); return cpufreq_frequency_table_verify(policy, policy->freq_table);
} }
EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation, unsigned int relation)
unsigned int *index)
{ {
struct cpufreq_frequency_table optimal = { struct cpufreq_frequency_table optimal = {
.driver_data = ~0, .driver_data = ~0,
...@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -132,7 +126,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
.frequency = 0, .frequency = 0,
}; };
struct cpufreq_frequency_table *pos; struct cpufreq_frequency_table *pos;
struct cpufreq_frequency_table *table = policy->freq_table;
unsigned int freq, diff, i = 0; unsigned int freq, diff, i = 0;
int index;
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);
...@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -196,25 +192,26 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
} }
} }
if (optimal.driver_data > i) { if (optimal.driver_data > i) {
if (suboptimal.driver_data > i) if (suboptimal.driver_data > i) {
return -EINVAL; WARN(1, "Invalid frequency table: %d\n", policy->cpu);
*index = suboptimal.driver_data; return 0;
} else }
*index = optimal.driver_data;
pr_debug("target index is %u, freq is:%u kHz\n", *index, index = suboptimal.driver_data;
table[*index].frequency); } else
index = optimal.driver_data;
return 0; pr_debug("target index is %u, freq is:%u kHz\n", index,
table[index].frequency);
return index;
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
unsigned int freq) unsigned int freq)
{ {
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table = policy->freq_table;
table = cpufreq_frequency_get_table(policy->cpu);
if (unlikely(!table)) { if (unlikely(!table)) {
pr_debug("%s: Unable to find frequency table\n", __func__); pr_debug("%s: Unable to find frequency table\n", __func__);
return -ENOENT; return -ENOENT;
......
...@@ -760,9 +760,8 @@ void powernv_cpufreq_work_fn(struct work_struct *work) ...@@ -760,9 +760,8 @@ void powernv_cpufreq_work_fn(struct work_struct *work)
struct cpufreq_policy policy; struct cpufreq_policy policy;
cpufreq_get_policy(&policy, cpu); cpufreq_get_policy(&policy, cpu);
cpufreq_frequency_table_target(&policy, policy.freq_table, index = cpufreq_frequency_table_target(&policy, policy.cur,
policy.cur, CPUFREQ_RELATION_C);
CPUFREQ_RELATION_C, &index);
powernv_cpufreq_target_index(&policy, index); powernv_cpufreq_target_index(&policy, index);
cpumask_andnot(&mask, &mask, policy.cpus); cpumask_andnot(&mask, &mask, policy.cpus);
} }
......
...@@ -94,7 +94,7 @@ static int pmi_notifier(struct notifier_block *nb, ...@@ -94,7 +94,7 @@ static int pmi_notifier(struct notifier_block *nb,
unsigned long event, void *data) unsigned long event, void *data)
{ {
struct cpufreq_policy *policy = data; struct cpufreq_policy *policy = data;
struct cpufreq_frequency_table *cbe_freqs; struct cpufreq_frequency_table *cbe_freqs = policy->freq_table;
u8 node; u8 node;
/* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY /* Should this really be called for CPUFREQ_ADJUST and CPUFREQ_NOTIFY
...@@ -103,7 +103,6 @@ static int pmi_notifier(struct notifier_block *nb, ...@@ -103,7 +103,6 @@ static int pmi_notifier(struct notifier_block *nb,
if (event == CPUFREQ_START) if (event == CPUFREQ_START)
return 0; return 0;
cbe_freqs = cpufreq_frequency_get_table(policy->cpu);
node = cbe_cpu_to_node(policy->cpu); node = cbe_cpu_to_node(policy->cpu);
pr_debug("got notified, event=%lu, node=%u\n", event, node); pr_debug("got notified, event=%lu, node=%u\n", event, node);
......
...@@ -293,12 +293,8 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -293,12 +293,8 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
__func__, policy, target_freq, relation); __func__, policy, target_freq, relation);
if (ftab) { if (ftab) {
if (cpufreq_frequency_table_target(policy, ftab, index = cpufreq_frequency_table_target(policy, target_freq,
target_freq, relation, relation);
&index)) {
s3c_freq_dbg("%s: table failed\n", __func__);
return -EINVAL;
}
s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__, s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__,
target_freq, index, ftab[index].frequency); target_freq, index, ftab[index].frequency);
...@@ -315,7 +311,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -315,7 +311,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
pll = NULL; pll = NULL;
} else { } else {
struct cpufreq_policy tmp_policy; struct cpufreq_policy tmp_policy;
int ret;
/* we keep the cpu pll table in Hz, to ensure we get an /* we keep the cpu pll table in Hz, to ensure we get an
* accurate value for the PLL output. */ * accurate value for the PLL output. */
...@@ -323,20 +318,14 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -323,20 +318,14 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
tmp_policy.min = policy->min * 1000; tmp_policy.min = policy->min * 1000;
tmp_policy.max = policy->max * 1000; tmp_policy.max = policy->max * 1000;
tmp_policy.cpu = policy->cpu; tmp_policy.cpu = policy->cpu;
tmp_policy.freq_table = pll_reg;
/* cpufreq_frequency_table_target uses a pointer to 'index' /* cpufreq_frequency_table_target returns the index
* which is the number of the table entry, not the value of * of the table entry, not the value of
* the table entry's index field. */ * the table entry's index field. */
ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg, index = cpufreq_frequency_table_target(&tmp_policy, target_freq,
target_freq, relation, relation);
&index);
if (ret < 0) {
pr_err("%s: no PLL available\n", __func__);
goto err_notpossible;
}
pll = pll_reg + index; pll = pll_reg + index;
s3c_freq_dbg("%s: target %u => %u\n", s3c_freq_dbg("%s: target %u => %u\n",
...@@ -346,10 +335,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy, ...@@ -346,10 +335,6 @@ static int s3c_cpufreq_target(struct cpufreq_policy *policy,
} }
return s3c_cpufreq_settarget(policy, target_freq, pll); return s3c_cpufreq_settarget(policy, target_freq, pll);
err_notpossible:
pr_err("no compatible settings for %d\n", target_freq);
return -EINVAL;
} }
struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
...@@ -571,11 +556,7 @@ static int s3c_cpufreq_build_freq(void) ...@@ -571,11 +556,7 @@ static int s3c_cpufreq_build_freq(void)
{ {
int size, ret; int size, ret;
if (!cpu_cur.info->calc_freqtable)
return -EINVAL;
kfree(ftab); kfree(ftab);
ftab = NULL;
size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
size++; size++;
......
...@@ -246,12 +246,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -246,12 +246,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
new_freq = s5pv210_freq_table[index].frequency; new_freq = s5pv210_freq_table[index].frequency;
/* Finding current running level index */ /* Finding current running level index */
if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, priv_index = cpufreq_frequency_table_target(policy, old_freq,
old_freq, CPUFREQ_RELATION_H, CPUFREQ_RELATION_H);
&priv_index)) {
ret = -EINVAL;
goto exit;
}
arm_volt = dvs_conf[index].arm_volt; arm_volt = dvs_conf[index].arm_volt;
int_volt = dvs_conf[index].int_volt; int_volt = dvs_conf[index].int_volt;
......
...@@ -787,22 +787,34 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -787,22 +787,34 @@ __cpufreq_cooling_register(struct device_node *np,
const struct cpumask *clip_cpus, u32 capacitance, const struct cpumask *clip_cpus, u32 capacitance,
get_static_t plat_static_func) get_static_t plat_static_func)
{ {
struct cpufreq_policy *policy;
struct thermal_cooling_device *cool_dev; struct thermal_cooling_device *cool_dev;
struct cpufreq_cooling_device *cpufreq_dev; struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH]; char dev_name[THERMAL_NAME_LENGTH];
struct cpufreq_frequency_table *pos, *table; struct cpufreq_frequency_table *pos, *table;
struct cpumask temp_mask;
unsigned int freq, i, num_cpus; unsigned int freq, i, num_cpus;
int ret; int ret;
table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); cpumask_and(&temp_mask, clip_cpus, cpu_online_mask);
policy = cpufreq_cpu_get(cpumask_first(&temp_mask));
if (!policy) {
pr_debug("%s: CPUFreq policy not found\n", __func__);
return ERR_PTR(-EPROBE_DEFER);
}
table = policy->freq_table;
if (!table) { if (!table) {
pr_debug("%s: CPUFreq table not found\n", __func__); pr_debug("%s: CPUFreq table not found\n", __func__);
return ERR_PTR(-EPROBE_DEFER); cool_dev = ERR_PTR(-ENODEV);
goto put_policy;
} }
cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL); cpufreq_dev = kzalloc(sizeof(*cpufreq_dev), GFP_KERNEL);
if (!cpufreq_dev) if (!cpufreq_dev) {
return ERR_PTR(-ENOMEM); cool_dev = ERR_PTR(-ENOMEM);
goto put_policy;
}
num_cpus = cpumask_weight(clip_cpus); num_cpus = cpumask_weight(clip_cpus);
cpufreq_dev->time_in_idle = kcalloc(num_cpus, cpufreq_dev->time_in_idle = kcalloc(num_cpus,
...@@ -892,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -892,7 +904,7 @@ __cpufreq_cooling_register(struct device_node *np,
CPUFREQ_POLICY_NOTIFIER); CPUFREQ_POLICY_NOTIFIER);
mutex_unlock(&cooling_cpufreq_lock); mutex_unlock(&cooling_cpufreq_lock);
return cool_dev; goto put_policy;
remove_idr: remove_idr:
release_idr(&cpufreq_idr, cpufreq_dev->id); release_idr(&cpufreq_idr, cpufreq_dev->id);
...@@ -906,6 +918,8 @@ __cpufreq_cooling_register(struct device_node *np, ...@@ -906,6 +918,8 @@ __cpufreq_cooling_register(struct device_node *np,
kfree(cpufreq_dev->time_in_idle); kfree(cpufreq_dev->time_in_idle);
free_cdev: free_cdev:
kfree(cpufreq_dev); kfree(cpufreq_dev);
put_policy:
cpufreq_cpu_put(policy);
return cool_dev; return cool_dev;
} }
......
...@@ -185,6 +185,18 @@ static inline unsigned int cpufreq_quick_get_max(unsigned int cpu) ...@@ -185,6 +185,18 @@ static inline unsigned int cpufreq_quick_get_max(unsigned int cpu)
static inline void disable_cpufreq(void) { } static inline void disable_cpufreq(void) { }
#endif #endif
#ifdef CONFIG_CPU_FREQ_STAT
void cpufreq_stats_create_table(struct cpufreq_policy *policy);
void cpufreq_stats_free_table(struct cpufreq_policy *policy);
void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
unsigned int new_freq);
#else
static inline void cpufreq_stats_create_table(struct cpufreq_policy *policy) { }
static inline void cpufreq_stats_free_table(struct cpufreq_policy *policy) { }
static inline void cpufreq_stats_record_transition(struct cpufreq_policy *policy,
unsigned int new_freq) { }
#endif /* CONFIG_CPU_FREQ_STAT */
/********************************************************************* /*********************************************************************
* CPUFREQ DRIVER INTERFACE * * CPUFREQ DRIVER INTERFACE *
*********************************************************************/ *********************************************************************/
...@@ -455,18 +467,13 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, ...@@ -455,18 +467,13 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
#define MIN_LATENCY_MULTIPLIER (20) #define MIN_LATENCY_MULTIPLIER (20)
#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
/* Governor Events */
#define CPUFREQ_GOV_START 1
#define CPUFREQ_GOV_STOP 2
#define CPUFREQ_GOV_LIMITS 3
#define CPUFREQ_GOV_POLICY_INIT 4
#define CPUFREQ_GOV_POLICY_EXIT 5
struct cpufreq_governor { struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN]; char name[CPUFREQ_NAME_LEN];
int initialized; int (*init)(struct cpufreq_policy *policy);
int (*governor) (struct cpufreq_policy *policy, void (*exit)(struct cpufreq_policy *policy);
unsigned int event); int (*start)(struct cpufreq_policy *policy);
void (*stop)(struct cpufreq_policy *policy);
void (*limits)(struct cpufreq_policy *policy);
ssize_t (*show_setspeed) (struct cpufreq_policy *policy, ssize_t (*show_setspeed) (struct cpufreq_policy *policy,
char *buf); char *buf);
int (*store_setspeed) (struct cpufreq_policy *policy, int (*store_setspeed) (struct cpufreq_policy *policy,
...@@ -493,6 +500,14 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor); ...@@ -493,6 +500,14 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor);
struct cpufreq_governor *cpufreq_default_governor(void); struct cpufreq_governor *cpufreq_default_governor(void);
struct cpufreq_governor *cpufreq_fallback_governor(void); struct cpufreq_governor *cpufreq_fallback_governor(void);
static inline void cpufreq_policy_apply_limits(struct cpufreq_policy *policy)
{
if (policy->max < policy->cur)
__cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
else if (policy->min > policy->cur)
__cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
}
/* Governor attribute set */ /* Governor attribute set */
struct gov_attr_set { struct gov_attr_set {
struct kobject kobj; struct kobject kobj;
...@@ -583,10 +598,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, ...@@ -583,10 +598,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy); int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation, unsigned int relation);
unsigned int *index);
int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
unsigned int freq); unsigned int freq);
...@@ -617,8 +630,6 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy) ...@@ -617,8 +630,6 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
return false; return false;
} }
#endif #endif
/* the following funtion is for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
/* the following are really really optional */ /* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
......
...@@ -394,7 +394,7 @@ static int sugov_init(struct cpufreq_policy *policy) ...@@ -394,7 +394,7 @@ static int sugov_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
static int sugov_exit(struct cpufreq_policy *policy) static void sugov_exit(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
struct sugov_tunables *tunables = sg_policy->tunables; struct sugov_tunables *tunables = sg_policy->tunables;
...@@ -412,7 +412,6 @@ static int sugov_exit(struct cpufreq_policy *policy) ...@@ -412,7 +412,6 @@ static int sugov_exit(struct cpufreq_policy *policy)
mutex_unlock(&global_tunables_lock); mutex_unlock(&global_tunables_lock);
sugov_policy_free(sg_policy); sugov_policy_free(sg_policy);
return 0;
} }
static int sugov_start(struct cpufreq_policy *policy) static int sugov_start(struct cpufreq_policy *policy)
...@@ -444,7 +443,7 @@ static int sugov_start(struct cpufreq_policy *policy) ...@@ -444,7 +443,7 @@ static int sugov_start(struct cpufreq_policy *policy)
return 0; return 0;
} }
static int sugov_stop(struct cpufreq_policy *policy) static void sugov_stop(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
unsigned int cpu; unsigned int cpu;
...@@ -456,53 +455,29 @@ static int sugov_stop(struct cpufreq_policy *policy) ...@@ -456,53 +455,29 @@ static int sugov_stop(struct cpufreq_policy *policy)
irq_work_sync(&sg_policy->irq_work); irq_work_sync(&sg_policy->irq_work);
cancel_work_sync(&sg_policy->work); cancel_work_sync(&sg_policy->work);
return 0;
} }
static int sugov_limits(struct cpufreq_policy *policy) static void sugov_limits(struct cpufreq_policy *policy)
{ {
struct sugov_policy *sg_policy = policy->governor_data; struct sugov_policy *sg_policy = policy->governor_data;
if (!policy->fast_switch_enabled) { if (!policy->fast_switch_enabled) {
mutex_lock(&sg_policy->work_lock); mutex_lock(&sg_policy->work_lock);
cpufreq_policy_apply_limits(policy);
if (policy->max < policy->cur)
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
else if (policy->min > policy->cur)
__cpufreq_driver_target(policy, policy->min,
CPUFREQ_RELATION_L);
mutex_unlock(&sg_policy->work_lock); mutex_unlock(&sg_policy->work_lock);
} }
sg_policy->need_freq_update = true; sg_policy->need_freq_update = true;
return 0;
}
int sugov_governor(struct cpufreq_policy *policy, unsigned int event)
{
if (event == CPUFREQ_GOV_POLICY_INIT) {
return sugov_init(policy);
} else if (policy->governor_data) {
switch (event) {
case CPUFREQ_GOV_POLICY_EXIT:
return sugov_exit(policy);
case CPUFREQ_GOV_START:
return sugov_start(policy);
case CPUFREQ_GOV_STOP:
return sugov_stop(policy);
case CPUFREQ_GOV_LIMITS:
return sugov_limits(policy);
}
}
return -EINVAL;
} }
static struct cpufreq_governor schedutil_gov = { static struct cpufreq_governor schedutil_gov = {
.name = "schedutil", .name = "schedutil",
.governor = sugov_governor,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.init = sugov_init,
.exit = sugov_exit,
.start = sugov_start,
.stop = sugov_stop,
.limits = sugov_limits,
}; };
static int __init sugov_module_init(void) static int __init sugov_module_init(void)
......
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