summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
authorQuentin Perret <qperret@google.com>2020-06-29 10:25:00 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2020-07-02 13:03:30 +0200
commit8412b4563e5910485c7bcd4fdcd8bcc3e728284c (patch)
tree65b3dd3492c141dfa9feb32bd3b99de656cc1205 /drivers/cpufreq/cpufreq.c
parentcpufreq: Register governors at core_initcall (diff)
downloadlinux-8412b4563e5910485c7bcd4fdcd8bcc3e728284c.tar.xz
linux-8412b4563e5910485c7bcd4fdcd8bcc3e728284c.zip
cpufreq: Specify default governor on command line
Currently, the only way to specify the default CPUfreq governor is via Kconfig options, which suits users who can build the kernel themselves perfectly. However, for those who use a distro-like kernel (such as Android, with the Generic Kernel Image project), the only way to use a non-default governor is to boot to userspace, and to then switch using the sysfs interface. Being able to specify the default governor on the command line, like is the case for cpuidle, would allow those users to specify their governor of choice earlier on, and to simplify the userspace boot procedure slighlty. To support this use-case, add a kernel command line parameter allowing the default governor for CPUfreq to be specified, which takes precedence over the built-in default. This implementation has one notable limitation: the default governor must be registered before the driver. This is solved for builtin governors and drivers using appropriate *_initcall() functions. And in the modular case, this must be reflected as a constraint on the module loading order. Signed-off-by: Quentin Perret <qperret@google.com> [ Viresh: Converted 'default_governor' to a string and parsing it only at initcall level, and several updates to cpufreq_init_policy(). ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e9e8200a0211..ad94b1d47ddb 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -50,6 +50,8 @@ static LIST_HEAD(cpufreq_governor_list);
#define for_each_governor(__governor) \
list_for_each_entry(__governor, &cpufreq_governor_list, governor_list)
+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
@@ -1061,7 +1063,6 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)
static int cpufreq_init_policy(struct cpufreq_policy *policy)
{
- struct cpufreq_governor *def_gov = cpufreq_default_governor();
struct cpufreq_governor *gov = NULL;
unsigned int pol = CPUFREQ_POLICY_UNKNOWN;
int ret;
@@ -1071,21 +1072,27 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
gov = get_governor(policy->last_governor);
if (gov) {
pr_debug("Restoring governor %s for cpu %d\n",
- policy->governor->name, policy->cpu);
- } else if (def_gov) {
- gov = def_gov;
- __module_get(gov->owner);
+ gov->name, policy->cpu);
} else {
- return -ENODATA;
+ gov = get_governor(default_governor);
+ }
+
+ if (!gov) {
+ gov = cpufreq_default_governor();
+ if (!gov)
+ return -ENODATA;
+ __module_get(gov->owner);
}
+
} else {
+
/* Use the default policy if there is no last_policy. */
if (policy->last_policy) {
pol = policy->last_policy;
- } else if (def_gov) {
- pol = cpufreq_parse_policy(def_gov->name);
+ } else {
+ pol = cpufreq_parse_policy(default_governor);
/*
- * In case the default governor is neiter "performance"
+ * In case the default governor is neither "performance"
* nor "powersave", fall back to the initial policy
* value set by the driver.
*/
@@ -2795,13 +2802,19 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
static int __init cpufreq_core_init(void)
{
+ struct cpufreq_governor *gov = cpufreq_default_governor();
+
if (cpufreq_disabled())
return -ENODEV;
cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
BUG_ON(!cpufreq_global_kobject);
+ if (!strlen(default_governor))
+ strncpy(default_governor, gov->name, CPUFREQ_NAME_LEN);
+
return 0;
}
module_param(off, int, 0444);
+module_param_string(default_governor, default_governor, CPUFREQ_NAME_LEN, 0444);
core_initcall(cpufreq_core_init);