Commit 15afee3a authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge back earlier 'pm-cpufreq' material.

parents 2ed99e39 2449d33a
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
static void __init spear1310_dt_init(void) static void __init spear1310_dt_init(void)
{ {
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
} }
static const char * const spear1310_dt_board_compat[] = { static const char * const spear1310_dt_board_compat[] = {
......
...@@ -143,6 +143,7 @@ static void __init spear1340_dt_init(void) ...@@ -143,6 +143,7 @@ static void __init spear1340_dt_init(void)
{ {
of_platform_populate(NULL, of_default_bus_match_table, of_platform_populate(NULL, of_default_bus_match_table,
spear1340_auxdata_lookup, NULL); spear1340_auxdata_lookup, NULL);
platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
} }
static const char * const spear1340_dt_board_compat[] = { static const char * const spear1340_dt_board_compat[] = {
......
...@@ -303,6 +303,14 @@ source "drivers/cpuidle/Kconfig" ...@@ -303,6 +303,14 @@ source "drivers/cpuidle/Kconfig"
endmenu endmenu
menu "Power management options"
source "kernel/power/Kconfig"
source "drivers/cpufreq/Kconfig"
endmenu
source "net/Kconfig" source "net/Kconfig"
source "drivers/Kconfig" source "drivers/Kconfig"
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/async.h> #include <linux/async.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <trace/events/power.h> #include <trace/events/power.h>
#include <linux/cpufreq.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/timer.h> #include <linux/timer.h>
...@@ -789,6 +790,8 @@ void dpm_resume(pm_message_t state) ...@@ -789,6 +790,8 @@ void dpm_resume(pm_message_t state)
mutex_unlock(&dpm_list_mtx); mutex_unlock(&dpm_list_mtx);
async_synchronize_full(); async_synchronize_full();
dpm_show_time(starttime, state, NULL); dpm_show_time(starttime, state, NULL);
cpufreq_resume();
} }
/** /**
...@@ -1259,6 +1262,8 @@ int dpm_suspend(pm_message_t state) ...@@ -1259,6 +1262,8 @@ int dpm_suspend(pm_message_t state)
might_sleep(); might_sleep();
cpufreq_suspend();
mutex_lock(&dpm_list_mtx); mutex_lock(&dpm_list_mtx);
pm_transition = state; pm_transition = state;
async_error = 0; async_error = 0;
......
...@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86" ...@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86"
endmenu endmenu
menu "ARM CPU frequency scaling drivers" menu "ARM CPU frequency scaling drivers"
depends on ARM depends on ARM || ARM64
source "drivers/cpufreq/Kconfig.arm" source "drivers/cpufreq/Kconfig.arm"
endmenu endmenu
......
...@@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
pr_debug("acpi_cpufreq_cpu_exit\n"); pr_debug("acpi_cpufreq_cpu_exit\n");
if (data) { if (data) {
cpufreq_frequency_table_put_attr(policy->cpu);
per_cpu(acfreq_data, policy->cpu) = NULL; per_cpu(acfreq_data, policy->cpu) = NULL;
acpi_processor_unregister_performance(data->acpi_data, acpi_processor_unregister_performance(data->acpi_data,
policy->cpu); policy->cpu);
......
...@@ -478,7 +478,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) ...@@ -478,7 +478,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
return -ENODEV; return -ENODEV;
} }
cpufreq_frequency_table_put_attr(policy->cpu);
put_cluster_clk_and_freq_table(cpu_dev); put_cluster_clk_and_freq_table(cpu_dev);
dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu); dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
......
...@@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = { ...@@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = {
.target_index = bfin_target, .target_index = bfin_target,
.get = bfin_getfreq_khz, .get = bfin_getfreq_khz,
.init = __bfin_cpu_init, .init = __bfin_cpu_init,
.exit = cpufreq_generic_exit,
.name = "bfin cpufreq", .name = "bfin cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = { ...@@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
.target_index = cpu0_set_target, .target_index = cpu0_set_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = cpu0_cpufreq_init, .init = cpu0_cpufreq_init,
.exit = cpufreq_generic_exit,
.name = "generic_cpu0", .name = "generic_cpu0",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/syscore_ops.h> #include <linux/suspend.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <trace/events/power.h> #include <trace/events/power.h>
...@@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock); ...@@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock);
DEFINE_MUTEX(cpufreq_governor_lock); DEFINE_MUTEX(cpufreq_governor_lock);
static LIST_HEAD(cpufreq_policy_list); static LIST_HEAD(cpufreq_policy_list);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */ /* This one keeps track of the previously set governor of a removed CPU */
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
#endif
/* Flag to suspend/resume CPUFreq governors */
static bool cpufreq_suspended;
static inline bool has_target(void) static inline bool has_target(void)
{ {
...@@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu) ...@@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
if (!policy || IS_ERR(policy->clk)) { if (!policy || IS_ERR(policy->clk)) {
pr_err("%s: No %s associated to cpu: %d\n", __func__, pr_err("%s: No %s associated to cpu: %d\n",
policy ? "clk" : "policy", cpu); __func__, policy ? "clk" : "policy", cpu);
return 0; return 0;
} }
...@@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu) ...@@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
} }
EXPORT_SYMBOL_GPL(cpufreq_generic_get); EXPORT_SYMBOL_GPL(cpufreq_generic_get);
/* Only for cpufreq core internal use */
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
{
return per_cpu(cpufreq_cpu_data, cpu);
}
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{ {
struct cpufreq_policy *policy = NULL; struct cpufreq_policy *policy = NULL;
...@@ -254,15 +261,15 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) ...@@ -254,15 +261,15 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
if (!l_p_j_ref_freq) { if (!l_p_j_ref_freq) {
l_p_j_ref = loops_per_jiffy; l_p_j_ref = loops_per_jiffy;
l_p_j_ref_freq = ci->old; l_p_j_ref_freq = ci->old;
pr_debug("saving %lu as reference value for loops_per_jiffy; " pr_debug("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n",
"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq); l_p_j_ref, l_p_j_ref_freq);
} }
if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) || if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
ci->new); ci->new);
pr_debug("scaling loops_per_jiffy to %lu " pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n",
"for frequency %u kHz\n", loops_per_jiffy, ci->new); loops_per_jiffy, ci->new);
} }
} }
#else #else
...@@ -294,8 +301,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -294,8 +301,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((policy) && (policy->cpu == freqs->cpu) && if ((policy) && (policy->cpu == freqs->cpu) &&
(policy->cur) && (policy->cur != freqs->old)) { (policy->cur) && (policy->cur != freqs->old)) {
pr_debug("Warning: CPU frequency is" pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
" %u, cpufreq assumed %u kHz.\n",
freqs->old, policy->cur); freqs->old, policy->cur);
freqs->old = policy->cur; freqs->old = policy->cur;
} }
...@@ -307,8 +313,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, ...@@ -307,8 +313,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, pr_debug("FREQ: %lu - CPU: %lu\n",
(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);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list, srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs); CPUFREQ_POSTCHANGE, freqs);
...@@ -352,7 +358,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); ...@@ -352,7 +358,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
/********************************************************************* /*********************************************************************
* SYSFS INTERFACE * * SYSFS INTERFACE *
*********************************************************************/ *********************************************************************/
ssize_t show_boost(struct kobject *kobj, static ssize_t show_boost(struct kobject *kobj,
struct attribute *attr, char *buf) struct attribute *attr, char *buf)
{ {
return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
...@@ -368,13 +374,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, ...@@ -368,13 +374,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
return -EINVAL; return -EINVAL;
if (cpufreq_boost_trigger_state(enable)) { if (cpufreq_boost_trigger_state(enable)) {
pr_err("%s: Cannot %s BOOST!\n", __func__, pr_err("%s: Cannot %s BOOST!\n",
enable ? "enable" : "disable"); __func__, enable ? "enable" : "disable");
return -EINVAL; return -EINVAL;
} }
pr_debug("%s: cpufreq BOOST %s\n", __func__, pr_debug("%s: cpufreq BOOST %s\n",
enable ? "enabled" : "disabled"); __func__, enable ? "enabled" : "disabled");
return count; return count;
} }
...@@ -879,18 +885,25 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, ...@@ -879,18 +885,25 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
static void cpufreq_init_policy(struct cpufreq_policy *policy) static void cpufreq_init_policy(struct cpufreq_policy *policy)
{ {
struct cpufreq_governor *gov = NULL;
struct cpufreq_policy new_policy; struct cpufreq_policy new_policy;
int ret = 0; int ret = 0;
memcpy(&new_policy, policy, sizeof(*policy)); memcpy(&new_policy, policy, sizeof(*policy));
/* Update governor of new_policy to the governor used before hotplug */
gov = __find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu));
if (gov)
pr_debug("Restoring governor %s for cpu %d\n",
policy->governor->name, policy->cpu);
else
gov = CPUFREQ_DEFAULT_GOVERNOR;
new_policy.governor = gov;
/* Use the default policy if its valid. */ /* Use the default policy if its valid. */
if (cpufreq_driver->setpolicy) if (cpufreq_driver->setpolicy)
cpufreq_parse_governor(policy->governor->name, cpufreq_parse_governor(gov->name, &new_policy.policy, NULL);
&new_policy.policy, NULL);
/* assure that the starting sequence is run in cpufreq_set_policy */
policy->governor = NULL;
/* set default policy */ /* set default policy */
ret = cpufreq_set_policy(policy, &new_policy); ret = cpufreq_set_policy(policy, &new_policy);
...@@ -949,6 +962,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) ...@@ -949,6 +962,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
read_unlock_irqrestore(&cpufreq_driver_lock, flags); read_unlock_irqrestore(&cpufreq_driver_lock, flags);
policy->governor = NULL;
return policy; return policy;
} }
...@@ -1022,21 +1037,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) ...@@ -1022,21 +1037,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
up_write(&policy->rwsem); up_write(&policy->rwsem);
cpufreq_frequency_table_update_policy_cpu(policy);
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_UPDATE_POLICY_CPU, policy); CPUFREQ_UPDATE_POLICY_CPU, policy);
} }
static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int j, cpu = dev->id; unsigned int j, cpu = dev->id;
int ret = -ENOMEM; int ret = -ENOMEM;
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
unsigned long flags; unsigned long flags;
bool recover_policy = cpufreq_suspended;
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
struct cpufreq_policy *tpolicy; struct cpufreq_policy *tpolicy;
struct cpufreq_governor *gov;
#endif #endif
if (cpu_is_offline(cpu)) if (cpu_is_offline(cpu))
...@@ -1075,9 +1088,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1075,9 +1088,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
* Restore the saved policy when doing light-weight init and fall back * Restore the saved policy when doing light-weight init and fall back
* to the full init if that fails. * to the full init if that fails.
*/ */
policy = frozen ? cpufreq_policy_restore(cpu) : NULL; policy = recover_policy ? cpufreq_policy_restore(cpu) : NULL;
if (!policy) { if (!policy) {
frozen = false; recover_policy = false;
policy = cpufreq_policy_alloc(); policy = cpufreq_policy_alloc();
if (!policy) if (!policy)
goto nomem_out; goto nomem_out;
...@@ -1089,12 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1089,12 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
* the creation of a brand new one. So we need to perform this update * the creation of a brand new one. So we need to perform this update
* by invoking update_policy_cpu(). * by invoking update_policy_cpu().
*/ */
if (frozen && cpu != policy->cpu) if (recover_policy && cpu != policy->cpu)
update_policy_cpu(policy, cpu); update_policy_cpu(policy, cpu);
else else
policy->cpu = cpu; policy->cpu = cpu;
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
cpumask_copy(policy->cpus, cpumask_of(cpu)); cpumask_copy(policy->cpus, cpumask_of(cpu));
init_completion(&policy->kobj_unregister); init_completion(&policy->kobj_unregister);
...@@ -1118,7 +1130,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1118,7 +1130,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
*/ */
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
if (!frozen) { if (!recover_policy) {
policy->user_policy.min = policy->min; policy->user_policy.min = policy->min;
policy->user_policy.max = policy->max; policy->user_policy.max = policy->max;
} }
...@@ -1180,16 +1192,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1180,16 +1192,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy); CPUFREQ_START, policy);
#ifdef CONFIG_HOTPLUG_CPU if (!recover_policy) {
gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
if (gov) {
policy->governor = gov;
pr_debug("Restoring governor %s for cpu %d\n",
policy->governor->name, cpu);
}
#endif
if (!frozen) {
ret = cpufreq_add_dev_interface(policy, dev); ret = cpufreq_add_dev_interface(policy, dev);
if (ret) if (ret)
goto err_out_unregister; goto err_out_unregister;
...@@ -1203,7 +1206,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1203,7 +1206,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
cpufreq_init_policy(policy); cpufreq_init_policy(policy);
if (!frozen) { if (!recover_policy) {
policy->user_policy.policy = policy->policy; policy->user_policy.policy = policy->policy;
policy->user_policy.governor = policy->governor; policy->user_policy.governor = policy->governor;
} }
...@@ -1226,7 +1229,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1226,7 +1229,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
if (cpufreq_driver->exit) if (cpufreq_driver->exit)
cpufreq_driver->exit(policy); cpufreq_driver->exit(policy);
err_set_policy_cpu: err_set_policy_cpu:
if (frozen) { if (recover_policy) {
/* Do not leave stale fallback data behind. */ /* Do not leave stale fallback data behind. */
per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL; per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
cpufreq_policy_put_kobj(policy); cpufreq_policy_put_kobj(policy);
...@@ -1250,7 +1253,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ...@@ -1250,7 +1253,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
*/ */
static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
{ {
return __cpufreq_add_dev(dev, sif, false); return __cpufreq_add_dev(dev, sif);
} }
static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
...@@ -1265,7 +1268,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, ...@@ -1265,7 +1268,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
ret = kobject_move(&policy->kobj, &cpu_dev->kobj); ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
if (ret) { if (ret) {
pr_err("%s: Failed to move kobj: %d", __func__, ret); pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
down_write(&policy->rwsem); down_write(&policy->rwsem);
cpumask_set_cpu(old_cpu, policy->cpus); cpumask_set_cpu(old_cpu, policy->cpus);
...@@ -1281,8 +1284,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, ...@@ -1281,8 +1284,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
} }
static int __cpufreq_remove_dev_prepare(struct device *dev, static int __cpufreq_remove_dev_prepare(struct device *dev,
struct subsys_interface *sif, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int cpu = dev->id, cpus; unsigned int cpu = dev->id, cpus;
int new_cpu, ret; int new_cpu, ret;
...@@ -1296,7 +1298,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1296,7 +1298,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
policy = per_cpu(cpufreq_cpu_data, cpu); policy = per_cpu(cpufreq_cpu_data, cpu);
/* Save the policy somewhere when doing a light-weight tear-down */ /* Save the policy somewhere when doing a light-weight tear-down */
if (frozen) if (cpufreq_suspended)
per_cpu(cpufreq_cpu_data_fallback, cpu) = policy; per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
...@@ -1314,11 +1316,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1314,11 +1316,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
} }
} }
#ifdef CONFIG_HOTPLUG_CPU
if (!cpufreq_driver->setpolicy) if (!cpufreq_driver->setpolicy)
strncpy(per_cpu(cpufreq_cpu_governor, cpu), strncpy(per_cpu(cpufreq_cpu_governor, cpu),
policy->governor->name, CPUFREQ_NAME_LEN); policy->governor->name, CPUFREQ_NAME_LEN);
#endif
down_read(&policy->rwsem); down_read(&policy->rwsem);
cpus = cpumask_weight(policy->cpus); cpus = cpumask_weight(policy->cpus);
...@@ -1331,7 +1331,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1331,7 +1331,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
if (new_cpu >= 0) { if (new_cpu >= 0) {
update_policy_cpu(policy, new_cpu); update_policy_cpu(policy, new_cpu);
if (!frozen) { if (!cpufreq_suspended) {
pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
__func__, new_cpu, cpu); __func__, new_cpu, cpu);
} }
...@@ -1342,8 +1342,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, ...@@ -1342,8 +1342,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
} }
static int __cpufreq_remove_dev_finish(struct device *dev, static int __cpufreq_remove_dev_finish(struct device *dev,
struct subsys_interface *sif, struct subsys_interface *sif)
bool frozen)
{ {
unsigned int cpu = dev->id, cpus; unsigned int cpu = dev->id, cpus;
int ret; int ret;
...@@ -1378,7 +1377,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, ...@@ -1378,7 +1377,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
} }
} }
if (!frozen) if (!cpufreq_suspended)
cpufreq_policy_put_kobj(policy); cpufreq_policy_put_kobj(policy);
/* /*
...@@ -1394,7 +1393,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev, ...@@ -1394,7 +1393,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
list_del(&policy->policy_list); list_del(&policy->policy_list);
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (!frozen) if (!cpufreq_suspended)
cpufreq_policy_free(policy); cpufreq_policy_free(policy);
} else { } else {
if (has_target()) { if (has_target()) {
...@@ -1424,10 +1423,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) ...@@ -1424,10 +1423,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
if (cpu_is_offline(cpu)) if (cpu_is_offline(cpu))
return 0; return 0;
ret = __cpufreq_remove_dev_prepare(dev, sif, false); ret = __cpufreq_remove_dev_prepare(dev, sif);
if (!ret) if (!ret)
ret = __cpufreq_remove_dev_finish(dev, sif, false); ret = __cpufreq_remove_dev_finish(dev, sif);
return ret; return ret;
} }
...@@ -1458,8 +1457,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, ...@@ -1458,8 +1457,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
unsigned long flags; unsigned long flags;
pr_debug("Warning: CPU frequency out of sync: cpufreq and timing " pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n",
"core thinks of %u, is %u kHz.\n", old_freq, new_freq); old_freq, new_freq);
freqs.old = old_freq; freqs.old = old_freq;
freqs.new = new_freq; freqs.new = new_freq;
...@@ -1570,83 +1569,104 @@ static struct subsys_interface cpufreq_interface = { ...@@ -1570,83 +1569,104 @@ static struct subsys_interface cpufreq_interface = {
.remove_dev = cpufreq_remove_dev, .remove_dev = cpufreq_remove_dev,
}; };
/*
* In case platform wants some specific frequency to be configured
* during suspend..
*/
int cpufreq_generic_suspend(struct cpufreq_policy *policy)
{
int ret;
if (!policy->suspend_freq) {
pr_err("%s: suspend_freq can't be zero\n", __func__);
return -EINVAL;
}
pr_debug("%s: Setting suspend-freq: %u\n", __func__,
policy->suspend_freq);
ret = __cpufreq_driver_target(policy, policy->suspend_freq,
CPUFREQ_RELATION_H);
if (ret)
pr_err("%s: unable to set suspend-freq: %u. err: %d\n",
__func__, policy->suspend_freq, ret);
return ret;
}
EXPORT_SYMBOL(cpufreq_generic_suspend);
/** /**
* cpufreq_bp_suspend - Prepare the boot CPU for system suspend. * cpufreq_suspend() - Suspend CPUFreq governors
* *
* This function is only executed for the boot processor. The other CPUs * Called during system wide Suspend/Hibernate cycles for suspending governors
* have been put offline by means of CPU hotplug. * as some platforms can't change frequency after this point in suspend cycle.
* Because some of the devices (like: i2c, regulators, etc) they use for
* changing frequency are suspended quickly after this point.
*/ */
static int cpufreq_bp_suspend(void) void cpufreq_suspend(void)
{ {
int ret = 0;
int cpu = smp_processor_id();
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
pr_debug("suspending cpu %u\n", cpu); if (!cpufreq_driver)
return;
/* If there's no policy for the boot CPU, we have nothing to do. */ if (!has_target())
policy = cpufreq_cpu_get(cpu); return;
if (!policy)
return 0;
if (cpufreq_driver->suspend) { pr_debug("%s: Suspending Governors\n", __func__);
ret = cpufreq_driver->suspend(policy);
if (ret) list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
printk(KERN_ERR "cpufreq: suspend failed in ->suspend " if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
"step on CPU %u\n", policy->cpu); pr_err("%s: Failed to stop governor for policy: %p\n",
__func__, policy);
else if (cpufreq_driver->suspend
&& cpufreq_driver->suspend(policy))
pr_err("%s: Failed to suspend driver: %p\n", __func__,
policy);
} }
cpufreq_cpu_put(policy); cpufreq_suspended = true;
return ret;
} }
/** /**
* cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. * cpufreq_resume() - Resume CPUFreq governors
*
* 1.) resume CPUfreq hardware support (cpufreq_driver->resume())
* 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
* restored. It will verify that the current freq is in sync with
* what we believe it to be. This is a bit later than when it
* should be, but nonethteless it's better than calling
* cpufreq_driver->get() here which might re-enable interrupts...
* *
* This function is only executed for the boot CPU. The other CPUs have not * Called during system wide Suspend/Hibernate cycle for resuming governors that
* been turned on yet. * are suspended with cpufreq_suspend().
*/ */
static void cpufreq_bp_resume(void) void cpufreq_resume(void)
{ {
int ret = 0;
int cpu = smp_processor_id();
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
pr_debug("resuming cpu %u\n", cpu); if (!cpufreq_driver)
return;
/* If there's no policy for the boot CPU, we have nothing to do. */ if (!has_target())
policy = cpufreq_cpu_get(cpu);
if (!policy)
return; return;
if (cpufreq_driver->resume) { pr_debug("%s: Resuming Governors\n", __func__);
ret = cpufreq_driver->resume(policy);
if (ret) {
printk(KERN_ERR "cpufreq: resume failed in ->resume "
"step on CPU %u\n", policy->cpu);
goto fail;
}
}
schedule_work(&policy->update); cpufreq_suspended = false;
fail: list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
cpufreq_cpu_put(policy); if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
} || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
pr_err("%s: Failed to start governor for policy: %p\n",
__func__, policy);
else if (cpufreq_driver->resume
&& cpufreq_driver->resume(policy))
pr_err("%s: Failed to resume driver: %p\n", __func__,
policy);
static struct syscore_ops cpufreq_syscore_ops = { /*
.suspend = cpufreq_bp_suspend, * schedule call cpufreq_update_policy() for boot CPU, i.e. last
.resume = cpufreq_bp_resume, * policy in list. It will verify that the current freq is in
}; * sync with what we believe it to be.
*/
if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
schedule_work(&policy->update);
}
}
/** /**
* cpufreq_get_current_driver - return current driver's name * cpufreq_get_current_driver - return current driver's name
...@@ -1807,8 +1827,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1807,8 +1827,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
freqs.flags = 0; freqs.flags = 0;
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, __func__, policy->cpu, freqs.old, freqs.new);
freqs.new);
cpufreq_notify_transition(policy, &freqs, cpufreq_notify_transition(policy, &freqs,
CPUFREQ_PRECHANGE); CPUFREQ_PRECHANGE);
...@@ -1863,17 +1882,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, ...@@ -1863,17 +1882,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
struct cpufreq_governor *gov = NULL; struct cpufreq_governor *gov = NULL;
#endif #endif
/* Don't start any governor operations if we are entering suspend */
if (cpufreq_suspended)
return 0;
if (policy->governor->max_transition_latency && if (policy->governor->max_transition_latency &&
policy->cpuinfo.transition_latency > policy->cpuinfo.transition_latency >
policy->governor->max_transition_latency) { policy->governor->max_transition_latency) {
if (!gov) if (!gov)
return -EINVAL; return -EINVAL;
else { else {
printk(KERN_WARNING "%s governor failed, too long" pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
" transition latency of HW, fallback" policy->governor->name, gov->name);
" to %s governor\n",
policy->governor->name,
gov->name);
policy->governor = gov; policy->governor = gov;
} }
} }
...@@ -1950,9 +1970,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor); ...@@ -1950,9 +1970,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor);
void cpufreq_unregister_governor(struct cpufreq_governor *governor) void cpufreq_unregister_governor(struct cpufreq_governor *governor)
{ {
#ifdef CONFIG_HOTPLUG_CPU
int cpu; int cpu;
#endif
if (!governor) if (!governor)
return; return;
...@@ -1960,14 +1978,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor) ...@@ -1960,14 +1978,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
if (cpufreq_disabled()) if (cpufreq_disabled())
return; return;
#ifdef CONFIG_HOTPLUG_CPU
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
if (cpu_online(cpu)) if (cpu_online(cpu))
continue; continue;
if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name)) if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0"); strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
} }
#endif
mutex_lock(&cpufreq_governor_mutex); mutex_lock(&cpufreq_governor_mutex);
list_del(&governor->governor_list); list_del(&governor->governor_list);
...@@ -2012,22 +2028,21 @@ EXPORT_SYMBOL(cpufreq_get_policy); ...@@ -2012,22 +2028,21 @@ EXPORT_SYMBOL(cpufreq_get_policy);
static int cpufreq_set_policy(struct cpufreq_policy *policy, static int cpufreq_set_policy(struct cpufreq_policy *policy,
struct cpufreq_policy *new_policy) struct cpufreq_policy *new_policy)
{ {
int ret = 0, failed = 1; struct cpufreq_governor *old_gov;
int ret;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
new_policy->min, new_policy->max); new_policy->cpu, new_policy->min, new_policy->max);
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
if (new_policy->min > policy->max || new_policy->max < policy->min) { if (new_policy->min > policy->max || new_policy->max < policy->min)
ret = -EINVAL; return -EINVAL;
goto error_out;
}
/* verify the cpu speed can be set within this limit */ /* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(new_policy); ret = cpufreq_driver->verify(new_policy);
if (ret) if (ret)
goto error_out; return ret;
/* adjust if necessary - all reasons */ /* adjust if necessary - all reasons */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
...@@ -2043,7 +2058,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2043,7 +2058,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
*/ */
ret = cpufreq_driver->verify(new_policy); ret = cpufreq_driver->verify(new_policy);
if (ret) if (ret)
goto error_out; return ret;
/* notification of the new policy */ /* notification of the new policy */
blocking_notifier_call_chain(&cpufreq_policy_notifier_list, blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
...@@ -2058,58 +2073,48 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, ...@@ -2058,58 +2073,48 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
if (cpufreq_driver->setpolicy) { if (cpufreq_driver->setpolicy) {
policy->policy = new_policy->policy; policy->policy = new_policy->policy;
pr_debug("setting range\n"); pr_debug("setting range\n");
ret = cpufreq_driver->setpolicy(new_policy); return cpufreq_driver->setpolicy(new_policy);
} else { }
if (new_policy->governor != policy->governor) {
/* save old, working values */ if (new_policy->governor == policy->governor)
struct cpufreq_governor *old_gov = policy->governor; goto out;
pr_debug("governor switch\n"); pr_debug("governor switch\n");
/* save old, working values */
old_gov = policy->governor;
/* end old governor */ /* end old governor */
if (policy->governor) { if (old_gov) {
__cpufreq_governor(policy, CPUFREQ_GOV_STOP); __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
up_write(&policy->rwsem); up_write(&policy->rwsem);
__cpufreq_governor(policy, __cpufreq_governor(policy,CPUFREQ_GOV_POLICY_EXIT);
CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem); down_write(&policy->rwsem);
} }
/* start new governor */ /* start new governor */
policy->governor = new_policy->governor; policy->governor = new_policy->governor;
if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) { if (!__cpufreq_governor(policy, CPUFREQ_GOV_START))
failed = 0; goto out;
} else {
up_write(&policy->rwsem); up_write(&policy->rwsem);
__cpufreq_governor(policy, __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
CPUFREQ_GOV_POLICY_EXIT);
down_write(&policy->rwsem); down_write(&policy->rwsem);
} }
}
if (failed) {
/* new governor failed, so re-start old one */ /* new governor failed, so re-start old one */
pr_debug("starting governor %s failed\n", pr_debug("starting governor %s failed\n", policy->governor->name);
policy->governor->name);
if (old_gov) { if (old_gov) {
policy->governor = old_gov; policy->governor = old_gov;
__cpufreq_governor(policy, __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
CPUFREQ_GOV_POLICY_INIT); __cpufreq_governor(policy, CPUFREQ_GOV_START);
__cpufreq_governor(policy,
CPUFREQ_GOV_START);
}
ret = -EINVAL;
goto error_out;
}
/* might be a policy change, too, so fall through */
}
pr_debug("governor: change or update limits\n");
ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
} }
error_out: return -EINVAL;
return ret;
out:
pr_debug("governor: change or update limits\n");
return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
} }
/** /**
...@@ -2145,8 +2150,13 @@ int cpufreq_update_policy(unsigned int cpu) ...@@ -2145,8 +2150,13 @@ int cpufreq_update_policy(unsigned int cpu)
*/ */
if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
new_policy.cur = cpufreq_driver->get(cpu); new_policy.cur = cpufreq_driver->get(cpu);
if (WARN_ON(!new_policy.cur)) {
ret = -EIO;
goto no_policy;
}
if (!policy->cur) { if (!policy->cur) {
pr_debug("Driver did not initialize current freq"); pr_debug("Driver did not initialize current freq\n");
policy->cur = new_policy.cur; policy->cur = new_policy.cur;
} else { } else {
if (policy->cur != new_policy.cur && has_target()) if (policy->cur != new_policy.cur && has_target())
...@@ -2170,30 +2180,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, ...@@ -2170,30 +2180,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
{ {
unsigned int cpu = (unsigned long)hcpu; unsigned int cpu = (unsigned long)hcpu;
struct device *dev; struct device *dev;
bool frozen = false;
dev = get_cpu_device(cpu); dev = get_cpu_device(cpu);
if (dev) { if (dev) {
if (action & CPU_TASKS_FROZEN)
frozen = true;
switch (action & ~CPU_TASKS_FROZEN) { switch (action & ~CPU_TASKS_FROZEN) {
case CPU_ONLINE: case CPU_ONLINE:
__cpufreq_add_dev(dev, NULL, frozen); __cpufreq_add_dev(dev, NULL);
cpufreq_update_policy(cpu);
break; break;
case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE:
__cpufreq_remove_dev_prepare(dev, NULL, frozen); __cpufreq_remove_dev_prepare(dev, NULL);
break; break;
case CPU_POST_DEAD: case CPU_POST_DEAD:
__cpufreq_remove_dev_finish(dev, NULL, frozen); __cpufreq_remove_dev_finish(dev, NULL);
break; break;
case CPU_DOWN_FAILED: case CPU_DOWN_FAILED:
__cpufreq_add_dev(dev, NULL, frozen); __cpufreq_add_dev(dev, NULL);
break; break;
} }
} }
...@@ -2249,8 +2253,8 @@ int cpufreq_boost_trigger_state(int state) ...@@ -2249,8 +2253,8 @@ int cpufreq_boost_trigger_state(int state)
cpufreq_driver->boost_enabled = !state; cpufreq_driver->boost_enabled = !state;
write_unlock_irqrestore(&cpufreq_driver_lock, flags); write_unlock_irqrestore(&cpufreq_driver_lock, flags);
pr_err("%s: Cannot %s BOOST\n", __func__, pr_err("%s: Cannot %s BOOST\n",
state ? "enable" : "disable"); __func__, state ? "enable" : "disable");
} }
return ret; return ret;
...@@ -2409,7 +2413,6 @@ static int __init cpufreq_core_init(void) ...@@ -2409,7 +2413,6 @@ static int __init cpufreq_core_init(void)
cpufreq_global_kobject = kobject_create(); cpufreq_global_kobject = kobject_create();
BUG_ON(!cpufreq_global_kobject); BUG_ON(!cpufreq_global_kobject);
register_syscore_ops(&cpufreq_syscore_ops);
return 0; return 0;
} }
......
...@@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu) ...@@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu)
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
} }
static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
struct cpufreq_frequency_table *table)
{ {
unsigned int i, j, count = 0, ret = 0; unsigned int i, j, count = 0, ret = 0;
struct cpufreq_stats *stat; struct cpufreq_stats *stat;
struct cpufreq_policy *current_policy;
unsigned int alloc_size; unsigned int alloc_size;
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct cpufreq_frequency_table *table;
table = cpufreq_frequency_get_table(cpu);
if (unlikely(!table))
return 0;
if (per_cpu(cpufreq_stats_table, cpu)) if (per_cpu(cpufreq_stats_table, cpu))
return -EBUSY; return -EBUSY;
stat = kzalloc(sizeof(*stat), GFP_KERNEL); stat = kzalloc(sizeof(*stat), GFP_KERNEL);
if ((stat) == NULL) if ((stat) == NULL)
return -ENOMEM; return -ENOMEM;
current_policy = cpufreq_cpu_get(cpu); ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
if (current_policy == NULL) {
ret = -EINVAL;
goto error_get_fail;
}
ret = sysfs_create_group(&current_policy->kobj, &stats_attr_group);
if (ret) if (ret)
goto error_out; goto error_out;
...@@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL); stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
if (!stat->time_in_state) { if (!stat->time_in_state) {
ret = -ENOMEM; ret = -ENOMEM;
goto error_out; goto error_alloc;
} }
stat->freq_table = (unsigned int *)(stat->time_in_state + count); stat->freq_table = (unsigned int *)(stat->time_in_state + count);
...@@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
stat->last_time = get_jiffies_64(); stat->last_time = get_jiffies_64();
stat->last_index = freq_table_get_index(stat, policy->cur); stat->last_index = freq_table_get_index(stat, policy->cur);
spin_unlock(&cpufreq_stats_lock); spin_unlock(&cpufreq_stats_lock);
cpufreq_cpu_put(current_policy);
return 0; return 0;
error_alloc:
sysfs_remove_group(&policy->kobj, &stats_attr_group);
error_out: error_out:
cpufreq_cpu_put(current_policy);
error_get_fail:
kfree(stat); kfree(stat);
per_cpu(cpufreq_stats_table, cpu) = NULL; per_cpu(cpufreq_stats_table, cpu) = NULL;
return ret; return ret;
...@@ -256,7 +253,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, ...@@ -256,7 +253,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
static void cpufreq_stats_create_table(unsigned int cpu) static void cpufreq_stats_create_table(unsigned int cpu)
{ {
struct cpufreq_policy *policy; struct cpufreq_policy *policy;
struct cpufreq_frequency_table *table;
/* /*
* "likely(!policy)" because normally cpufreq_stats will be registered * "likely(!policy)" because normally cpufreq_stats will be registered
...@@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu) ...@@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu)
if (likely(!policy)) if (likely(!policy))
return; return;
table = cpufreq_frequency_get_table(policy->cpu); __cpufreq_stats_create_table(policy);
if (likely(table))
__cpufreq_stats_create_table(policy, table);
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
} }
...@@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, ...@@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
{ {
int ret = 0; int ret = 0;
struct cpufreq_policy *policy = data; struct cpufreq_policy *policy = data;
struct cpufreq_frequency_table *table;
unsigned int cpu = policy->cpu;
if (val == CPUFREQ_UPDATE_POLICY_CPU) { if (val == CPUFREQ_UPDATE_POLICY_CPU) {
cpufreq_stats_update_policy_cpu(policy); cpufreq_stats_update_policy_cpu(policy);
return 0; return 0;
} }
table = cpufreq_frequency_get_table(cpu);
if (!table)
return 0;
if (val == CPUFREQ_CREATE_POLICY) if (val == CPUFREQ_CREATE_POLICY)
ret = __cpufreq_stats_create_table(policy, table); ret = __cpufreq_stats_create_table(policy);
else if (val == CPUFREQ_REMOVE_POLICY) else if (val == CPUFREQ_REMOVE_POLICY)
__cpufreq_stats_free_table(policy); __cpufreq_stats_free_table(policy);
......
...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { ...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cris_freq_target, .target_index = cris_freq_target,
.init = cris_freq_cpu_init, .init = cris_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cris_freq", .name = "cris_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = { ...@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cris_freq_target, .target_index = cris_freq_target,
.init = cris_freq_cpu_init, .init = cris_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cris_freq", .name = "cris_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = { ...@@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = {
.target_index = davinci_target, .target_index = davinci_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = davinci_cpu_init, .init = davinci_cpu_init,
.exit = cpufreq_generic_exit,
.name = "davinci", .name = "davinci",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy) ...@@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
/* Bye */ /* Bye */
cpufreq_frequency_table_put_attr(policy->cpu);
kfree(eps_cpu[cpu]); kfree(eps_cpu[cpu]);
eps_cpu[cpu] = NULL; eps_cpu[cpu] = NULL;
return 0; return 0;
......
...@@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = { ...@@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = elanfreq_target, .target_index = elanfreq_target,
.init = elanfreq_cpu_init, .init = elanfreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "elanfreq", .name = "elanfreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/suspend.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <plat/cpu.h> #include <plat/cpu.h>
...@@ -24,12 +23,8 @@ ...@@ -24,12 +23,8 @@
#include "exynos-cpufreq.h" #include "exynos-cpufreq.h"
static struct exynos_dvfs_info *exynos_info; static struct exynos_dvfs_info *exynos_info;
static struct regulator *arm_regulator; static struct regulator *arm_regulator;
static unsigned int locking_frequency; static unsigned int locking_frequency;
static bool frequency_locked;
static DEFINE_MUTEX(cpufreq_lock);
static int exynos_cpufreq_get_index(unsigned int freq) static int exynos_cpufreq_get_index(unsigned int freq)
{ {
...@@ -134,83 +129,13 @@ static int exynos_cpufreq_scale(unsigned int target_freq) ...@@ -134,83 +129,13 @@ static int exynos_cpufreq_scale(unsigned int target_freq)
static int exynos_target(struct cpufreq_policy *policy, unsigned int index) static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
{ {
struct cpufreq_frequency_table *freq_table = exynos_info->freq_table; return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
int ret = 0;
mutex_lock(&cpufreq_lock);
if (frequency_locked)
goto out;
ret = exynos_cpufreq_scale(freq_table[index].frequency);
out:
mutex_unlock(&cpufreq_lock);
return ret;
}
#ifdef CONFIG_PM
static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
{
return 0;
}
static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
{
return 0;
}
#endif
/**
* exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
* context
* @notifier
* @pm_event
* @v
*
* While frequency_locked == true, target() ignores every frequency but
* locking_frequency. The locking_frequency value is the initial frequency,
* which is set by the bootloader. In order to eliminate possible
* inconsistency in clock values, we save and restore frequencies during
* suspend and resume and block CPUFREQ activities. Note that the standard
* suspend/resume cannot be used as they are too deep (syscore_ops) for
* regulator actions.
*/
static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
unsigned long pm_event, void *v)
{
int ret;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
mutex_lock(&cpufreq_lock);
frequency_locked = true;
mutex_unlock(&cpufreq_lock);
ret = exynos_cpufreq_scale(locking_frequency);
if (ret < 0)
return NOTIFY_BAD;
break;
case PM_POST_SUSPEND:
mutex_lock(&cpufreq_lock);
frequency_locked = false;
mutex_unlock(&cpufreq_lock);
break;
}
return NOTIFY_OK;
} }
static struct notifier_block exynos_cpufreq_nb = {
.notifier_call = exynos_cpufreq_pm_notifier,
};
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy) static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{ {
policy->clk = exynos_info->cpu_clk; policy->clk = exynos_info->cpu_clk;
policy->suspend_freq = locking_frequency;
return cpufreq_generic_init(policy, exynos_info->freq_table, 100000); return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
} }
...@@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = { ...@@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = {
.target_index = exynos_target, .target_index = exynos_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init, .init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "exynos_cpufreq", .name = "exynos_cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
#ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
.boost_supported = true, .boost_supported = true,
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = exynos_cpufreq_suspend, .suspend = cpufreq_generic_suspend,
.resume = exynos_cpufreq_resume,
#endif #endif
}; };
...@@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
goto err_vdd_arm; goto err_vdd_arm;
} }
/* Done here as we want to capture boot frequency */
locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000; locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
register_pm_notifier(&exynos_cpufreq_nb); if (!cpufreq_register_driver(&exynos_driver))
if (cpufreq_register_driver(&exynos_driver)) {
pr_err("%s: failed to register cpufreq driver\n", __func__);
goto err_cpufreq;
}
return 0; return 0;
err_cpufreq:
unregister_pm_notifier(&exynos_cpufreq_nb);
pr_err("%s: failed to register cpufreq driver\n", __func__);
regulator_put(arm_regulator); regulator_put(arm_regulator);
err_vdd_arm: err_vdd_arm:
kfree(exynos_info); kfree(exynos_info);
......
...@@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = { ...@@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = {
.target_index = exynos_target, .target_index = exynos_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = exynos_cpufreq_cpu_init, .init = exynos_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = CPUFREQ_NAME, .name = CPUFREQ_NAME,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, ...@@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
/* /*
* Generic routine to verify policy & frequency table, requires driver to call * Generic routine to verify policy & frequency table, requires driver to set
* cpufreq_frequency_table_get_attr() prior to it. * policy->freq_table prior to it.
*/ */
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy) int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
{ {
...@@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, ...@@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index); EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/** /**
* show_available_freqs - show available frequencies for the specified CPU * show_available_freqs - show available frequencies for the specified CPU
*/ */
...@@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf, ...@@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
bool show_boost) bool show_boost)
{ {
unsigned int i = 0; unsigned int i = 0;
unsigned int cpu = policy->cpu;
ssize_t count = 0; ssize_t count = 0;
struct cpufreq_frequency_table *table; struct cpufreq_frequency_table *table = policy->freq_table;
if (!per_cpu(cpufreq_show_table, cpu)) if (!table)
return -ENODEV; return -ENODEV;
table = per_cpu(cpufreq_show_table, cpu);
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID) if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue; continue;
...@@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = { ...@@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = {
}; };
EXPORT_SYMBOL_GPL(cpufreq_generic_attr); EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
*/
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu)
{
pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
per_cpu(cpufreq_show_table, cpu) = table;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
pr_debug("clearing show_table for cpu %u\n", cpu);
per_cpu(cpufreq_show_table, cpu) = NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table) struct cpufreq_frequency_table *table)
{ {
int ret = cpufreq_frequency_table_cpuinfo(policy, table); int ret = cpufreq_frequency_table_cpuinfo(policy, table);
if (!ret) if (!ret)
cpufreq_frequency_table_get_attr(table, policy->cpu); policy->freq_table = table;
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy) struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
{
pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
policy->cpu, policy->last_cpu);
per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table,
policy->last_cpu);
per_cpu(cpufreq_show_table, policy->last_cpu) = NULL;
}
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{ {
return per_cpu(cpufreq_show_table, cpu); struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
return policy ? policy->freq_table : NULL;
} }
EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
......
...@@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit ( ...@@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit (
pr_debug("acpi_cpufreq_cpu_exit\n"); pr_debug("acpi_cpufreq_cpu_exit\n");
if (data) { if (data) {
cpufreq_frequency_table_put_attr(policy->cpu);
acpi_io_data[policy->cpu] = NULL; acpi_io_data[policy->cpu] = NULL;
acpi_processor_unregister_performance(&data->acpi_data, acpi_processor_unregister_performance(&data->acpi_data,
policy->cpu); policy->cpu);
......
...@@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { ...@@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
.target_index = imx6q_set_target, .target_index = imx6q_set_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = imx6q_cpufreq_init, .init = imx6q_cpufreq_init,
.exit = cpufreq_generic_exit,
.name = "imx6q-cpufreq", .name = "imx6q-cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -99,8 +99,7 @@ struct cpudata { ...@@ -99,8 +99,7 @@ struct cpudata {
u64 prev_aperf; u64 prev_aperf;
u64 prev_mperf; u64 prev_mperf;
unsigned long long prev_tsc; unsigned long long prev_tsc;
int sample_ptr; struct sample sample;
struct sample samples[SAMPLE_COUNT];
}; };
static struct cpudata **all_cpu_data; static struct cpudata **all_cpu_data;
...@@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy, ...@@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
pid->setpoint = setpoint; pid->setpoint = setpoint;
pid->deadband = deadband; pid->deadband = deadband;
pid->integral = int_tofp(integral); pid->integral = int_tofp(integral);
pid->last_err = setpoint - busy; pid->last_err = int_tofp(setpoint) - int_tofp(busy);
} }
static inline void pid_p_gain_set(struct _pid *pid, int percent) static inline void pid_p_gain_set(struct _pid *pid, int percent)
...@@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu) ...@@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
mperf = mperf >> FRAC_BITS; mperf = mperf >> FRAC_BITS;
tsc = tsc >> FRAC_BITS; tsc = tsc >> FRAC_BITS;
cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; cpu->sample.aperf = aperf;
cpu->samples[cpu->sample_ptr].aperf = aperf; cpu->sample.mperf = mperf;
cpu->samples[cpu->sample_ptr].mperf = mperf; cpu->sample.tsc = tsc;
cpu->samples[cpu->sample_ptr].tsc = tsc; cpu->sample.aperf -= cpu->prev_aperf;
cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; cpu->sample.mperf -= cpu->prev_mperf;
cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; cpu->sample.tsc -= cpu->prev_tsc;
cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc;
intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); intel_pstate_calc_busy(cpu, &cpu->sample);
cpu->prev_aperf = aperf; cpu->prev_aperf = aperf;
cpu->prev_mperf = mperf; cpu->prev_mperf = mperf;
...@@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) ...@@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
{ {
int32_t core_busy, max_pstate, current_pstate; int32_t core_busy, max_pstate, current_pstate;
core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; core_busy = cpu->sample.core_pct_busy;
max_pstate = int_tofp(cpu->pstate.max_pstate); max_pstate = int_tofp(cpu->pstate.max_pstate);
current_pstate = int_tofp(cpu->pstate.current_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate);
core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
...@@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data) ...@@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data)
intel_pstate_sample(cpu); intel_pstate_sample(cpu);
sample = &cpu->samples[cpu->sample_ptr]; sample = &cpu->sample;
intel_pstate_adjust_busy_pstate(cpu); intel_pstate_adjust_busy_pstate(cpu);
...@@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num) ...@@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
cpu = all_cpu_data[cpu_num]; cpu = all_cpu_data[cpu_num];
if (!cpu) if (!cpu)
return 0; return 0;
sample = &cpu->samples[cpu->sample_ptr]; sample = &cpu->sample;
return sample->freq; return sample->freq;
} }
......
...@@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = { ...@@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = kirkwood_cpufreq_target, .target_index = kirkwood_cpufreq_target,
.init = kirkwood_cpufreq_cpu_init, .init = kirkwood_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "kirkwood-cpufreq", .name = "kirkwood-cpufreq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = { ...@@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = {
.target_index = longhaul_target, .target_index = longhaul_target,
.get = longhaul_get, .get = longhaul_get,
.init = longhaul_cpu_init, .init = longhaul_cpu_init,
.exit = cpufreq_generic_exit,
.name = "longhaul", .name = "longhaul",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
static int loongson2_cpufreq_exit(struct cpufreq_policy *policy) static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
clk_put(policy->clk); clk_put(policy->clk);
return 0; return 0;
} }
......
...@@ -143,7 +143,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy) ...@@ -143,7 +143,6 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
static int omap_cpu_exit(struct cpufreq_policy *policy) static int omap_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
freq_table_free(); freq_table_free();
clk_put(policy->clk); clk_put(policy->clk);
return 0; return 0;
......
...@@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = { ...@@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cpufreq_p4_target, .target_index = cpufreq_p4_target,
.init = cpufreq_p4_cpu_init, .init = cpufreq_p4_cpu_init,
.exit = cpufreq_generic_exit,
.get = cpufreq_p4_get, .get = cpufreq_p4_get,
.name = "p4-clockmod", .name = "p4-clockmod",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
......
...@@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
if (sdcpwr_mapbase) if (sdcpwr_mapbase)
iounmap(sdcpwr_mapbase); iounmap(sdcpwr_mapbase);
cpufreq_frequency_table_put_attr(policy->cpu);
return 0; return 0;
} }
......
...@@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy) ...@@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
if (i == max_multiplier) if (i == max_multiplier)
powernow_k6_target(policy, i); powernow_k6_target(policy, i);
} }
cpufreq_frequency_table_put_attr(policy->cpu);
return 0; return 0;
} }
......
...@@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) ...@@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
static int powernow_cpu_exit(struct cpufreq_policy *policy) static int powernow_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
#ifdef CONFIG_X86_POWERNOW_K7_ACPI #ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (acpi_processor_perf) { if (acpi_processor_perf) {
acpi_processor_unregister_performance(acpi_processor_perf, 0); acpi_processor_unregister_performance(acpi_processor_perf, 0);
......
...@@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) ...@@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
powernow_k8_cpu_exit_acpi(data); powernow_k8_cpu_exit_acpi(data);
cpufreq_frequency_table_put_attr(pol->cpu);
kfree(data->powernow_table); kfree(data->powernow_table);
kfree(data); kfree(data);
for_each_cpu(cpu, pol->cpus) for_each_cpu(cpu, pol->cpus)
......
...@@ -228,7 +228,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -228,7 +228,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
struct cpu_data *data = per_cpu(cpu_data, policy->cpu); struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
unsigned int cpu; unsigned int cpu;
cpufreq_frequency_table_put_attr(policy->cpu);
of_node_put(data->parent); of_node_put(data->parent);
kfree(data->table); kfree(data->table);
kfree(data); kfree(data);
......
...@@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = { ...@@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = cbe_cpufreq_target, .target_index = cbe_cpufreq_target,
.init = cbe_cpufreq_cpu_init, .init = cbe_cpufreq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "cbe-cpufreq", .name = "cbe-cpufreq",
.flags = CPUFREQ_CONST_LOOPS, .flags = CPUFREQ_CONST_LOOPS,
}; };
......
...@@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = { ...@@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = pxa_set_target, .target_index = pxa_set_target,
.init = pxa_cpufreq_init, .init = pxa_cpufreq_init,
.exit = cpufreq_generic_exit,
.get = pxa_cpufreq_get, .get = pxa_cpufreq_get,
.name = "PXA2xx", .name = "PXA2xx",
}; };
......
...@@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = { ...@@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = pxa3xx_cpufreq_set, .target_index = pxa3xx_cpufreq_set,
.init = pxa3xx_cpufreq_init, .init = pxa3xx_cpufreq_init,
.exit = cpufreq_generic_exit,
.get = pxa3xx_cpufreq_get, .get = pxa3xx_cpufreq_get,
.name = "pxa3xx-cpufreq", .name = "pxa3xx-cpufreq",
}; };
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/suspend.h>
#include <mach/map.h> #include <mach/map.h>
#include <mach/regs-clock.h> #include <mach/regs-clock.h>
...@@ -435,18 +434,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) ...@@ -435,18 +434,6 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
return ret; return ret;
} }
#ifdef CONFIG_PM
static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
{
return 0;
}
static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
{
return 0;
}
#endif
static int check_mem_type(void __iomem *dmc_reg) static int check_mem_type(void __iomem *dmc_reg)
{ {
unsigned long val; unsigned long val;
...@@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
policy->suspend_freq = SLEEP_FREQ;
return cpufreq_generic_init(policy, s5pv210_freq_table, 40000); return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
out_dmc1: out_dmc1:
...@@ -511,32 +499,6 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) ...@@ -511,32 +499,6 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int ret;
switch (event) {
case PM_SUSPEND_PREPARE:
ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
if (ret < 0)
return NOTIFY_BAD;
/* Disable updation of cpu frequency */
no_cpufreq_access = true;
return NOTIFY_OK;
case PM_POST_RESTORE:
case PM_POST_SUSPEND:
/* Enable updation of cpu frequency */
no_cpufreq_access = false;
cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
...@@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = { ...@@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = {
.init = s5pv210_cpu_init, .init = s5pv210_cpu_init,
.name = "s5pv210", .name = "s5pv210",
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = s5pv210_cpufreq_suspend, .suspend = cpufreq_generic_suspend,
.resume = s5pv210_cpufreq_resume, .resume = cpufreq_generic_suspend, /* We need to set SLEEP FREQ again */
#endif #endif
}; };
static struct notifier_block s5pv210_cpufreq_notifier = {
.notifier_call = s5pv210_cpufreq_notifier_event,
};
static struct notifier_block s5pv210_cpufreq_reboot_notifier = { static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
.notifier_call = s5pv210_cpufreq_reboot_notifier_event, .notifier_call = s5pv210_cpufreq_reboot_notifier_event,
}; };
...@@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void) ...@@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void)
return PTR_ERR(int_regulator); return PTR_ERR(int_regulator);
} }
register_pm_notifier(&s5pv210_cpufreq_notifier);
register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
return cpufreq_register_driver(&s5pv210_driver); return cpufreq_register_driver(&s5pv210_driver);
......
...@@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = { ...@@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = sc520_freq_target, .target_index = sc520_freq_target,
.init = sc520_freq_cpu_init, .init = sc520_freq_cpu_init,
.exit = cpufreq_generic_exit,
.name = "sc520_freq", .name = "sc520_freq",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu); struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
cpufreq_frequency_table_put_attr(cpu);
clk_put(cpuclk); clk_put(cpuclk);
return 0; return 0;
......
...@@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
static int us2e_freq_cpu_exit(struct cpufreq_policy *policy) static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
{ {
if (cpufreq_us2e_driver) { if (cpufreq_us2e_driver)
cpufreq_frequency_table_put_attr(policy->cpu);
us2e_freq_target(policy, 0); us2e_freq_target(policy, 0);
}
return 0; return 0;
} }
......
...@@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
static int us3_freq_cpu_exit(struct cpufreq_policy *policy) static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
{ {
if (cpufreq_us3_driver) { if (cpufreq_us3_driver)
cpufreq_frequency_table_put_attr(policy->cpu);
us3_freq_target(policy, 0); us3_freq_target(policy, 0);
}
return 0; return 0;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = { ...@@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = {
.target_index = spear_cpufreq_target, .target_index = spear_cpufreq_target,
.get = cpufreq_generic_get, .get = cpufreq_generic_get,
.init = spear_cpufreq_init, .init = spear_cpufreq_init,
.exit = cpufreq_generic_exit,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
static int spear_cpufreq_driver_init(void) static int spear_cpufreq_probe(struct platform_device *pdev)
{ {
struct device_node *np; struct device_node *np;
const struct property *prop; const struct property *prop;
...@@ -235,7 +235,15 @@ static int spear_cpufreq_driver_init(void) ...@@ -235,7 +235,15 @@ static int spear_cpufreq_driver_init(void)
of_node_put(np); of_node_put(np);
return ret; return ret;
} }
late_initcall(spear_cpufreq_driver_init);
static struct platform_driver spear_cpufreq_platdrv = {
.driver = {
.name = "spear-cpufreq",
.owner = THIS_MODULE,
},
.probe = spear_cpufreq_probe,
};
module_platform_driver(spear_cpufreq_platdrv);
MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>"); MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
MODULE_DESCRIPTION("SPEAr CPUFreq driver"); MODULE_DESCRIPTION("SPEAr CPUFreq driver");
......
...@@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) ...@@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
if (!per_cpu(centrino_model, cpu)) if (!per_cpu(centrino_model, cpu))
return -ENODEV; return -ENODEV;
cpufreq_frequency_table_put_attr(cpu);
per_cpu(centrino_model, cpu) = NULL; per_cpu(centrino_model, cpu) = NULL;
return 0; return 0;
......
...@@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = speedstep_target, .target_index = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.exit = cpufreq_generic_exit,
.get = speedstep_get, .get = speedstep_get,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = { ...@@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = {
.verify = cpufreq_generic_frequency_table_verify, .verify = cpufreq_generic_frequency_table_verify,
.target_index = speedstep_target, .target_index = speedstep_target,
.init = speedstep_cpu_init, .init = speedstep_cpu_init,
.exit = cpufreq_generic_exit,
.get = speedstep_get, .get = speedstep_get,
.resume = speedstep_resume, .resume = speedstep_resume,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/suspend.h>
static struct cpufreq_frequency_table freq_table[] = { static struct cpufreq_frequency_table freq_table[] = {
{ .frequency = 216000 }, { .frequency = 216000 },
...@@ -47,9 +46,6 @@ static struct clk *pll_x_clk; ...@@ -47,9 +46,6 @@ static struct clk *pll_x_clk;
static struct clk *pll_p_clk; static struct clk *pll_p_clk;
static struct clk *emc_clk; static struct clk *emc_clk;
static DEFINE_MUTEX(tegra_cpu_lock);
static bool is_suspended;
static int tegra_cpu_clk_set_rate(unsigned long rate) static int tegra_cpu_clk_set_rate(unsigned long rate)
{ {
int ret; int ret;
...@@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy, ...@@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
static int tegra_target(struct cpufreq_policy *policy, unsigned int index) static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
{ {
int ret = -EBUSY; return tegra_update_cpu_speed(policy, freq_table[index].frequency);
mutex_lock(&tegra_cpu_lock);
if (!is_suspended)
ret = tegra_update_cpu_speed(policy,
freq_table[index].frequency);
mutex_unlock(&tegra_cpu_lock);
return ret;
} }
static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
{
mutex_lock(&tegra_cpu_lock);
if (event == PM_SUSPEND_PREPARE) {
struct cpufreq_policy *policy = cpufreq_cpu_get(0);
is_suspended = true;
pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
freq_table[0].frequency);
if (clk_get_rate(cpu_clk) / 1000 != freq_table[0].frequency)
tegra_update_cpu_speed(policy, freq_table[0].frequency);
cpufreq_cpu_put(policy);
} else if (event == PM_POST_SUSPEND) {
is_suspended = false;
}
mutex_unlock(&tegra_cpu_lock);
return NOTIFY_OK;
}
static struct notifier_block tegra_cpu_pm_notifier = {
.notifier_call = tegra_pm_notify,
};
static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_init(struct cpufreq_policy *policy)
{ {
int ret; int ret;
...@@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) ...@@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
if (policy->cpu == 0)
register_pm_notifier(&tegra_cpu_pm_notifier);
policy->clk = cpu_clk; policy->clk = cpu_clk;
policy->suspend_freq = freq_table[0].frequency;
return 0; return 0;
} }
static int tegra_cpu_exit(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_put_attr(policy->cpu);
clk_disable_unprepare(cpu_clk); clk_disable_unprepare(cpu_clk);
clk_disable_unprepare(emc_clk); clk_disable_unprepare(emc_clk);
return 0; return 0;
...@@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = { ...@@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
.exit = tegra_cpu_exit, .exit = tegra_cpu_exit,
.name = "tegra", .name = "tegra",
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
#ifdef CONFIG_PM
.suspend = cpufreq_generic_suspend,
#endif
}; };
static int __init tegra_cpufreq_init(void) static int __init tegra_cpufreq_init(void)
......
...@@ -74,6 +74,8 @@ struct cpufreq_policy { ...@@ -74,6 +74,8 @@ struct cpufreq_policy {
unsigned int max; /* in kHz */ unsigned int max; /* in kHz */
unsigned int cur; /* in kHz, only needed if cpufreq unsigned int cur; /* in kHz, only needed if cpufreq
* governors are used */ * governors are used */
unsigned int suspend_freq; /* freq to set during suspend */
unsigned int policy; /* see above */ unsigned int policy; /* see above */
struct cpufreq_governor *governor; /* see below */ struct cpufreq_governor *governor; /* see below */
void *governor_data; void *governor_data;
...@@ -83,6 +85,7 @@ struct cpufreq_policy { ...@@ -83,6 +85,7 @@ struct cpufreq_policy {
* called, but you're in IRQ context */ * called, but you're in IRQ context */
struct cpufreq_real_policy user_policy; struct cpufreq_real_policy user_policy;
struct cpufreq_frequency_table *freq_table;
struct list_head policy_list; struct list_head policy_list;
struct kobject kobj; struct kobject kobj;
...@@ -296,6 +299,15 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) ...@@ -296,6 +299,15 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq); policy->cpuinfo.max_freq);
} }
#ifdef CONFIG_CPU_FREQ
void cpufreq_suspend(void);
void cpufreq_resume(void);
int cpufreq_generic_suspend(struct cpufreq_policy *policy);
#else
static inline void cpufreq_suspend(void) {}
static inline void cpufreq_resume(void) {}
#endif
/********************************************************************* /*********************************************************************
* CPUFREQ NOTIFIER INTERFACE * * CPUFREQ NOTIFIER INTERFACE *
*********************************************************************/ *********************************************************************/
...@@ -463,7 +475,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, ...@@ -463,7 +475,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
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);
void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
...@@ -490,9 +501,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); ...@@ -490,9 +501,6 @@ 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;
extern struct freq_attr *cpufreq_generic_attr[]; extern struct freq_attr *cpufreq_generic_attr[];
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
void cpufreq_frequency_table_put_attr(unsigned int cpu);
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table); struct cpufreq_frequency_table *table);
...@@ -500,10 +508,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu); ...@@ -500,10 +508,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu);
int cpufreq_generic_init(struct cpufreq_policy *policy, int cpufreq_generic_init(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table, struct cpufreq_frequency_table *table,
unsigned int transition_latency); unsigned int transition_latency);
static inline int cpufreq_generic_exit(struct cpufreq_policy *policy)
{
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
#endif /* _LINUX_CPUFREQ_H */ #endif /* _LINUX_CPUFREQ_H */
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