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 51002a700b39..ce93f49e03a0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -131,6 +131,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) @@ -141,6 +142,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) { @@ -1105,7 +1115,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; } } @@ -1120,7 +1131,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; } } @@ -1434,7 +1446,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); @@ -1484,7 +1497,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); } /* @@ -1816,7 +1830,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: @@ -1827,6 +1842,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; } @@ -1861,6 +1880,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; } @@ -1973,15 +1996,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; @@ -2365,6 +2379,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); @@ -2538,6 +2555,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(); @@ -2570,8 +2590,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(); @@ -2604,7 +2623,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(); |
