Loading MAINTAINERS +11 −0 Original line number Diff line number Diff line Loading @@ -5883,6 +5883,8 @@ F: include/dt-bindings/clock/ F: include/linux/clk-pr* F: include/linux/clk/ F: include/linux/of_clk.h F: rust/helpers/clk.c F: rust/kernel/clk.rs X: drivers/clk/clkdev.c COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3) Loading Loading @@ -6140,6 +6142,7 @@ F: drivers/cpufreq/ F: include/linux/cpufreq.h F: include/linux/sched/cpufreq.h F: kernel/sched/cpufreq*.c F: rust/kernel/cpufreq.rs F: tools/testing/selftests/cpufreq/ CPU HOTPLUG Loading @@ -6153,6 +6156,7 @@ F: include/linux/cpuhotplug.h F: include/linux/smpboot.h F: kernel/cpu.c F: kernel/smpboot.* F: rust/kernel/cpu.rs CPU IDLE TIME MANAGEMENT FRAMEWORK M: "Rafael J. Wysocki" <rafael@kernel.org> Loading Loading @@ -6237,6 +6241,12 @@ L: linux-riscv@lists.infradead.org S: Maintained F: drivers/cpuidle/cpuidle-riscv-sbi.c CPUMASK API [RUST] M: Viresh Kumar <viresh.kumar@linaro.org> R: Yury Norov <yury.norov@gmail.com> S: Maintained F: rust/kernel/cpumask.rs CRAMFS FILESYSTEM M: Nicolas Pitre <nico@fluxnic.net> S: Maintained Loading Loading @@ -18156,6 +18166,7 @@ F: Documentation/devicetree/bindings/opp/ F: Documentation/power/opp.rst F: drivers/opp/ F: include/linux/pm_opp.h F: rust/kernel/opp.rs OPL4 DRIVER M: Clemens Ladisch <clemens@ladisch.de> drivers/cpufreq/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,18 @@ config CPUFREQ_DT If in doubt, say N. config CPUFREQ_DT_RUST tristate "Rust based Generic DT based cpufreq driver" depends on HAVE_CLK && OF && RUST select CPUFREQ_DT_PLATDEV select PM_OPP help This adds a Rust based generic DT based cpufreq driver for frequency management. It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) systems. If in doubt, say N. config CPUFREQ_VIRT tristate "Virtual cpufreq driver" depends on GENERIC_ARCH_TOPOLOGY Loading drivers/cpufreq/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_RUST) += rcpufreq_dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o obj-$(CONFIG_CPUFREQ_VIRT) += virtual-cpufreq.o 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 Loading
MAINTAINERS +11 −0 Original line number Diff line number Diff line Loading @@ -5883,6 +5883,8 @@ F: include/dt-bindings/clock/ F: include/linux/clk-pr* F: include/linux/clk/ F: include/linux/of_clk.h F: rust/helpers/clk.c F: rust/kernel/clk.rs X: drivers/clk/clkdev.c COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3) Loading Loading @@ -6140,6 +6142,7 @@ F: drivers/cpufreq/ F: include/linux/cpufreq.h F: include/linux/sched/cpufreq.h F: kernel/sched/cpufreq*.c F: rust/kernel/cpufreq.rs F: tools/testing/selftests/cpufreq/ CPU HOTPLUG Loading @@ -6153,6 +6156,7 @@ F: include/linux/cpuhotplug.h F: include/linux/smpboot.h F: kernel/cpu.c F: kernel/smpboot.* F: rust/kernel/cpu.rs CPU IDLE TIME MANAGEMENT FRAMEWORK M: "Rafael J. Wysocki" <rafael@kernel.org> Loading Loading @@ -6237,6 +6241,12 @@ L: linux-riscv@lists.infradead.org S: Maintained F: drivers/cpuidle/cpuidle-riscv-sbi.c CPUMASK API [RUST] M: Viresh Kumar <viresh.kumar@linaro.org> R: Yury Norov <yury.norov@gmail.com> S: Maintained F: rust/kernel/cpumask.rs CRAMFS FILESYSTEM M: Nicolas Pitre <nico@fluxnic.net> S: Maintained Loading Loading @@ -18156,6 +18166,7 @@ F: Documentation/devicetree/bindings/opp/ F: Documentation/power/opp.rst F: drivers/opp/ F: include/linux/pm_opp.h F: rust/kernel/opp.rs OPL4 DRIVER M: Clemens Ladisch <clemens@ladisch.de>
drivers/cpufreq/Kconfig +12 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,18 @@ config CPUFREQ_DT If in doubt, say N. config CPUFREQ_DT_RUST tristate "Rust based Generic DT based cpufreq driver" depends on HAVE_CLK && OF && RUST select CPUFREQ_DT_PLATDEV select PM_OPP help This adds a Rust based generic DT based cpufreq driver for frequency management. It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) systems. If in doubt, say N. config CPUFREQ_VIRT tristate "Virtual cpufreq driver" depends on GENERIC_ARCH_TOPOLOGY Loading
drivers/cpufreq/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o obj-$(CONFIG_CPUFREQ_DT_RUST) += rcpufreq_dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o obj-$(CONFIG_CPUFREQ_VIRT) += virtual-cpufreq.o 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