Loading drivers/cpufreq/amd-pstate.c +2 −5 Original line number Diff line number Diff line Loading @@ -821,19 +821,16 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) schedule_work(&sched_prefcore_work); } static void amd_pstate_update_limits(unsigned int cpu) static void amd_pstate_update_limits(struct cpufreq_policy *policy) { struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); struct amd_cpudata *cpudata; u32 prev_high = 0, cur_high = 0; bool highest_perf_changed = false; unsigned int cpu = policy->cpu; if (!amd_pstate_prefcore) return; if (!policy) return; if (amd_get_highest_perf(cpu, &cur_high)) return; Loading drivers/cpufreq/cpufreq.c +149 −196 Original line number Diff line number Diff line Loading @@ -255,51 +255,6 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(cpufreq_cpu_put); /** * cpufreq_cpu_release - Unlock a policy and decrement its usage counter. * @policy: cpufreq policy returned by cpufreq_cpu_acquire(). */ void cpufreq_cpu_release(struct cpufreq_policy *policy) { if (WARN_ON(!policy)) return; lockdep_assert_held(&policy->rwsem); up_write(&policy->rwsem); cpufreq_cpu_put(policy); } /** * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it. * @cpu: CPU to find the policy for. * * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and * if the policy returned by it is not NULL, acquire its rwsem for writing. * Return the policy if it is active or release it and return NULL otherwise. * * The policy returned by this function has to be released with the help of * cpufreq_cpu_release() in order to release its rwsem and balance its usage * counter properly. */ struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); if (!policy) return NULL; down_write(&policy->rwsem); if (policy_is_inactive(policy)) { cpufreq_cpu_release(policy); return NULL; } return policy; } /********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/ Loading Loading @@ -1009,17 +964,16 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EBUSY; if (!fattr->show) return -EIO; down_read(&policy->rwsem); guard(cpufreq_policy_read)(policy); if (likely(!policy_is_inactive(policy))) ret = fattr->show(policy, buf); up_read(&policy->rwsem); return fattr->show(policy, buf); return ret; return -EBUSY; } static ssize_t store(struct kobject *kobj, struct attribute *attr, Loading @@ -1027,17 +981,16 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EBUSY; if (!fattr->store) return -EIO; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); if (likely(!policy_is_inactive(policy))) ret = fattr->store(policy, buf, count); up_write(&policy->rwsem); return fattr->store(policy, buf, count); return ret; return -EBUSY; } static void cpufreq_sysfs_release(struct kobject *kobj) Loading Loading @@ -1195,7 +1148,8 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp if (cpumask_test_cpu(cpu, policy->cpus)) return 0; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); if (has_target()) cpufreq_stop_governor(policy); Loading @@ -1206,7 +1160,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp if (ret) pr_err("%s: Failed to start governor\n", __func__); } up_write(&policy->rwsem); return ret; } Loading @@ -1226,9 +1180,10 @@ static void handle_update(struct work_struct *work) container_of(work, struct cpufreq_policy, update); pr_debug("handle_update for cpu %u called\n", policy->cpu); down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); refresh_frequency_limits(policy); up_write(&policy->rwsem); } static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq, Loading @@ -1254,11 +1209,11 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy) struct kobject *kobj; struct completion *cmp; down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { cpufreq_stats_free_table(policy); kobj = &policy->kobj; cmp = &policy->kobj_unregister; up_write(&policy->rwsem); } kobject_put(kobj); /* Loading Loading @@ -1334,7 +1289,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) init_waitqueue_head(&policy->transition_wait); INIT_WORK(&policy->update, handle_update); policy->cpu = cpu; return policy; err_min_qos_notifier: Loading Loading @@ -1403,35 +1357,17 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) kfree(policy); } static int cpufreq_online(unsigned int cpu) static int cpufreq_policy_online(struct cpufreq_policy *policy, unsigned int cpu, bool new_policy) { struct cpufreq_policy *policy; bool new_policy; unsigned long flags; unsigned int j; int ret; pr_debug("%s: bringing CPU%u online\n", __func__, cpu); /* Check if this CPU already has a policy to manage it */ policy = per_cpu(cpufreq_cpu_data, cpu); if (policy) { WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); if (!policy_is_inactive(policy)) return cpufreq_add_policy_cpu(policy, cpu); guard(cpufreq_policy_write)(policy); /* This is the only online CPU for the policy. Start over. */ new_policy = false; down_write(&policy->rwsem); policy->cpu = cpu; policy->governor = NULL; } else { new_policy = true; policy = cpufreq_policy_alloc(cpu); if (!policy) return -ENOMEM; down_write(&policy->rwsem); } if (!new_policy && cpufreq_driver->online) { /* Recover policy->cpus using related_cpus */ Loading @@ -1454,7 +1390,7 @@ static int cpufreq_online(unsigned int cpu) if (ret) { pr_debug("%s: %d: initialization failed\n", __func__, __LINE__); goto out_free_policy; goto out_clear_policy; } /* Loading Loading @@ -1605,7 +1541,55 @@ static int cpufreq_online(unsigned int cpu) goto out_destroy_policy; } up_write(&policy->rwsem); return 0; out_destroy_policy: for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, j, get_cpu_device(j)); out_offline_policy: if (cpufreq_driver->offline) cpufreq_driver->offline(policy); out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); out_clear_policy: cpumask_clear(policy->cpus); return ret; } static int cpufreq_online(unsigned int cpu) { struct cpufreq_policy *policy; bool new_policy; int ret; pr_debug("%s: bringing CPU%u online\n", __func__, cpu); /* Check if this CPU already has a policy to manage it */ policy = per_cpu(cpufreq_cpu_data, cpu); if (policy) { WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); if (!policy_is_inactive(policy)) return cpufreq_add_policy_cpu(policy, cpu); /* This is the only online CPU for the policy. Start over. */ new_policy = false; } else { new_policy = true; policy = cpufreq_policy_alloc(cpu); if (!policy) return -ENOMEM; } ret = cpufreq_policy_online(policy, cpu, new_policy); if (ret) { cpufreq_policy_free(policy); return ret; } kobject_uevent(&policy->kobj, KOBJ_ADD); Loading Loading @@ -1633,25 +1617,6 @@ static int cpufreq_online(unsigned int cpu) pr_debug("initialization complete\n"); return 0; out_destroy_policy: for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, j, get_cpu_device(j)); out_offline_policy: if (cpufreq_driver->offline) cpufreq_driver->offline(policy); out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); out_free_policy: cpumask_clear(policy->cpus); up_write(&policy->rwsem); cpufreq_policy_free(policy); return ret; } /** Loading Loading @@ -1741,11 +1706,10 @@ static int cpufreq_offline(unsigned int cpu) return 0; } down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); __cpufreq_offline(cpu, policy); up_write(&policy->rwsem); return 0; } Loading @@ -1762,21 +1726,18 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) if (!policy) return; down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { if (cpu_online(cpu)) __cpufreq_offline(cpu, policy); remove_cpu_dev_symlink(policy, cpu, dev); if (!cpumask_empty(policy->real_cpus)) { up_write(&policy->rwsem); if (!cpumask_empty(policy->real_cpus)) return; } /* * Unregister cpufreq cooling once all the CPUs of the policy are * removed. * Unregister cpufreq cooling once all the CPUs of the policy * are removed. */ if (cpufreq_thermal_control_enabled(cpufreq_driver)) { cpufreq_cooling_unregister(policy->cdev); Loading @@ -1786,8 +1747,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) /* We did light-weight exit earlier, do full tear down now */ if (cpufreq_driver->offline && cpufreq_driver->exit) cpufreq_driver->exit(policy); up_write(&policy->rwsem); } cpufreq_policy_free(policy); } Loading Loading @@ -1858,27 +1818,26 @@ static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, b */ unsigned int cpufreq_quick_get(unsigned int cpu) { struct cpufreq_policy *policy; unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; unsigned long flags; read_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) { ret_freq = cpufreq_driver->get(cpu); unsigned int ret_freq = cpufreq_driver->get(cpu); read_unlock_irqrestore(&cpufreq_driver_lock, flags); return ret_freq; } read_unlock_irqrestore(&cpufreq_driver_lock, flags); policy = cpufreq_cpu_get(cpu); if (policy) { ret_freq = policy->cur; cpufreq_cpu_put(policy); } if (policy) return policy->cur; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_quick_get); Loading @@ -1890,15 +1849,13 @@ EXPORT_SYMBOL(cpufreq_quick_get); */ unsigned int cpufreq_quick_get_max(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { ret_freq = policy->max; cpufreq_cpu_put(policy); } policy = cpufreq_cpu_get(cpu); if (policy) return policy->max; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_quick_get_max); Loading @@ -1910,15 +1867,13 @@ EXPORT_SYMBOL(cpufreq_quick_get_max); */ __weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { ret_freq = policy->cpuinfo.max_freq; cpufreq_cpu_put(policy); } policy = cpufreq_cpu_get(cpu); if (policy) return policy->cpuinfo.max_freq; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_get_hw_max_freq); Loading @@ -1938,19 +1893,18 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy) */ unsigned int cpufreq_get(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { down_read(&policy->rwsem); if (cpufreq_driver->get) ret_freq = __cpufreq_get(policy); up_read(&policy->rwsem); policy = cpufreq_cpu_get(cpu); if (!policy) return 0; cpufreq_cpu_put(policy); } guard(cpufreq_policy_read)(policy); return ret_freq; if (cpufreq_driver->get) return __cpufreq_get(policy); return 0; } EXPORT_SYMBOL(cpufreq_get); Loading Loading @@ -2009,9 +1963,9 @@ void cpufreq_suspend(void) for_each_active_policy(policy) { if (has_target()) { down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { cpufreq_stop_governor(policy); up_write(&policy->rwsem); } } if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy)) Loading Loading @@ -2052,9 +2006,9 @@ void cpufreq_resume(void) pr_err("%s: Failed to resume driver: %s\n", __func__, cpufreq_driver->name); } else if (has_target()) { down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { ret = cpufreq_start_governor(policy); up_write(&policy->rwsem); } if (ret) pr_err("%s: Failed to start governor for CPU%u's policy\n", Loading Loading @@ -2421,15 +2375,9 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { int ret; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); ret = __cpufreq_driver_target(policy, target_freq, relation); up_write(&policy->rwsem); return ret; return __cpufreq_driver_target(policy, target_freq, relation); } EXPORT_SYMBOL_GPL(cpufreq_driver_target); Loading Loading @@ -2611,7 +2559,8 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); */ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) { struct cpufreq_policy *cpu_policy; struct cpufreq_policy *cpu_policy __free(put_cpufreq_policy); if (!policy) return -EINVAL; Loading @@ -2621,7 +2570,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) memcpy(policy, cpu_policy, sizeof(*policy)); cpufreq_cpu_put(cpu_policy); return 0; } EXPORT_SYMBOL(cpufreq_get_policy); Loading Loading @@ -2769,6 +2717,21 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, return ret; } static void cpufreq_policy_refresh(struct cpufreq_policy *policy) { guard(cpufreq_policy_write)(policy); /* * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get && has_target() && (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false)))) return; refresh_frequency_limits(policy); } /** * cpufreq_update_policy - Re-evaluate an existing cpufreq policy. * @cpu: CPU to re-evaluate the policy for. Loading @@ -2780,23 +2743,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, */ void cpufreq_update_policy(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); struct cpufreq_policy *policy __free(put_cpufreq_policy); policy = cpufreq_cpu_get(cpu); if (!policy) return; /* * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get && has_target() && (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false)))) goto unlock; refresh_frequency_limits(policy); unlock: cpufreq_cpu_release(policy); cpufreq_policy_refresh(policy); } EXPORT_SYMBOL(cpufreq_update_policy); Loading @@ -2805,7 +2758,7 @@ EXPORT_SYMBOL(cpufreq_update_policy); * @cpu: CPU to update the policy limits for. * * Invoke the driver's ->update_limits callback if present or call * cpufreq_update_policy() for @cpu. * cpufreq_policy_refresh() for @cpu. */ void cpufreq_update_limits(unsigned int cpu) { Loading @@ -2816,9 +2769,9 @@ void cpufreq_update_limits(unsigned int cpu) return; if (cpufreq_driver->update_limits) cpufreq_driver->update_limits(cpu); cpufreq_driver->update_limits(policy); else cpufreq_update_policy(cpu); cpufreq_policy_refresh(policy); } EXPORT_SYMBOL_GPL(cpufreq_update_limits); Loading drivers/cpufreq/intel_pstate.c +18 −29 Original line number Diff line number Diff line Loading @@ -1353,9 +1353,11 @@ static void intel_pstate_update_policies(void) cpufreq_update_policy(cpu); } static void __intel_pstate_update_max_freq(struct cpudata *cpudata, struct cpufreq_policy *policy) static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy, struct cpudata *cpudata) { guard(cpufreq_policy_write)(policy); if (hwp_active) intel_pstate_get_hwp_cap(cpudata); Loading @@ -1365,42 +1367,34 @@ static void __intel_pstate_update_max_freq(struct cpudata *cpudata, refresh_frequency_limits(policy); } static void intel_pstate_update_limits(unsigned int cpu) static bool intel_pstate_update_max_freq(struct cpudata *cpudata) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); struct cpudata *cpudata; struct cpufreq_policy *policy __free(put_cpufreq_policy); policy = cpufreq_cpu_get(cpudata->cpu); if (!policy) return; return false; cpudata = all_cpu_data[cpu]; __intel_pstate_update_max_freq(policy, cpudata); __intel_pstate_update_max_freq(cpudata, policy); return true; } /* Prevent the driver from being unregistered now. */ mutex_lock(&intel_pstate_driver_lock); static void intel_pstate_update_limits(struct cpufreq_policy *policy) { struct cpudata *cpudata = all_cpu_data[policy->cpu]; cpufreq_cpu_release(policy); __intel_pstate_update_max_freq(policy, cpudata); hybrid_update_capacity(cpudata); mutex_unlock(&intel_pstate_driver_lock); } static void intel_pstate_update_limits_for_all(void) { int cpu; for_each_possible_cpu(cpu) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); if (!policy) continue; __intel_pstate_update_max_freq(all_cpu_data[cpu], policy); cpufreq_cpu_release(policy); } for_each_possible_cpu(cpu) intel_pstate_update_max_freq(all_cpu_data[cpu]); mutex_lock(&hybrid_capacity_lock); Loading Loading @@ -1840,13 +1834,8 @@ static void intel_pstate_notify_work(struct work_struct *work) { struct cpudata *cpudata = container_of(to_delayed_work(work), struct cpudata, hwp_notify_work); struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpudata->cpu); if (policy) { __intel_pstate_update_max_freq(cpudata, policy); cpufreq_cpu_release(policy); if (intel_pstate_update_max_freq(cpudata)) { /* * The driver will not be unregistered while this function is * running, so update the capacity without acquiring the driver Loading include/linux/cpufreq.h +7 −3 Original line number Diff line number Diff line Loading @@ -170,6 +170,12 @@ struct cpufreq_policy { struct notifier_block nb_max; }; DEFINE_GUARD(cpufreq_policy_write, struct cpufreq_policy *, down_write(&_T->rwsem), up_write(&_T->rwsem)) DEFINE_GUARD(cpufreq_policy_read, struct cpufreq_policy *, down_read(&_T->rwsem), up_read(&_T->rwsem)) /* * Used for passing new cpufreq policy data to the cpufreq driver's ->verify() * callback for sanitization. That callback is only expected to modify the min Loading Loading @@ -235,8 +241,6 @@ void disable_cpufreq(void); u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu); void cpufreq_cpu_release(struct cpufreq_policy *policy); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); void refresh_frequency_limits(struct cpufreq_policy *policy); void cpufreq_update_policy(unsigned int cpu); Loading Loading @@ -395,7 +399,7 @@ struct cpufreq_driver { unsigned int (*get)(unsigned int cpu); /* Called to update policy limits on firmware notifications. */ void (*update_limits)(unsigned int cpu); void (*update_limits)(struct cpufreq_policy *policy); /* optional */ int (*bios_limit)(int cpu, unsigned int *limit); Loading Loading
drivers/cpufreq/amd-pstate.c +2 −5 Original line number Diff line number Diff line Loading @@ -821,19 +821,16 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) schedule_work(&sched_prefcore_work); } static void amd_pstate_update_limits(unsigned int cpu) static void amd_pstate_update_limits(struct cpufreq_policy *policy) { struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); struct amd_cpudata *cpudata; u32 prev_high = 0, cur_high = 0; bool highest_perf_changed = false; unsigned int cpu = policy->cpu; if (!amd_pstate_prefcore) return; if (!policy) return; if (amd_get_highest_perf(cpu, &cur_high)) return; Loading
drivers/cpufreq/cpufreq.c +149 −196 Original line number Diff line number Diff line Loading @@ -255,51 +255,6 @@ void cpufreq_cpu_put(struct cpufreq_policy *policy) } EXPORT_SYMBOL_GPL(cpufreq_cpu_put); /** * cpufreq_cpu_release - Unlock a policy and decrement its usage counter. * @policy: cpufreq policy returned by cpufreq_cpu_acquire(). */ void cpufreq_cpu_release(struct cpufreq_policy *policy) { if (WARN_ON(!policy)) return; lockdep_assert_held(&policy->rwsem); up_write(&policy->rwsem); cpufreq_cpu_put(policy); } /** * cpufreq_cpu_acquire - Find policy for a CPU, mark it as busy and lock it. * @cpu: CPU to find the policy for. * * Call cpufreq_cpu_get() to get a reference on the cpufreq policy for @cpu and * if the policy returned by it is not NULL, acquire its rwsem for writing. * Return the policy if it is active or release it and return NULL otherwise. * * The policy returned by this function has to be released with the help of * cpufreq_cpu_release() in order to release its rwsem and balance its usage * counter properly. */ struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); if (!policy) return NULL; down_write(&policy->rwsem); if (policy_is_inactive(policy)) { cpufreq_cpu_release(policy); return NULL; } return policy; } /********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/ Loading Loading @@ -1009,17 +964,16 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EBUSY; if (!fattr->show) return -EIO; down_read(&policy->rwsem); guard(cpufreq_policy_read)(policy); if (likely(!policy_is_inactive(policy))) ret = fattr->show(policy, buf); up_read(&policy->rwsem); return fattr->show(policy, buf); return ret; return -EBUSY; } static ssize_t store(struct kobject *kobj, struct attribute *attr, Loading @@ -1027,17 +981,16 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EBUSY; if (!fattr->store) return -EIO; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); if (likely(!policy_is_inactive(policy))) ret = fattr->store(policy, buf, count); up_write(&policy->rwsem); return fattr->store(policy, buf, count); return ret; return -EBUSY; } static void cpufreq_sysfs_release(struct kobject *kobj) Loading Loading @@ -1195,7 +1148,8 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp if (cpumask_test_cpu(cpu, policy->cpus)) return 0; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); if (has_target()) cpufreq_stop_governor(policy); Loading @@ -1206,7 +1160,7 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp if (ret) pr_err("%s: Failed to start governor\n", __func__); } up_write(&policy->rwsem); return ret; } Loading @@ -1226,9 +1180,10 @@ static void handle_update(struct work_struct *work) container_of(work, struct cpufreq_policy, update); pr_debug("handle_update for cpu %u called\n", policy->cpu); down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); refresh_frequency_limits(policy); up_write(&policy->rwsem); } static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq, Loading @@ -1254,11 +1209,11 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy) struct kobject *kobj; struct completion *cmp; down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { cpufreq_stats_free_table(policy); kobj = &policy->kobj; cmp = &policy->kobj_unregister; up_write(&policy->rwsem); } kobject_put(kobj); /* Loading Loading @@ -1334,7 +1289,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) init_waitqueue_head(&policy->transition_wait); INIT_WORK(&policy->update, handle_update); policy->cpu = cpu; return policy; err_min_qos_notifier: Loading Loading @@ -1403,35 +1357,17 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) kfree(policy); } static int cpufreq_online(unsigned int cpu) static int cpufreq_policy_online(struct cpufreq_policy *policy, unsigned int cpu, bool new_policy) { struct cpufreq_policy *policy; bool new_policy; unsigned long flags; unsigned int j; int ret; pr_debug("%s: bringing CPU%u online\n", __func__, cpu); /* Check if this CPU already has a policy to manage it */ policy = per_cpu(cpufreq_cpu_data, cpu); if (policy) { WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); if (!policy_is_inactive(policy)) return cpufreq_add_policy_cpu(policy, cpu); guard(cpufreq_policy_write)(policy); /* This is the only online CPU for the policy. Start over. */ new_policy = false; down_write(&policy->rwsem); policy->cpu = cpu; policy->governor = NULL; } else { new_policy = true; policy = cpufreq_policy_alloc(cpu); if (!policy) return -ENOMEM; down_write(&policy->rwsem); } if (!new_policy && cpufreq_driver->online) { /* Recover policy->cpus using related_cpus */ Loading @@ -1454,7 +1390,7 @@ static int cpufreq_online(unsigned int cpu) if (ret) { pr_debug("%s: %d: initialization failed\n", __func__, __LINE__); goto out_free_policy; goto out_clear_policy; } /* Loading Loading @@ -1605,7 +1541,55 @@ static int cpufreq_online(unsigned int cpu) goto out_destroy_policy; } up_write(&policy->rwsem); return 0; out_destroy_policy: for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, j, get_cpu_device(j)); out_offline_policy: if (cpufreq_driver->offline) cpufreq_driver->offline(policy); out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); out_clear_policy: cpumask_clear(policy->cpus); return ret; } static int cpufreq_online(unsigned int cpu) { struct cpufreq_policy *policy; bool new_policy; int ret; pr_debug("%s: bringing CPU%u online\n", __func__, cpu); /* Check if this CPU already has a policy to manage it */ policy = per_cpu(cpufreq_cpu_data, cpu); if (policy) { WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); if (!policy_is_inactive(policy)) return cpufreq_add_policy_cpu(policy, cpu); /* This is the only online CPU for the policy. Start over. */ new_policy = false; } else { new_policy = true; policy = cpufreq_policy_alloc(cpu); if (!policy) return -ENOMEM; } ret = cpufreq_policy_online(policy, cpu, new_policy); if (ret) { cpufreq_policy_free(policy); return ret; } kobject_uevent(&policy->kobj, KOBJ_ADD); Loading Loading @@ -1633,25 +1617,6 @@ static int cpufreq_online(unsigned int cpu) pr_debug("initialization complete\n"); return 0; out_destroy_policy: for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, j, get_cpu_device(j)); out_offline_policy: if (cpufreq_driver->offline) cpufreq_driver->offline(policy); out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); out_free_policy: cpumask_clear(policy->cpus); up_write(&policy->rwsem); cpufreq_policy_free(policy); return ret; } /** Loading Loading @@ -1741,11 +1706,10 @@ static int cpufreq_offline(unsigned int cpu) return 0; } down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); __cpufreq_offline(cpu, policy); up_write(&policy->rwsem); return 0; } Loading @@ -1762,21 +1726,18 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) if (!policy) return; down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { if (cpu_online(cpu)) __cpufreq_offline(cpu, policy); remove_cpu_dev_symlink(policy, cpu, dev); if (!cpumask_empty(policy->real_cpus)) { up_write(&policy->rwsem); if (!cpumask_empty(policy->real_cpus)) return; } /* * Unregister cpufreq cooling once all the CPUs of the policy are * removed. * Unregister cpufreq cooling once all the CPUs of the policy * are removed. */ if (cpufreq_thermal_control_enabled(cpufreq_driver)) { cpufreq_cooling_unregister(policy->cdev); Loading @@ -1786,8 +1747,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) /* We did light-weight exit earlier, do full tear down now */ if (cpufreq_driver->offline && cpufreq_driver->exit) cpufreq_driver->exit(policy); up_write(&policy->rwsem); } cpufreq_policy_free(policy); } Loading Loading @@ -1858,27 +1818,26 @@ static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, b */ unsigned int cpufreq_quick_get(unsigned int cpu) { struct cpufreq_policy *policy; unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; unsigned long flags; read_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) { ret_freq = cpufreq_driver->get(cpu); unsigned int ret_freq = cpufreq_driver->get(cpu); read_unlock_irqrestore(&cpufreq_driver_lock, flags); return ret_freq; } read_unlock_irqrestore(&cpufreq_driver_lock, flags); policy = cpufreq_cpu_get(cpu); if (policy) { ret_freq = policy->cur; cpufreq_cpu_put(policy); } if (policy) return policy->cur; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_quick_get); Loading @@ -1890,15 +1849,13 @@ EXPORT_SYMBOL(cpufreq_quick_get); */ unsigned int cpufreq_quick_get_max(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { ret_freq = policy->max; cpufreq_cpu_put(policy); } policy = cpufreq_cpu_get(cpu); if (policy) return policy->max; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_quick_get_max); Loading @@ -1910,15 +1867,13 @@ EXPORT_SYMBOL(cpufreq_quick_get_max); */ __weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { ret_freq = policy->cpuinfo.max_freq; cpufreq_cpu_put(policy); } policy = cpufreq_cpu_get(cpu); if (policy) return policy->cpuinfo.max_freq; return ret_freq; return 0; } EXPORT_SYMBOL(cpufreq_get_hw_max_freq); Loading @@ -1938,19 +1893,18 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy) */ unsigned int cpufreq_get(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); unsigned int ret_freq = 0; struct cpufreq_policy *policy __free(put_cpufreq_policy); if (policy) { down_read(&policy->rwsem); if (cpufreq_driver->get) ret_freq = __cpufreq_get(policy); up_read(&policy->rwsem); policy = cpufreq_cpu_get(cpu); if (!policy) return 0; cpufreq_cpu_put(policy); } guard(cpufreq_policy_read)(policy); return ret_freq; if (cpufreq_driver->get) return __cpufreq_get(policy); return 0; } EXPORT_SYMBOL(cpufreq_get); Loading Loading @@ -2009,9 +1963,9 @@ void cpufreq_suspend(void) for_each_active_policy(policy) { if (has_target()) { down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { cpufreq_stop_governor(policy); up_write(&policy->rwsem); } } if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy)) Loading Loading @@ -2052,9 +2006,9 @@ void cpufreq_resume(void) pr_err("%s: Failed to resume driver: %s\n", __func__, cpufreq_driver->name); } else if (has_target()) { down_write(&policy->rwsem); scoped_guard(cpufreq_policy_write, policy) { ret = cpufreq_start_governor(policy); up_write(&policy->rwsem); } if (ret) pr_err("%s: Failed to start governor for CPU%u's policy\n", Loading Loading @@ -2421,15 +2375,9 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { int ret; down_write(&policy->rwsem); guard(cpufreq_policy_write)(policy); ret = __cpufreq_driver_target(policy, target_freq, relation); up_write(&policy->rwsem); return ret; return __cpufreq_driver_target(policy, target_freq, relation); } EXPORT_SYMBOL_GPL(cpufreq_driver_target); Loading Loading @@ -2611,7 +2559,8 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); */ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) { struct cpufreq_policy *cpu_policy; struct cpufreq_policy *cpu_policy __free(put_cpufreq_policy); if (!policy) return -EINVAL; Loading @@ -2621,7 +2570,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) memcpy(policy, cpu_policy, sizeof(*policy)); cpufreq_cpu_put(cpu_policy); return 0; } EXPORT_SYMBOL(cpufreq_get_policy); Loading Loading @@ -2769,6 +2717,21 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, return ret; } static void cpufreq_policy_refresh(struct cpufreq_policy *policy) { guard(cpufreq_policy_write)(policy); /* * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get && has_target() && (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false)))) return; refresh_frequency_limits(policy); } /** * cpufreq_update_policy - Re-evaluate an existing cpufreq policy. * @cpu: CPU to re-evaluate the policy for. Loading @@ -2780,23 +2743,13 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, */ void cpufreq_update_policy(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); struct cpufreq_policy *policy __free(put_cpufreq_policy); policy = cpufreq_cpu_get(cpu); if (!policy) return; /* * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get && has_target() && (cpufreq_suspended || WARN_ON(!cpufreq_verify_current_freq(policy, false)))) goto unlock; refresh_frequency_limits(policy); unlock: cpufreq_cpu_release(policy); cpufreq_policy_refresh(policy); } EXPORT_SYMBOL(cpufreq_update_policy); Loading @@ -2805,7 +2758,7 @@ EXPORT_SYMBOL(cpufreq_update_policy); * @cpu: CPU to update the policy limits for. * * Invoke the driver's ->update_limits callback if present or call * cpufreq_update_policy() for @cpu. * cpufreq_policy_refresh() for @cpu. */ void cpufreq_update_limits(unsigned int cpu) { Loading @@ -2816,9 +2769,9 @@ void cpufreq_update_limits(unsigned int cpu) return; if (cpufreq_driver->update_limits) cpufreq_driver->update_limits(cpu); cpufreq_driver->update_limits(policy); else cpufreq_update_policy(cpu); cpufreq_policy_refresh(policy); } EXPORT_SYMBOL_GPL(cpufreq_update_limits); Loading
drivers/cpufreq/intel_pstate.c +18 −29 Original line number Diff line number Diff line Loading @@ -1353,9 +1353,11 @@ static void intel_pstate_update_policies(void) cpufreq_update_policy(cpu); } static void __intel_pstate_update_max_freq(struct cpudata *cpudata, struct cpufreq_policy *policy) static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy, struct cpudata *cpudata) { guard(cpufreq_policy_write)(policy); if (hwp_active) intel_pstate_get_hwp_cap(cpudata); Loading @@ -1365,42 +1367,34 @@ static void __intel_pstate_update_max_freq(struct cpudata *cpudata, refresh_frequency_limits(policy); } static void intel_pstate_update_limits(unsigned int cpu) static bool intel_pstate_update_max_freq(struct cpudata *cpudata) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); struct cpudata *cpudata; struct cpufreq_policy *policy __free(put_cpufreq_policy); policy = cpufreq_cpu_get(cpudata->cpu); if (!policy) return; return false; cpudata = all_cpu_data[cpu]; __intel_pstate_update_max_freq(policy, cpudata); __intel_pstate_update_max_freq(cpudata, policy); return true; } /* Prevent the driver from being unregistered now. */ mutex_lock(&intel_pstate_driver_lock); static void intel_pstate_update_limits(struct cpufreq_policy *policy) { struct cpudata *cpudata = all_cpu_data[policy->cpu]; cpufreq_cpu_release(policy); __intel_pstate_update_max_freq(policy, cpudata); hybrid_update_capacity(cpudata); mutex_unlock(&intel_pstate_driver_lock); } static void intel_pstate_update_limits_for_all(void) { int cpu; for_each_possible_cpu(cpu) { struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu); if (!policy) continue; __intel_pstate_update_max_freq(all_cpu_data[cpu], policy); cpufreq_cpu_release(policy); } for_each_possible_cpu(cpu) intel_pstate_update_max_freq(all_cpu_data[cpu]); mutex_lock(&hybrid_capacity_lock); Loading Loading @@ -1840,13 +1834,8 @@ static void intel_pstate_notify_work(struct work_struct *work) { struct cpudata *cpudata = container_of(to_delayed_work(work), struct cpudata, hwp_notify_work); struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpudata->cpu); if (policy) { __intel_pstate_update_max_freq(cpudata, policy); cpufreq_cpu_release(policy); if (intel_pstate_update_max_freq(cpudata)) { /* * The driver will not be unregistered while this function is * running, so update the capacity without acquiring the driver Loading
include/linux/cpufreq.h +7 −3 Original line number Diff line number Diff line Loading @@ -170,6 +170,12 @@ struct cpufreq_policy { struct notifier_block nb_max; }; DEFINE_GUARD(cpufreq_policy_write, struct cpufreq_policy *, down_write(&_T->rwsem), up_write(&_T->rwsem)) DEFINE_GUARD(cpufreq_policy_read, struct cpufreq_policy *, down_read(&_T->rwsem), up_read(&_T->rwsem)) /* * Used for passing new cpufreq policy data to the cpufreq driver's ->verify() * callback for sanitization. That callback is only expected to modify the min Loading Loading @@ -235,8 +241,6 @@ void disable_cpufreq(void); u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu); void cpufreq_cpu_release(struct cpufreq_policy *policy); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); void refresh_frequency_limits(struct cpufreq_policy *policy); void cpufreq_update_policy(unsigned int cpu); Loading Loading @@ -395,7 +399,7 @@ struct cpufreq_driver { unsigned int (*get)(unsigned int cpu); /* Called to update policy limits on firmware notifications. */ void (*update_limits)(unsigned int cpu); void (*update_limits)(struct cpufreq_policy *policy); /* optional */ int (*bios_limit)(int cpu, unsigned int *limit); Loading