diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 620ab220feff..5f0f983ce173 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -130,6 +130,7 @@ static void handle_update(struct work_struct *work); */ static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); static struct srcu_notifier_head cpufreq_transition_notifier_list; +struct atomic_notifier_head cpufreq_govinfo_notifier_list; static bool init_cpufreq_transition_notifier_list_called; static int __init init_cpufreq_transition_notifier_list(void) @@ -140,6 +141,15 @@ static int __init init_cpufreq_transition_notifier_list(void) } pure_initcall(init_cpufreq_transition_notifier_list); +static bool init_cpufreq_govinfo_notifier_list_called; +static int __init init_cpufreq_govinfo_notifier_list(void) +{ + ATOMIC_INIT_NOTIFIER_HEAD(&cpufreq_govinfo_notifier_list); + init_cpufreq_govinfo_notifier_list_called = true; + return 0; +} +pure_initcall(init_cpufreq_govinfo_notifier_list); + static int off __read_mostly; static int cpufreq_disabled(void) { @@ -1095,7 +1105,8 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp if (has_target()) { ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); if (ret) { - pr_err("%s: Failed to stop governor\n", __func__); + pr_err("%s: Failed to stop governor for CPU%u, policy CPU%u\n", + __func__, cpu, policy->cpu); return ret; } } @@ -1110,7 +1121,8 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); if (ret) { - pr_err("%s: Failed to start governor\n", __func__); + pr_err("%s: Failed to start governor for CPU%u, policy CPU%u\n", + __func__, cpu, policy->cpu); return ret; } } @@ -1423,7 +1435,8 @@ static void cpufreq_offline_prepare(unsigned int cpu) if (has_target()) { int ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); if (ret) - pr_err("%s: Failed to stop governor\n", __func__); + pr_err("%s: Failed to stop governor for CPU%u\n", + __func__, cpu); } down_write(&policy->rwsem); @@ -1473,7 +1486,8 @@ static void cpufreq_offline_finish(unsigned int cpu) if (has_target()) { int ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); if (ret) - pr_err("%s: Failed to exit governor\n", __func__); + pr_err("%s: Failed to start governor for CPU%u, policy CPU%u\n", + __func__, cpu, policy->cpu); } /* @@ -1802,7 +1816,8 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) if (cpufreq_disabled()) return -EINVAL; - WARN_ON(!init_cpufreq_transition_notifier_list_called); + WARN_ON(!init_cpufreq_transition_notifier_list_called || + !init_cpufreq_govinfo_notifier_list_called); switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: @@ -1813,6 +1828,10 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) ret = blocking_notifier_chain_register( &cpufreq_policy_notifier_list, nb); break; + case CPUFREQ_GOVINFO_NOTIFIER: + ret = atomic_notifier_chain_register( + &cpufreq_govinfo_notifier_list, nb); + break; default: ret = -EINVAL; } @@ -1847,6 +1866,10 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) ret = blocking_notifier_chain_unregister( &cpufreq_policy_notifier_list, nb); break; + case CPUFREQ_GOVINFO_NOTIFIER: + ret = atomic_notifier_chain_unregister( + &cpufreq_govinfo_notifier_list, nb); + break; default: ret = -EINVAL; } @@ -1959,15 +1982,6 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n", policy->cpu, target_freq, relation, old_target_freq); - /* - * This might look like a redundant call as we are checking it again - * after finding index. But it is left intentionally for cases where - * exactly same freq is called again and so we can save on few function - * calls. - */ - if (target_freq == policy->cur) - return 0; - /* Save last value to restore later on errors */ policy->restore_freq = policy->cur; @@ -2356,6 +2370,9 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, { unsigned int cpu = (unsigned long)hcpu; + if (!cpufreq_driver) + return NOTIFY_OK; + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: cpufreq_online(cpu); @@ -2522,6 +2539,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) pr_debug("trying to register driver %s\n", driver_data->name); + /* Register for hotplug notifers before blocking hotplug. */ + register_hotcpu_notifier(&cpufreq_cpu_notifier); + /* Protect against concurrent CPU online/offline. */ get_online_cpus(); @@ -2554,8 +2574,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) goto err_if_unreg; } - register_hotcpu_notifier(&cpufreq_cpu_notifier); - pr_debug("driver %s up and running\n", driver_data->name); + pr_info("driver %s up and running\n", driver_data->name); out: put_online_cpus(); @@ -2588,7 +2607,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) if (!cpufreq_driver || (driver != cpufreq_driver)) return -EINVAL; - pr_debug("unregistering driver %s\n", driver->name); + pr_info("unregistering driver %s\n", driver->name); /* Protect against concurrent cpu hotplug */ get_online_cpus(); |