// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/cpufreq/cpufreq.c * * Copyright (C) 2001 Russell King * (C) 2002 - 2003 Dominik Brodowski <[email protected]> * (C) 2013 Viresh Kumar <[email protected]> * * Oct 2005 - Ashok Raj <[email protected]> * Added handling for CPU hotplug * Feb 2006 - Jacob Shin <[email protected]> * Fix handling for CPU hotplug -- affected CPUs */ #define pr_fmt(fmt) … #include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/cpu_cooling.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/init.h> #include <linux/kernel_stat.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/pm_qos.h> #include <linux/slab.h> #include <linux/suspend.h> #include <linux/syscore_ops.h> #include <linux/tick.h> #include <linux/units.h> #include <trace/events/power.h> static LIST_HEAD(cpufreq_policy_list); /* Macros to iterate over CPU policies */ #define for_each_suitable_policy(__policy, __active) … #define for_each_active_policy(__policy) … #define for_each_inactive_policy(__policy) … /* Iterate over governors */ static LIST_HEAD(cpufreq_governor_list); #define for_each_governor(__governor) … static char default_governor[CPUFREQ_NAME_LEN]; /* * The "cpufreq driver" - the arch- or hardware-dependent low * level driver of CPUFreq support, and its spinlock. This lock * also protects the cpufreq_cpu_data array. */ static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); static DEFINE_RWLOCK(cpufreq_driver_lock); static DEFINE_STATIC_KEY_FALSE(cpufreq_freq_invariance); bool cpufreq_supports_freq_invariance(void) { … } /* Flag to suspend/resume CPUFreq governors */ static bool cpufreq_suspended; static inline bool has_target(void) { … } bool has_target_index(void) { … } /* internal prototypes */ static unsigned int __cpufreq_get(struct cpufreq_policy *policy); static int cpufreq_init_governor(struct cpufreq_policy *policy); static void cpufreq_exit_governor(struct cpufreq_policy *policy); static void cpufreq_governor_limits(struct cpufreq_policy *policy); static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_governor *new_gov, unsigned int new_pol); static bool cpufreq_boost_supported(void); /* * Two notifier lists: the "policy" list is involved in the * validation process for a new CPU frequency policy; the * "transition" list for kernel code that needs to handle * changes to devices when the CPU clock speed changes. * The mutex locks both lists. */ static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); SRCU_NOTIFIER_HEAD_STATIC(…); static int off __read_mostly; static int cpufreq_disabled(void) { … } void disable_cpufreq(void) { … } static DEFINE_MUTEX(cpufreq_governor_mutex); bool have_governor_per_policy(void) { … } EXPORT_SYMBOL_GPL(…); static struct kobject *cpufreq_global_kobject; struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL_GPL(…); static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { … } u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy) { … } EXPORT_SYMBOL_GPL(…); /* * This is a generic cpufreq init() routine which can be used by cpufreq * drivers of SMP systems. It will do following: * - validate & show freq table passed * - set policies transition latency * - policy->cpus with all possible CPUs */ void cpufreq_generic_init(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int transition_latency) { … } EXPORT_SYMBOL_GPL(…); struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu) { … } EXPORT_SYMBOL_GPL(…); unsigned int cpufreq_generic_get(unsigned int cpu) { … } EXPORT_SYMBOL_GPL(…); /** * cpufreq_cpu_get - Return policy for a CPU and mark it as busy. * @cpu: CPU to find the policy for. * * Call cpufreq_cpu_get_raw() to obtain a cpufreq policy for @cpu and increment * the kobject reference counter of that policy. Return a valid policy on * success or NULL on failure. * * The policy returned by this function has to be released with the help of * cpufreq_cpu_put() to balance its kobject reference counter properly. */ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { … } EXPORT_SYMBOL_GPL(…); /** * cpufreq_cpu_put - Decrement kobject usage counter for cpufreq policy. * @policy: cpufreq policy returned by cpufreq_cpu_get(). */ void cpufreq_cpu_put(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL_GPL(…); /** * 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) { … } /** * 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) { … } /********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/ /** * adjust_jiffies - Adjust the system "loops_per_jiffy". * @val: CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. * @ci: Frequency change information. * * This function alters the system "loops_per_jiffy" for the clock * speed change. Note that loops_per_jiffy cannot be updated on SMP * systems as each CPU might be scaled differently. So, use the arch * per-CPU loops_per_jiffy value wherever possible. */ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { … } /** * cpufreq_notify_transition - Notify frequency transition and adjust jiffies. * @policy: cpufreq policy to enable fast frequency switching for. * @freqs: contain details of the frequency update. * @state: set to CPUFREQ_PRECHANGE or CPUFREQ_POSTCHANGE. * * This function calls the transition notifiers and adjust_jiffies(). * * It is called twice on all CPU frequency changes that have external effects. */ static void cpufreq_notify_transition(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, unsigned int state) { … } /* Do post notifications when there are chances that transition has failed */ static void cpufreq_notify_post_transition(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, int transition_failed) { … } void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs) { … } EXPORT_SYMBOL_GPL(…); void cpufreq_freq_transition_end(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, int transition_failed) { … } EXPORT_SYMBOL_GPL(…); /* * Fast frequency switching status count. Positive means "enabled", negative * means "disabled" and 0 means "not decided yet". */ static int cpufreq_fast_switch_count; static DEFINE_MUTEX(cpufreq_fast_switch_lock); static void cpufreq_list_transition_notifiers(void) { … } /** * cpufreq_enable_fast_switch - Enable fast frequency switching for policy. * @policy: cpufreq policy to enable fast frequency switching for. * * Try to enable fast frequency switching for @policy. * * The attempt will fail if there is at least one transition notifier registered * at this point, as fast frequency switching is quite fundamentally at odds * with transition notifiers. Thus if successful, it will make registration of * transition notifiers fail going forward. */ void cpufreq_enable_fast_switch(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL_GPL(…); /** * cpufreq_disable_fast_switch - Disable fast frequency switching for policy. * @policy: cpufreq policy to disable fast frequency switching for. */ void cpufreq_disable_fast_switch(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL_GPL(…); static unsigned int __resolve_freq(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { … } /** * cpufreq_driver_resolve_freq - Map a target frequency to a driver-supported * one. * @policy: associated policy to interrogate * @target_freq: target frequency to resolve. * * The target to driver frequency mapping is cached in the policy. * * Return: Lowest driver-supported frequency greater than or equal to the * given target_freq, subject to policy (min/max) and driver limitations. */ unsigned int cpufreq_driver_resolve_freq(struct cpufreq_policy *policy, unsigned int target_freq) { … } EXPORT_SYMBOL_GPL(…); unsigned int cpufreq_policy_transition_delay_us(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL_GPL(…); /********************************************************************* * SYSFS INTERFACE * *********************************************************************/ static ssize_t show_boost(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { … } static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { … } define_one_global_rw(…); static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) { … } static ssize_t store_local_boost(struct cpufreq_policy *policy, const char *buf, size_t count) { … } static struct freq_attr local_boost = …; static struct cpufreq_governor *find_governor(const char *str_governor) { … } static struct cpufreq_governor *get_governor(const char *str_governor) { … } static unsigned int cpufreq_parse_policy(char *str_governor) { … } /** * cpufreq_parse_governor - parse a governor string only for has_target() * @str_governor: Governor name. */ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor) { … } /* * cpufreq_per_cpu_attr_read() / show_##file_name() - * print out cpufreq information * * Write out information from cpufreq_driver->policy[cpu]; object must be * "unsigned int". */ #define show_one(file_name, object) … show_one(cpuinfo_min_freq, cpuinfo.min_freq); show_one(cpuinfo_max_freq, cpuinfo.max_freq); show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); __weak unsigned int arch_freq_get_on_cpu(int cpu) { … } static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf) { … } /* * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access */ #define store_one(file_name, object) … store_one(scaling_min_freq, min); store_one(scaling_max_freq, max); /* * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware */ static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, char *buf) { … } /* * show_scaling_governor - show the current policy for the specified CPU */ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf) { … } /* * store_scaling_governor - store policy for the specified CPU */ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, const char *buf, size_t count) { … } /* * show_scaling_driver - show the cpufreq driver currently loaded */ static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) { … } /* * show_scaling_available_governors - show the available CPUfreq governors */ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, char *buf) { … } ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf) { … } EXPORT_SYMBOL_GPL(…); /* * show_related_cpus - show the CPUs affected by each transition even if * hw coordination is in use */ static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf) { … } /* * show_affected_cpus - show the CPUs affected by each transition */ static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) { … } static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, const char *buf, size_t count) { … } static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) { … } /* * show_bios_limit - show the current cpufreq HW/BIOS limitation */ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) { … } cpufreq_freq_attr_ro_perm(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_ro(…); cpufreq_freq_attr_rw(…); cpufreq_freq_attr_rw(…); cpufreq_freq_attr_rw(…); cpufreq_freq_attr_rw(…); static struct attribute *cpufreq_attrs[] = …; ATTRIBUTE_GROUPS(…); #define to_policy(k) … #define to_attr(a) … static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { … } static ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { … } static void cpufreq_sysfs_release(struct kobject *kobj) { … } static const struct sysfs_ops sysfs_ops = …; static const struct kobj_type ktype_cpufreq = …; static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu, struct device *dev) { … } static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu, struct device *dev) { … } static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) { … } static int cpufreq_init_policy(struct cpufreq_policy *policy) { … } static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) { … } void refresh_frequency_limits(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL(…); static void handle_update(struct work_struct *work) { … } static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq, void *data) { … } static int cpufreq_notifier_max(struct notifier_block *nb, unsigned long freq, void *data) { … } static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy) { … } static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) { … } static void cpufreq_policy_free(struct cpufreq_policy *policy) { … } static int cpufreq_online(unsigned int cpu) { … } /** * cpufreq_add_dev - the cpufreq interface for a CPU device. * @dev: CPU device. * @sif: Subsystem interface structure pointer (not used) */ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) { … } static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy) { … } static int cpufreq_offline(unsigned int cpu) { … } /* * cpufreq_remove_dev - remove a CPU device * * Removes the cpufreq interface for a CPU device. */ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { … } /** * cpufreq_out_of_sync - Fix up actual and saved CPU frequency difference. * @policy: Policy managing CPUs. * @new_freq: New CPU frequency. * * Adjust to the current frequency first and clean up later by either calling * cpufreq_update_policy(), or scheduling handle_update(). */ static void cpufreq_out_of_sync(struct cpufreq_policy *policy, unsigned int new_freq) { … } static unsigned int cpufreq_verify_current_freq(struct cpufreq_policy *policy, bool update) { … } /** * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur * @cpu: CPU number * * This is the last known freq, without actually getting it from the driver. * Return value will be same as what is shown in scaling_cur_freq in sysfs. */ unsigned int cpufreq_quick_get(unsigned int cpu) { … } EXPORT_SYMBOL(…); /** * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU * @cpu: CPU number * * Just return the max possible frequency for a given CPU. */ unsigned int cpufreq_quick_get_max(unsigned int cpu) { … } EXPORT_SYMBOL(…); /** * cpufreq_get_hw_max_freq - get the max hardware frequency of the CPU * @cpu: CPU number * * The default return value is the max_freq field of cpuinfo. */ __weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) { … } EXPORT_SYMBOL(…); static unsigned int __cpufreq_get(struct cpufreq_policy *policy) { … } /** * cpufreq_get - get the current CPU frequency (in kHz) * @cpu: CPU number * * Get the CPU current (static) CPU frequency */ unsigned int cpufreq_get(unsigned int cpu) { … } EXPORT_SYMBOL(…); static struct subsys_interface cpufreq_interface = …; /* * In case platform wants some specific frequency to be configured * during suspend.. */ int cpufreq_generic_suspend(struct cpufreq_policy *policy) { … } EXPORT_SYMBOL(…); /** * cpufreq_suspend() - Suspend CPUFreq governors. * * Called during system wide Suspend/Hibernate cycles for suspending governors * 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. */ void cpufreq_suspend(void) { … } /** * cpufreq_resume() - Resume CPUFreq governors. * * Called during system wide Suspend/Hibernate cycle for resuming governors that * are suspended with cpufreq_suspend(). */ void cpufreq_resume(void) { … } /** * cpufreq_driver_test_flags - Test cpufreq driver's flags against given ones. * @flags: Flags to test against the current cpufreq driver's flags. * * Assumes that the driver is there, so callers must ensure that this is the * case. */ bool cpufreq_driver_test_flags(u16 flags) { … } /** * cpufreq_get_current_driver - Return the current driver's name. * * Return the name string of the currently registered cpufreq driver or NULL if * none. */ const char *cpufreq_get_current_driver(void) { … } EXPORT_SYMBOL_GPL(…); /** * cpufreq_get_driver_data - Return current driver data. * * Return the private data of the currently registered cpufreq driver, or NULL * if no cpufreq driver has been registered. */ void *cpufreq_get_driver_data(void) { … } EXPORT_SYMBOL_GPL(…); /********************************************************************* * NOTIFIER LISTS INTERFACE * *********************************************************************/ /** * cpufreq_register_notifier - Register a notifier with cpufreq. * @nb: notifier function to register. * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER. * * Add a notifier to one of two lists: either a list of notifiers that run on * clock rate changes (once before and once after every transition), or a list * of notifiers that ron on cpufreq policy changes. * * This function may sleep and it has the same return values as * blocking_notifier_chain_register(). */ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) { … } EXPORT_SYMBOL(…); /** * cpufreq_unregister_notifier - Unregister a notifier from cpufreq. * @nb: notifier block to be unregistered. * @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER. * * Remove a notifier from one of the cpufreq notifier lists. * * This function may sleep and it has the same return values as * blocking_notifier_chain_unregister(). */ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) { … } EXPORT_SYMBOL(…); /********************************************************************* * GOVERNORS * *********************************************************************/ /** * cpufreq_driver_fast_switch - Carry out a fast CPU frequency switch. * @policy: cpufreq policy to switch the frequency for. * @target_freq: New frequency to set (may be approximate). * * Carry out a fast frequency switch without sleeping. * * The driver's ->fast_switch() callback invoked by this function must be * suitable for being called from within RCU-sched read-side critical sections * and it is expected to select the minimum available frequency greater than or * equal to @target_freq (CPUFREQ_RELATION_L). * * This function must not be called if policy->fast_switch_enabled is unset. * * Governors calling this function must guarantee that it will never be invoked * twice in parallel for the same policy and that it will never be called in * parallel with either ->target() or ->target_index() for the same policy. * * Returns the actual frequency set for the CPU. * * If 0 is returned by the driver's ->fast_switch() callback to indicate an * error condition, the hardware configuration must be preserved. */ unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, unsigned int target_freq) { … } EXPORT_SYMBOL_GPL(…); /** * cpufreq_driver_adjust_perf - Adjust CPU performance level in one go. * @cpu: Target CPU. * @min_perf: Minimum (required) performance level (units of @capacity). * @target_perf: Target (desired) performance level (units of @capacity). * @capacity: Capacity of the target CPU. * * Carry out a fast performance level switch of @cpu without sleeping. * * The driver's ->adjust_perf() callback invoked by this function must be * suitable for being called from within RCU-sched read-side critical sections * and it is expected to select a suitable performance level equal to or above * @min_perf and preferably equal to or below @target_perf. * * This function must not be called if policy->fast_switch_enabled is unset. * * Governors calling this function must guarantee that it will never be invoked * twice in parallel for the same CPU and that it will never be called in * parallel with either ->target() or ->target_index() or ->fast_switch() for * the same CPU. */ void cpufreq_driver_adjust_perf(unsigned int cpu, unsigned long min_perf, unsigned long target_perf, unsigned long capacity) { … } /** * cpufreq_driver_has_adjust_perf - Check "direct fast switch" callback. * * Return 'true' if the ->adjust_perf callback is present for the * current driver or 'false' otherwise. */ bool cpufreq_driver_has_adjust_perf(void) { … } /* Must set freqs->new to intermediate frequency */ static int __target_intermediate(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, int index) { … } static int __target_index(struct cpufreq_policy *policy, int index) { … } int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { … } EXPORT_SYMBOL_GPL(…); int cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { … } EXPORT_SYMBOL_GPL(…); __weak struct cpufreq_governor *cpufreq_fallback_governor(void) { … } static int cpufreq_init_governor(struct cpufreq_policy *policy) { … } static void cpufreq_exit_governor(struct cpufreq_policy *policy) { … } int cpufreq_start_governor(struct cpufreq_policy *policy) { … } void cpufreq_stop_governor(struct cpufreq_policy *policy) { … } static void cpufreq_governor_limits(struct cpufreq_policy *policy) { … } int cpufreq_register_governor(struct cpufreq_governor *governor) { … } EXPORT_SYMBOL_GPL(…); void cpufreq_unregister_governor(struct cpufreq_governor *governor) { … } EXPORT_SYMBOL_GPL(…); /********************************************************************* * POLICY INTERFACE * *********************************************************************/ /** * cpufreq_get_policy - get the current cpufreq_policy * @policy: struct cpufreq_policy into which the current cpufreq_policy * is written * @cpu: CPU to find the policy for * * Reads the current cpufreq policy. */ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) { … } EXPORT_SYMBOL(…); DEFINE_PER_CPU(unsigned long, cpufreq_pressure); /** * cpufreq_update_pressure() - Update cpufreq pressure for CPUs * @policy: cpufreq policy of the CPUs. * * Update the value of cpufreq pressure for all @cpus in the policy. */ static void cpufreq_update_pressure(struct cpufreq_policy *policy) { … } /** * cpufreq_set_policy - Modify cpufreq policy parameters. * @policy: Policy object to modify. * @new_gov: Policy governor pointer. * @new_pol: Policy value (for drivers with built-in governors). * * Invoke the cpufreq driver's ->verify() callback to sanity-check the frequency * limits to be set for the policy, update @policy with the verified limits * values and either invoke the driver's ->setpolicy() callback (if present) or * carry out a governor update for @policy. That is, run the current governor's * ->limits() callback (if @new_gov points to the same object as the one in * @policy) or replace the governor for @policy with @new_gov. * * The cpuinfo part of @policy is not updated by this function. */ static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_governor *new_gov, unsigned int new_pol) { … } /** * cpufreq_update_policy - Re-evaluate an existing cpufreq policy. * @cpu: CPU to re-evaluate the policy for. * * Update the current frequency for the cpufreq policy of @cpu and use * cpufreq_set_policy() to re-apply the min and max limits, which triggers the * evaluation of policy notifiers and the cpufreq driver's ->verify() callback * for the policy in question, among other things. */ void cpufreq_update_policy(unsigned int cpu) { … } EXPORT_SYMBOL(…); /** * cpufreq_update_limits - Update policy limits for a given CPU. * @cpu: CPU to update the policy limits for. * * Invoke the driver's ->update_limits callback if present or call * cpufreq_update_policy() for @cpu. */ void cpufreq_update_limits(unsigned int cpu) { … } EXPORT_SYMBOL_GPL(…); /********************************************************************* * BOOST * *********************************************************************/ static int cpufreq_boost_set_sw(struct cpufreq_policy *policy, int state) { … } int cpufreq_boost_trigger_state(int state) { … } static bool cpufreq_boost_supported(void) { … } static int create_boost_sysfs_file(void) { … } static void remove_boost_sysfs_file(void) { … } int cpufreq_enable_boost_support(void) { … } EXPORT_SYMBOL_GPL(…); bool cpufreq_boost_enabled(void) { … } EXPORT_SYMBOL_GPL(…); /********************************************************************* * REGISTER / UNREGISTER CPUFREQ DRIVER * *********************************************************************/ static enum cpuhp_state hp_online; static int cpuhp_cpufreq_online(unsigned int cpu) { … } static int cpuhp_cpufreq_offline(unsigned int cpu) { … } /** * cpufreq_register_driver - register a CPU Frequency driver * @driver_data: A struct cpufreq_driver containing the values# * submitted by the CPU Frequency driver. * * Registers a CPU Frequency driver to this core code. This code * returns zero on success, -EEXIST when another driver got here first * (and isn't unregistered in the meantime). * */ int cpufreq_register_driver(struct cpufreq_driver *driver_data) { … } EXPORT_SYMBOL_GPL(…); /* * cpufreq_unregister_driver - unregister the current CPUFreq driver * * Unregister the current CPUFreq driver. Only call this if you have * the right to do so, i.e. if you have succeeded in initialising before! * Returns zero if successful, and -EINVAL if the cpufreq_driver is * currently not initialised. */ void cpufreq_unregister_driver(struct cpufreq_driver *driver) { … } EXPORT_SYMBOL_GPL(…); static int __init cpufreq_core_init(void) { … } module_param(off, int, 0444); module_param_string(…); core_initcall(cpufreq_core_init);