Linux-PM Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v3 0/3] cpufreq: Allow default governor on cmdline and fix locking issues
@ 2020-06-26  3:51 Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 1/3] cpufreq: Fix locking issues with governors Viresh Kumar
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Viresh Kumar @ 2020-06-26  3:51 UTC (permalink / raw)
  To: Rafael Wysocki, Arnd Bergmann, Ben Segall, Dietmar Eggemann,
	Ingo Molnar, Jonathan Corbet, Juri Lelli, Mel Gorman,
	Peter Zijlstra, Steven Rostedt, Vincent Guittot, Viresh Kumar
  Cc: linux-pm, kernel-team, tkjos, adharmap, linux-doc, linux-kernel,
	linuxppc-dev, Quentin Perret

Hi,

I have picked Quentin's series over my patch, modified both and tested.

V2->V3:
- default_governor is a string now and we don't set it on governor
  registration or unregistration anymore.
- Fixed locking issues in cpufreq_init_policy().

--
Viresh

Original cover letter fro Quentin:

This series enables users of prebuilt kernels (e.g. distro kernels) to
specify their CPUfreq governor of choice using the kernel command line,
instead of having to wait for the system to fully boot to userspace to
switch using the sysfs interface. This is helpful for 2 reasons:
  1. users get to choose the governor that runs during the actual boot;
  2. it simplifies the userspace boot procedure a bit (one less thing to
     worry about).

To enable this, the first patch moves all governor init calls to
core_initcall, to make sure they are registered by the time the drivers
probe. This should be relatively low impact as registering a governor
is a simple procedure (it gets added to a llist), and all governors
already load at core_initcall anyway when they're set as the default
in Kconfig. This also allows to clean-up the governors' init/exit code,
and reduces boilerplate.

The second patch introduces the new command line parameter, inspired by
its cpuidle counterpart. More details can be found in the respective
patch headers.

Changes in v2:
 - added Viresh's ack to patch 01
 - moved the assignment of 'default_governor' in patch 02 to the governor
   registration path instead of the driver registration (Viresh)

Quentin Perret (2):
  cpufreq: Register governors at core_initcall
  cpufreq: Specify default governor on command line

Viresh Kumar (1):
  cpufreq: Fix locking issues with governors

 .../admin-guide/kernel-parameters.txt         |  5 +
 Documentation/admin-guide/pm/cpufreq.rst      |  6 +-
 .../platforms/cell/cpufreq_spudemand.c        | 26 +-----
 drivers/cpufreq/cpufreq.c                     | 93 ++++++++++++-------
 drivers/cpufreq/cpufreq_conservative.c        | 22 +----
 drivers/cpufreq/cpufreq_ondemand.c            | 24 ++---
 drivers/cpufreq/cpufreq_performance.c         | 14 +--
 drivers/cpufreq/cpufreq_powersave.c           | 18 +---
 drivers/cpufreq/cpufreq_userspace.c           | 18 +---
 include/linux/cpufreq.h                       | 14 +++
 kernel/sched/cpufreq_schedutil.c              |  6 +-
 11 files changed, 106 insertions(+), 140 deletions(-)

-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH V3 1/3] cpufreq: Fix locking issues with governors
  2020-06-26  3:51 [PATCH v3 0/3] cpufreq: Allow default governor on cmdline and fix locking issues Viresh Kumar
@ 2020-06-26  3:51 ` Viresh Kumar
  2020-06-26  8:24   ` Quentin Perret
  2020-06-26  3:51 ` [PATCH V3 2/3] cpufreq: Register governors at core_initcall Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 3/3] cpufreq: Specify default governor on command line Viresh Kumar
  2 siblings, 1 reply; 11+ messages in thread
From: Viresh Kumar @ 2020-06-26  3:51 UTC (permalink / raw)
  To: Rafael Wysocki, Viresh Kumar
  Cc: linux-pm, Vincent Guittot, kernel-team, tkjos, adharmap,
	Quentin Perret, linux-kernel

The locking around governors handling isn't adequate currently. The list
of governors should never be traversed without locking in place. Also we
must make sure the governor isn't removed while it is still referenced
by code.

Reported-by: Quentin Perret <qperret@google.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c | 59 ++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 23 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 0128de3603df..e798a1193bdf 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -621,6 +621,24 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
 	return NULL;
 }
 
+static struct cpufreq_governor *get_governor(const char *str_governor)
+{
+	struct cpufreq_governor *t;
+
+	mutex_lock(&cpufreq_governor_mutex);
+	t = find_governor(str_governor);
+	if (!t)
+		goto unlock;
+
+	if (!try_module_get(t->owner))
+		t = NULL;
+
+unlock:
+	mutex_unlock(&cpufreq_governor_mutex);
+
+	return t;
+}
+
 static unsigned int cpufreq_parse_policy(char *str_governor)
 {
 	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
@@ -640,28 +658,14 @@ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
 {
 	struct cpufreq_governor *t;
 
-	mutex_lock(&cpufreq_governor_mutex);
-
-	t = find_governor(str_governor);
-	if (!t) {
-		int ret;
-
-		mutex_unlock(&cpufreq_governor_mutex);
-
-		ret = request_module("cpufreq_%s", str_governor);
-		if (ret)
-			return NULL;
-
-		mutex_lock(&cpufreq_governor_mutex);
+	t = get_governor(str_governor);
+	if (t)
+		return t;
 
-		t = find_governor(str_governor);
-	}
-	if (t && !try_module_get(t->owner))
-		t = NULL;
-
-	mutex_unlock(&cpufreq_governor_mutex);
+	if (request_module("cpufreq_%s", str_governor))
+		return NULL;
 
-	return t;
+	return get_governor(str_governor);
 }
 
 /**
@@ -815,12 +819,14 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
 		goto out;
 	}
 
+	mutex_lock(&cpufreq_governor_mutex);
 	for_each_governor(t) {
 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
 		    - (CPUFREQ_NAME_LEN + 2)))
-			goto out;
+			break;
 		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
 	}
+	mutex_unlock(&cpufreq_governor_mutex);
 out:
 	i += sprintf(&buf[i], "\n");
 	return i;
@@ -1058,11 +1064,14 @@ 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;
+	bool put_governor = false;
+	int ret;
 
 	if (has_target()) {
 		/* Update policy governor to the one used before hotplug. */
-		gov = find_governor(policy->last_governor);
+		gov = get_governor(policy->last_governor);
 		if (gov) {
+			put_governor = true;
 			pr_debug("Restoring governor %s for cpu %d\n",
 				 policy->governor->name, policy->cpu);
 		} else if (def_gov) {
@@ -1089,7 +1098,11 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
 			return -ENODATA;
 	}
 
-	return cpufreq_set_policy(policy, gov, pol);
+	ret = cpufreq_set_policy(policy, gov, pol);
+	if (put_governor)
+		module_put(gov->owner);
+
+	return ret;
 }
 
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH V3 2/3] cpufreq: Register governors at core_initcall
  2020-06-26  3:51 [PATCH v3 0/3] cpufreq: Allow default governor on cmdline and fix locking issues Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 1/3] cpufreq: Fix locking issues with governors Viresh Kumar
@ 2020-06-26  3:51 ` Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 3/3] cpufreq: Specify default governor on command line Viresh Kumar
  2 siblings, 0 replies; 11+ messages in thread
From: Viresh Kumar @ 2020-06-26  3:51 UTC (permalink / raw)
  To: Rafael Wysocki, Arnd Bergmann, Viresh Kumar, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman
  Cc: linux-pm, kernel-team, tkjos, adharmap, Quentin Perret,
	linuxppc-dev, linux-kernel

From: Quentin Perret <qperret@google.com>

Currently, most CPUFreq governors are registered at core_initcall time
when used as default, and module_init otherwise. In preparation for
letting users specify the default governor on the kernel command line,
change all of them to use core_initcall unconditionally, as is already
the case for schedutil and performance. This will enable us to assume
builtin governors have been registered before the builtin CPUFreq
drivers probe.

And since all governors now have similar init/exit patterns, introduce
two new macros cpufreq_governor_{init,exit}() to factorize the code.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Quentin Perret <qperret@google.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../platforms/cell/cpufreq_spudemand.c        | 26 ++-----------------
 drivers/cpufreq/cpufreq_conservative.c        | 22 ++++------------
 drivers/cpufreq/cpufreq_ondemand.c            | 24 +++++------------
 drivers/cpufreq/cpufreq_performance.c         | 14 ++--------
 drivers/cpufreq/cpufreq_powersave.c           | 18 +++----------
 drivers/cpufreq/cpufreq_userspace.c           | 18 +++----------
 include/linux/cpufreq.h                       | 14 ++++++++++
 kernel/sched/cpufreq_schedutil.c              |  6 +----
 8 files changed, 36 insertions(+), 106 deletions(-)

diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index 55b31eadb3c8..ca7849e113d7 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -126,30 +126,8 @@ static struct cpufreq_governor spu_governor = {
 	.stop = spu_gov_stop,
 	.owner = THIS_MODULE,
 };
-
-/*
- * module init and destoy
- */
-
-static int __init spu_gov_init(void)
-{
-	int ret;
-
-	ret = cpufreq_register_governor(&spu_governor);
-	if (ret)
-		printk(KERN_ERR "registration of governor failed\n");
-	return ret;
-}
-
-static void __exit spu_gov_exit(void)
-{
-	cpufreq_unregister_governor(&spu_governor);
-}
-
-
-module_init(spu_gov_init);
-module_exit(spu_gov_exit);
+cpufreq_governor_init(spu_governor);
+cpufreq_governor_exit(spu_governor);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
-
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 737ff3b9c2c0..aa39ff31ec9f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -322,17 +322,7 @@ static struct dbs_governor cs_governor = {
 	.start = cs_start,
 };
 
-#define CPU_FREQ_GOV_CONSERVATIVE	(&cs_governor.gov)
-
-static int __init cpufreq_gov_dbs_init(void)
-{
-	return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE);
-}
-
-static void __exit cpufreq_gov_dbs_exit(void)
-{
-	cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE);
-}
+#define CPU_FREQ_GOV_CONSERVATIVE	(cs_governor.gov)
 
 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
@@ -343,11 +333,9 @@ MODULE_LICENSE("GPL");
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 struct cpufreq_governor *cpufreq_default_governor(void)
 {
-	return CPU_FREQ_GOV_CONSERVATIVE;
+	return &CPU_FREQ_GOV_CONSERVATIVE;
 }
-
-core_initcall(cpufreq_gov_dbs_init);
-#else
-module_init(cpufreq_gov_dbs_init);
 #endif
-module_exit(cpufreq_gov_dbs_exit);
+
+cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE);
+cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 82a4d37ddecb..ac361a8b1d3b 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -408,7 +408,7 @@ static struct dbs_governor od_dbs_gov = {
 	.start = od_start,
 };
 
-#define CPU_FREQ_GOV_ONDEMAND	(&od_dbs_gov.gov)
+#define CPU_FREQ_GOV_ONDEMAND	(od_dbs_gov.gov)
 
 static void od_set_powersave_bias(unsigned int powersave_bias)
 {
@@ -429,7 +429,7 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
 			continue;
 
 		policy = cpufreq_cpu_get_raw(cpu);
-		if (!policy || policy->governor != CPU_FREQ_GOV_ONDEMAND)
+		if (!policy || policy->governor != &CPU_FREQ_GOV_ONDEMAND)
 			continue;
 
 		policy_dbs = policy->governor_data;
@@ -461,16 +461,6 @@ void od_unregister_powersave_bias_handler(void)
 }
 EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler);
 
-static int __init cpufreq_gov_dbs_init(void)
-{
-	return cpufreq_register_governor(CPU_FREQ_GOV_ONDEMAND);
-}
-
-static void __exit cpufreq_gov_dbs_exit(void)
-{
-	cpufreq_unregister_governor(CPU_FREQ_GOV_ONDEMAND);
-}
-
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
 MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
 MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
@@ -480,11 +470,9 @@ MODULE_LICENSE("GPL");
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
 struct cpufreq_governor *cpufreq_default_governor(void)
 {
-	return CPU_FREQ_GOV_ONDEMAND;
+	return &CPU_FREQ_GOV_ONDEMAND;
 }
-
-core_initcall(cpufreq_gov_dbs_init);
-#else
-module_init(cpufreq_gov_dbs_init);
 #endif
-module_exit(cpufreq_gov_dbs_exit);
+
+cpufreq_governor_init(CPU_FREQ_GOV_ONDEMAND);
+cpufreq_governor_exit(CPU_FREQ_GOV_ONDEMAND);
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index def9afe0f5b8..71c1d9aba772 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -23,16 +23,6 @@ static struct cpufreq_governor cpufreq_gov_performance = {
 	.limits		= cpufreq_gov_performance_limits,
 };
 
-static int __init cpufreq_gov_performance_init(void)
-{
-	return cpufreq_register_governor(&cpufreq_gov_performance);
-}
-
-static void __exit cpufreq_gov_performance_exit(void)
-{
-	cpufreq_unregister_governor(&cpufreq_gov_performance);
-}
-
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
 struct cpufreq_governor *cpufreq_default_governor(void)
 {
@@ -50,5 +40,5 @@ MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'performance'");
 MODULE_LICENSE("GPL");
 
-core_initcall(cpufreq_gov_performance_init);
-module_exit(cpufreq_gov_performance_exit);
+cpufreq_governor_init(cpufreq_gov_performance);
+cpufreq_governor_exit(cpufreq_gov_performance);
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 1ae66019eb83..7749522355b5 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -23,16 +23,6 @@ static struct cpufreq_governor cpufreq_gov_powersave = {
 	.owner		= THIS_MODULE,
 };
 
-static int __init cpufreq_gov_powersave_init(void)
-{
-	return cpufreq_register_governor(&cpufreq_gov_powersave);
-}
-
-static void __exit cpufreq_gov_powersave_exit(void)
-{
-	cpufreq_unregister_governor(&cpufreq_gov_powersave);
-}
-
 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
 MODULE_LICENSE("GPL");
@@ -42,9 +32,7 @@ struct cpufreq_governor *cpufreq_default_governor(void)
 {
 	return &cpufreq_gov_powersave;
 }
-
-core_initcall(cpufreq_gov_powersave_init);
-#else
-module_init(cpufreq_gov_powersave_init);
 #endif
-module_exit(cpufreq_gov_powersave_exit);
+
+cpufreq_governor_init(cpufreq_gov_powersave);
+cpufreq_governor_exit(cpufreq_gov_powersave);
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index b43e7cd502c5..50a4d7846580 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -126,16 +126,6 @@ static struct cpufreq_governor cpufreq_gov_userspace = {
 	.owner		= THIS_MODULE,
 };
 
-static int __init cpufreq_gov_userspace_init(void)
-{
-	return cpufreq_register_governor(&cpufreq_gov_userspace);
-}
-
-static void __exit cpufreq_gov_userspace_exit(void)
-{
-	cpufreq_unregister_governor(&cpufreq_gov_userspace);
-}
-
 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
 		"Russell King <rmk@arm.linux.org.uk>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
@@ -146,9 +136,7 @@ struct cpufreq_governor *cpufreq_default_governor(void)
 {
 	return &cpufreq_gov_userspace;
 }
-
-core_initcall(cpufreq_gov_userspace_init);
-#else
-module_init(cpufreq_gov_userspace_init);
 #endif
-module_exit(cpufreq_gov_userspace_exit);
+
+cpufreq_governor_init(cpufreq_gov_userspace);
+cpufreq_governor_exit(cpufreq_gov_userspace);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3494f6763597..e62b022cb07e 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -577,6 +577,20 @@ unsigned int cpufreq_policy_transition_delay_us(struct cpufreq_policy *policy);
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
 
+#define cpufreq_governor_init(__governor)			\
+static int __init __governor##_init(void)			\
+{								\
+	return cpufreq_register_governor(&__governor);	\
+}								\
+core_initcall(__governor##_init)
+
+#define cpufreq_governor_exit(__governor)			\
+static void __exit __governor##_exit(void)			\
+{								\
+	return cpufreq_unregister_governor(&__governor);	\
+}								\
+module_exit(__governor##_exit)
+
 struct cpufreq_governor *cpufreq_default_governor(void);
 struct cpufreq_governor *cpufreq_fallback_governor(void);
 
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 7fbaee24c824..402a09af9f43 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -909,11 +909,7 @@ struct cpufreq_governor *cpufreq_default_governor(void)
 }
 #endif
 
-static int __init sugov_register(void)
-{
-	return cpufreq_register_governor(&schedutil_gov);
-}
-core_initcall(sugov_register);
+cpufreq_governor_init(schedutil_gov);
 
 #ifdef CONFIG_ENERGY_MODEL
 extern bool sched_energy_update;
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH V3 3/3] cpufreq: Specify default governor on command line
  2020-06-26  3:51 [PATCH v3 0/3] cpufreq: Allow default governor on cmdline and fix locking issues Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 1/3] cpufreq: Fix locking issues with governors Viresh Kumar
  2020-06-26  3:51 ` [PATCH V3 2/3] cpufreq: Register governors at core_initcall Viresh Kumar
@ 2020-06-26  3:51 ` Viresh Kumar
  2020-06-26 15:57   ` Quentin Perret
  2 siblings, 1 reply; 11+ messages in thread
From: Viresh Kumar @ 2020-06-26  3:51 UTC (permalink / raw)
  To: Rafael Wysocki, Jonathan Corbet, Viresh Kumar
  Cc: linux-pm, Vincent Guittot, kernel-team, tkjos, adharmap,
	Quentin Perret, linux-doc, linux-kernel

From: Quentin Perret <qperret@google.com>

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 different
default 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 enable those users to specify
their governor of choice earlier on, and to simplify slighlty the
userspace boot procedure.

To support this use-case, add a kernel command line parameter enabling
to specify a default governor for CPUfreq, which takes precedence over
the builtin 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>
---
 .../admin-guide/kernel-parameters.txt         |  5 +++
 Documentation/admin-guide/pm/cpufreq.rst      |  6 ++--
 drivers/cpufreq/cpufreq.c                     | 36 ++++++++++++++-----
 3 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb95fad81c79..8deb5a89328a 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -703,6 +703,11 @@
 	cpufreq.off=1	[CPU_FREQ]
 			disable the cpufreq sub-system
 
+	cpufreq.default_governor=
+			[CPU_FREQ] Name of the default cpufreq governor or
+			policy to use. This governor must be registered in the
+			kernel before the cpufreq driver probes.
+
 	cpu_init_udelay=N
 			[X86] Delay for N microsec between assert and de-assert
 			of APIC INIT to start processors.  This delay occurs
diff --git a/Documentation/admin-guide/pm/cpufreq.rst b/Documentation/admin-guide/pm/cpufreq.rst
index 0c74a7784964..368e612145d2 100644
--- a/Documentation/admin-guide/pm/cpufreq.rst
+++ b/Documentation/admin-guide/pm/cpufreq.rst
@@ -147,9 +147,9 @@ CPUs in it.
 
 The next major initialization step for a new policy object is to attach a
 scaling governor to it (to begin with, that is the default scaling governor
-determined by the kernel configuration, but it may be changed later
-via ``sysfs``).  First, a pointer to the new policy object is passed to the
-governor's ``->init()`` callback which is expected to initialize all of the
+determined by the kernel command line or configuration, but it may be changed
+later via ``sysfs``).  First, a pointer to the new policy object is passed to
+the governor's ``->init()`` callback which is expected to initialize all of the
 data structures necessary to handle the given policy and, possibly, to add
 a governor ``sysfs`` interface to it.  Next, the governor is started by
 invoking its ``->start()`` callback.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e798a1193bdf..93c6399c1a42 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -50,6 +50,9 @@ static LIST_HEAD(cpufreq_governor_list);
 #define for_each_governor(__governor)				\
 	list_for_each_entry(__governor, &cpufreq_governor_list, governor_list)
 
+static char cpufreq_param_governor[CPUFREQ_NAME_LEN];
+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 +1064,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;
 	bool put_governor = false;
@@ -1071,22 +1073,29 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
 		/* Update policy governor to the one used before hotplug. */
 		gov = get_governor(policy->last_governor);
 		if (gov) {
-			put_governor = true;
 			pr_debug("Restoring governor %s for cpu %d\n",
-				 policy->governor->name, policy->cpu);
-		} else if (def_gov) {
-			gov = def_gov;
+				 gov->name, policy->cpu);
 		} else {
-			return -ENODATA;
+			gov = get_governor(default_governor);
+		}
+
+		if (gov) {
+			put_governor = true;
+		} else {
+			gov = cpufreq_default_governor();
+			if (!gov)
+				return -ENODATA;
 		}
+
 	} 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.
 			 */
@@ -2796,13 +2805,22 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
 static int __init cpufreq_core_init(void)
 {
+	struct cpufreq_governor *gov = cpufreq_default_governor();
+	char *name = gov->name;
+
 	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(cpufreq_param_governor))
+		name = cpufreq_param_governor;
+
+	strncpy(default_governor, name, CPUFREQ_NAME_LEN);
+
 	return 0;
 }
 module_param(off, int, 0444);
+module_param_string(default_governor, cpufreq_param_governor, CPUFREQ_NAME_LEN, 0444);
 core_initcall(cpufreq_core_init);
-- 
2.25.0.rc1.19.g042ed3e048af


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 1/3] cpufreq: Fix locking issues with governors
  2020-06-26  3:51 ` [PATCH V3 1/3] cpufreq: Fix locking issues with governors Viresh Kumar
@ 2020-06-26  8:24   ` Quentin Perret
  2020-06-29  2:13     ` Viresh Kumar
  0 siblings, 1 reply; 11+ messages in thread
From: Quentin Perret @ 2020-06-26  8:24 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linux-pm, Vincent Guittot, kernel-team, tkjos,
	adharmap, linux-kernel

On Friday 26 Jun 2020 at 09:21:42 (+0530), Viresh Kumar wrote:
> The locking around governors handling isn't adequate currently. The list
> of governors should never be traversed without locking in place. Also we
> must make sure the governor isn't removed while it is still referenced
> by code.
> 
> Reported-by: Quentin Perret <qperret@google.com>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
>  drivers/cpufreq/cpufreq.c | 59 ++++++++++++++++++++++++---------------
>  1 file changed, 36 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 0128de3603df..e798a1193bdf 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -621,6 +621,24 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
>  	return NULL;
>  }
>  
> +static struct cpufreq_governor *get_governor(const char *str_governor)
> +{
> +	struct cpufreq_governor *t;
> +
> +	mutex_lock(&cpufreq_governor_mutex);
> +	t = find_governor(str_governor);
> +	if (!t)
> +		goto unlock;
> +
> +	if (!try_module_get(t->owner))
> +		t = NULL;
> +
> +unlock:
> +	mutex_unlock(&cpufreq_governor_mutex);
> +
> +	return t;
> +}
> +
>  static unsigned int cpufreq_parse_policy(char *str_governor)
>  {
>  	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
> @@ -640,28 +658,14 @@ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
>  {
>  	struct cpufreq_governor *t;
>  
> -	mutex_lock(&cpufreq_governor_mutex);
> -
> -	t = find_governor(str_governor);
> -	if (!t) {
> -		int ret;
> -
> -		mutex_unlock(&cpufreq_governor_mutex);
> -
> -		ret = request_module("cpufreq_%s", str_governor);
> -		if (ret)
> -			return NULL;
> -
> -		mutex_lock(&cpufreq_governor_mutex);
> +	t = get_governor(str_governor);
> +	if (t)
> +		return t;
>  
> -		t = find_governor(str_governor);
> -	}
> -	if (t && !try_module_get(t->owner))
> -		t = NULL;
> -
> -	mutex_unlock(&cpufreq_governor_mutex);
> +	if (request_module("cpufreq_%s", str_governor))
> +		return NULL;
>  
> -	return t;
> +	return get_governor(str_governor);
>  }
>  
>  /**
> @@ -815,12 +819,14 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
>  		goto out;
>  	}
>  
> +	mutex_lock(&cpufreq_governor_mutex);
>  	for_each_governor(t) {
>  		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
>  		    - (CPUFREQ_NAME_LEN + 2)))
> -			goto out;
> +			break;
>  		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
>  	}
> +	mutex_unlock(&cpufreq_governor_mutex);
>  out:
>  	i += sprintf(&buf[i], "\n");
>  	return i;
> @@ -1058,11 +1064,14 @@ 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;
> +	bool put_governor = false;
> +	int ret;
>  
>  	if (has_target()) {
>  		/* Update policy governor to the one used before hotplug. */
> -		gov = find_governor(policy->last_governor);
> +		gov = get_governor(policy->last_governor);
>  		if (gov) {
> +			put_governor = true;
>  			pr_debug("Restoring governor %s for cpu %d\n",
>  				 policy->governor->name, policy->cpu);
>  		} else if (def_gov) {
> @@ -1089,7 +1098,11 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
>  			return -ENODATA;
>  	}
>  
> -	return cpufreq_set_policy(policy, gov, pol);
> +	ret = cpufreq_set_policy(policy, gov, pol);
> +	if (put_governor)
> +		module_put(gov->owner);

Nit: I think you could safely do

	if (gov)
		module_put(gov->owner);

and get rid of 'put_governor', given that try_module_get() and
module_put() are nops if owner is NULL (which is guaranteed for
the result of cpufreq_default_governor() as it is builtin).

But other than that:

Reviewed-by: Quentin Perret <qperret@google.com>

Thanks!

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 3/3] cpufreq: Specify default governor on command line
  2020-06-26  3:51 ` [PATCH V3 3/3] cpufreq: Specify default governor on command line Viresh Kumar
@ 2020-06-26 15:57   ` Quentin Perret
  2020-06-29  2:08     ` Viresh Kumar
  0 siblings, 1 reply; 11+ messages in thread
From: Quentin Perret @ 2020-06-26 15:57 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Jonathan Corbet, linux-pm, Vincent Guittot,
	kernel-team, tkjos, adharmap, linux-doc, linux-kernel

On Friday 26 Jun 2020 at 09:21:44 (+0530), Viresh Kumar wrote:
> index e798a1193bdf..93c6399c1a42 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -50,6 +50,9 @@ static LIST_HEAD(cpufreq_governor_list);
>  #define for_each_governor(__governor)				\
>  	list_for_each_entry(__governor, &cpufreq_governor_list, governor_list)
>  
> +static char cpufreq_param_governor[CPUFREQ_NAME_LEN];
> +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 +1064,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;
>  	bool put_governor = false;
> @@ -1071,22 +1073,29 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
>  		/* Update policy governor to the one used before hotplug. */
>  		gov = get_governor(policy->last_governor);
>  		if (gov) {
> -			put_governor = true;
>  			pr_debug("Restoring governor %s for cpu %d\n",
> -				 policy->governor->name, policy->cpu);
> -		} else if (def_gov) {
> -			gov = def_gov;
> +				 gov->name, policy->cpu);
>  		} else {
> -			return -ENODATA;
> +			gov = get_governor(default_governor);
> +		}
> +
> +		if (gov) {
> +			put_governor = true;
> +		} else {
> +			gov = cpufreq_default_governor();
> +			if (!gov)
> +				return -ENODATA;
>  		}

As mentioned on patch 01, doing put_module() below if gov != NULL would
avoid this dance with put_governor, but this works too, so no strong
opinion.

> +
>  	} 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.
>  			 */
> @@ -2796,13 +2805,22 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
>  
>  static int __init cpufreq_core_init(void)
>  {
> +	struct cpufreq_governor *gov = cpufreq_default_governor();
> +	char *name = gov->name;
> +
>  	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(cpufreq_param_governor))
> +		name = cpufreq_param_governor;
> +
> +	strncpy(default_governor, name, CPUFREQ_NAME_LEN);

Do we need both cpufreq_param_governor and default_governor?
Could we move everything to only one of them? Something a little bit
like that maybe?

---8<---
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 93c6399c1a42..a0e90b567e1e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -50,7 +50,6 @@ static LIST_HEAD(cpufreq_governor_list);
 #define for_each_governor(__governor)                          \
        list_for_each_entry(__governor, &cpufreq_governor_list, governor_list)
 
-static char cpufreq_param_governor[CPUFREQ_NAME_LEN];
 static char default_governor[CPUFREQ_NAME_LEN];
 
 /**
@@ -2814,13 +2813,11 @@ static int __init cpufreq_core_init(void)
        cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
        BUG_ON(!cpufreq_global_kobject);
 
-       if (strlen(cpufreq_param_governor))
-               name = cpufreq_param_governor;
-
-       strncpy(default_governor, name, CPUFREQ_NAME_LEN);
+       if (!strlen(default_governor))
+               strncpy(default_governor, name, CPUFREQ_NAME_LEN);
 
        return 0;
 }
 module_param(off, int, 0444);
-module_param_string(default_governor, cpufreq_param_governor, CPUFREQ_NAME_LEN, 0444);
+module_param_string(default_governor, default_governor, CPUFREQ_NAME_LEN, 0444);
--->8---

Also, one thing to keep in mind with this version (or the one you
suggested) is that if the command line parameter is not valid, we will
not fallback on the builtin default for the ->setpolicy() case. But I
suppose one might argue this is a reasonable behaviour, so no objection
from me.

Otherwise, apart from these nits, I gave this a go on my setup, with
builtin and modular governors & drivers, and everything worked exactly
as expected.

Thanks Viresh for the help!
Quentin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 3/3] cpufreq: Specify default governor on command line
  2020-06-26 15:57   ` Quentin Perret
@ 2020-06-29  2:08     ` Viresh Kumar
  2020-06-29  8:03       ` Quentin Perret
  0 siblings, 1 reply; 11+ messages in thread
From: Viresh Kumar @ 2020-06-29  2:08 UTC (permalink / raw)
  To: Quentin Perret
  Cc: Rafael Wysocki, Jonathan Corbet, linux-pm, Vincent Guittot,
	kernel-team, tkjos, adharmap, linux-doc, linux-kernel

On 26-06-20, 16:57, Quentin Perret wrote:
> On Friday 26 Jun 2020 at 09:21:44 (+0530), Viresh Kumar wrote:
> > index e798a1193bdf..93c6399c1a42 100644
> > --- a/drivers/cpufreq/cpufreq.c
> > +++ b/drivers/cpufreq/cpufreq.c
> > @@ -50,6 +50,9 @@ static LIST_HEAD(cpufreq_governor_list);
> >  #define for_each_governor(__governor)				\
> >  	list_for_each_entry(__governor, &cpufreq_governor_list, governor_list)
> >  
> > +static char cpufreq_param_governor[CPUFREQ_NAME_LEN];
> > +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 +1064,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;
> >  	bool put_governor = false;
> > @@ -1071,22 +1073,29 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
> >  		/* Update policy governor to the one used before hotplug. */
> >  		gov = get_governor(policy->last_governor);
> >  		if (gov) {
> > -			put_governor = true;
> >  			pr_debug("Restoring governor %s for cpu %d\n",
> > -				 policy->governor->name, policy->cpu);
> > -		} else if (def_gov) {
> > -			gov = def_gov;
> > +				 gov->name, policy->cpu);
> >  		} else {
> > -			return -ENODATA;
> > +			gov = get_governor(default_governor);
> > +		}
> > +
> > +		if (gov) {
> > +			put_governor = true;
> > +		} else {
> > +			gov = cpufreq_default_governor();
> > +			if (!gov)
> > +				return -ENODATA;
> >  		}
> 
> As mentioned on patch 01, doing put_module() below if gov != NULL would
> avoid this dance with put_governor, but this works too, so no strong
> opinion.

I did it this way because the code looks buggy otherwise, even though
it isn't as put_module() handles it just fine. And so I would like to
keep it this way, unless there are two votes against mine :)

> > +
> >  	} 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.
> >  			 */
> > @@ -2796,13 +2805,22 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
> >  
> >  static int __init cpufreq_core_init(void)
> >  {
> > +	struct cpufreq_governor *gov = cpufreq_default_governor();
> > +	char *name = gov->name;
> > +
> >  	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(cpufreq_param_governor))
> > +		name = cpufreq_param_governor;
> > +
> > +	strncpy(default_governor, name, CPUFREQ_NAME_LEN);
> 
> Do we need both cpufreq_param_governor and default_governor?
> Could we move everything to only one of them? Something a little bit
> like that maybe?

No because we want to fallback to the default governor when the
governor shown by the cpufreq_param_governor is valid but missing.

> Also, one thing to keep in mind with this version (or the one you
> suggested) is that if the command line parameter is not valid, we will
> not fallback on the builtin default for the ->setpolicy() case. But I
> suppose one might argue this is a reasonable behaviour, so no objection
> from me.

Right, I did that on purpose.

> Otherwise, apart from these nits, I gave this a go on my setup, with
> builtin and modular governors & drivers, and everything worked exactly
> as expected.

Thanks for testing it out Quentin.

-- 
viresh

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 1/3] cpufreq: Fix locking issues with governors
  2020-06-26  8:24   ` Quentin Perret
@ 2020-06-29  2:13     ` Viresh Kumar
  2020-06-29  8:05       ` Quentin Perret
  2020-06-29 13:13       ` Rafael J. Wysocki
  0 siblings, 2 replies; 11+ messages in thread
From: Viresh Kumar @ 2020-06-29  2:13 UTC (permalink / raw)
  To: Quentin Perret
  Cc: Rafael Wysocki, linux-pm, Vincent Guittot, kernel-team, tkjos,
	adharmap, linux-kernel

On 26-06-20, 09:24, Quentin Perret wrote:
> On Friday 26 Jun 2020 at 09:21:42 (+0530), Viresh Kumar wrote:
> > The locking around governors handling isn't adequate currently. The list
> > of governors should never be traversed without locking in place. Also we
> > must make sure the governor isn't removed while it is still referenced
> > by code.
> > 
> > Reported-by: Quentin Perret <qperret@google.com>
> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > ---
> >  drivers/cpufreq/cpufreq.c | 59 ++++++++++++++++++++++++---------------
> >  1 file changed, 36 insertions(+), 23 deletions(-)
> > 
> > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> > index 0128de3603df..e798a1193bdf 100644
> > --- a/drivers/cpufreq/cpufreq.c
> > +++ b/drivers/cpufreq/cpufreq.c
> > @@ -621,6 +621,24 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
> >  	return NULL;
> >  }
> >  
> > +static struct cpufreq_governor *get_governor(const char *str_governor)
> > +{
> > +	struct cpufreq_governor *t;
> > +
> > +	mutex_lock(&cpufreq_governor_mutex);
> > +	t = find_governor(str_governor);
> > +	if (!t)
> > +		goto unlock;
> > +
> > +	if (!try_module_get(t->owner))
> > +		t = NULL;
> > +
> > +unlock:
> > +	mutex_unlock(&cpufreq_governor_mutex);
> > +
> > +	return t;
> > +}
> > +
> >  static unsigned int cpufreq_parse_policy(char *str_governor)
> >  {
> >  	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
> > @@ -640,28 +658,14 @@ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
> >  {
> >  	struct cpufreq_governor *t;
> >  
> > -	mutex_lock(&cpufreq_governor_mutex);
> > -
> > -	t = find_governor(str_governor);
> > -	if (!t) {
> > -		int ret;
> > -
> > -		mutex_unlock(&cpufreq_governor_mutex);
> > -
> > -		ret = request_module("cpufreq_%s", str_governor);
> > -		if (ret)
> > -			return NULL;
> > -
> > -		mutex_lock(&cpufreq_governor_mutex);
> > +	t = get_governor(str_governor);
> > +	if (t)
> > +		return t;
> >  
> > -		t = find_governor(str_governor);
> > -	}
> > -	if (t && !try_module_get(t->owner))
> > -		t = NULL;
> > -
> > -	mutex_unlock(&cpufreq_governor_mutex);
> > +	if (request_module("cpufreq_%s", str_governor))
> > +		return NULL;
> >  
> > -	return t;
> > +	return get_governor(str_governor);
> >  }
> >  
> >  /**
> > @@ -815,12 +819,14 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
> >  		goto out;
> >  	}
> >  
> > +	mutex_lock(&cpufreq_governor_mutex);
> >  	for_each_governor(t) {
> >  		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
> >  		    - (CPUFREQ_NAME_LEN + 2)))
> > -			goto out;
> > +			break;
> >  		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
> >  	}
> > +	mutex_unlock(&cpufreq_governor_mutex);
> >  out:
> >  	i += sprintf(&buf[i], "\n");
> >  	return i;
> > @@ -1058,11 +1064,14 @@ 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;
> > +	bool put_governor = false;
> > +	int ret;
> >  
> >  	if (has_target()) {
> >  		/* Update policy governor to the one used before hotplug. */
> > -		gov = find_governor(policy->last_governor);
> > +		gov = get_governor(policy->last_governor);
> >  		if (gov) {
> > +			put_governor = true;
> >  			pr_debug("Restoring governor %s for cpu %d\n",
> >  				 policy->governor->name, policy->cpu);
> >  		} else if (def_gov) {
> > @@ -1089,7 +1098,11 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
> >  			return -ENODATA;
> >  	}
> >  
> > -	return cpufreq_set_policy(policy, gov, pol);
> > +	ret = cpufreq_set_policy(policy, gov, pol);
> > +	if (put_governor)
> > +		module_put(gov->owner);
> 
> Nit: I think you could safely do
> 
> 	if (gov)
> 		module_put(gov->owner);
> 
> and get rid of 'put_governor', given that try_module_get() and
> module_put() are nops if owner is NULL (which is guaranteed for
> the result of cpufreq_default_governor() as it is builtin).

I described why I chose to keep it that way in the other email, but I
am all for dropping the variable. And so what about this ?

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e798a1193bdf..d9e9ae7051bb 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1064,18 +1064,17 @@ 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;
-       bool put_governor = false;
        int ret;
 
        if (has_target()) {
                /* Update policy governor to the one used before hotplug. */
                gov = get_governor(policy->last_governor);
                if (gov) {
-                       put_governor = true;
                        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);
                } else {
                        return -ENODATA;
                }
@@ -1099,7 +1098,7 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
        }
 
        ret = cpufreq_set_policy(policy, gov, pol);
-       if (put_governor)
+       if (gov)
                module_put(gov->owner);
 
        return ret;

-- 
viresh

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 3/3] cpufreq: Specify default governor on command line
  2020-06-29  2:08     ` Viresh Kumar
@ 2020-06-29  8:03       ` Quentin Perret
  0 siblings, 0 replies; 11+ messages in thread
From: Quentin Perret @ 2020-06-29  8:03 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, Jonathan Corbet, linux-pm, Vincent Guittot,
	kernel-team, tkjos, adharmap, linux-doc, linux-kernel

On Monday 29 Jun 2020 at 07:38:43 (+0530), Viresh Kumar wrote:
> On 26-06-20, 16:57, Quentin Perret wrote:
> > Do we need both cpufreq_param_governor and default_governor?
> > Could we move everything to only one of them? Something a little bit
> > like that maybe?
> 
> No because we want to fallback to the default governor when the
> governor shown by the cpufreq_param_governor is valid but missing.

But that would still work with my suggestion no? You still fallback to
calling cpufreq_default_governor() in cpufreq_init_policy() if
get_governor(default_governor) doesn't succeed, so we should be covered.

Thanks,
Quentin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 1/3] cpufreq: Fix locking issues with governors
  2020-06-29  2:13     ` Viresh Kumar
@ 2020-06-29  8:05       ` Quentin Perret
  2020-06-29 13:13       ` Rafael J. Wysocki
  1 sibling, 0 replies; 11+ messages in thread
From: Quentin Perret @ 2020-06-29  8:05 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Rafael Wysocki, linux-pm, Vincent Guittot, kernel-team, tkjos,
	adharmap, linux-kernel

On Monday 29 Jun 2020 at 07:43:09 (+0530), Viresh Kumar wrote:
> I described why I chose to keep it that way in the other email, but I
> am all for dropping the variable. And so what about this ?
> 
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index e798a1193bdf..d9e9ae7051bb 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1064,18 +1064,17 @@ 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;
> -       bool put_governor = false;
>         int ret;
>  
>         if (has_target()) {
>                 /* Update policy governor to the one used before hotplug. */
>                 gov = get_governor(policy->last_governor);
>                 if (gov) {
> -                       put_governor = true;
>                         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);
>                 } else {
>                         return -ENODATA;
>                 }
> @@ -1099,7 +1098,7 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
>         }
>  
>         ret = cpufreq_set_policy(policy, gov, pol);
> -       if (put_governor)
> +       if (gov)
>                 module_put(gov->owner);
>  
>         return ret;

Right, I guess this is a good trade-off, so that works for me.

Thanks,
Quentin

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 1/3] cpufreq: Fix locking issues with governors
  2020-06-29  2:13     ` Viresh Kumar
  2020-06-29  8:05       ` Quentin Perret
@ 2020-06-29 13:13       ` Rafael J. Wysocki
  1 sibling, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2020-06-29 13:13 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: Quentin Perret, Rafael Wysocki, Linux PM, Vincent Guittot,
	Cc: Android Kernel, Todd Kjos, adharmap,
	Linux Kernel Mailing List

On Mon, Jun 29, 2020 at 4:13 AM Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
> On 26-06-20, 09:24, Quentin Perret wrote:
> > On Friday 26 Jun 2020 at 09:21:42 (+0530), Viresh Kumar wrote:
> > > The locking around governors handling isn't adequate currently. The list
> > > of governors should never be traversed without locking in place. Also we
> > > must make sure the governor isn't removed while it is still referenced
> > > by code.
> > >
> > > Reported-by: Quentin Perret <qperret@google.com>
> > > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> > > ---
> > >  drivers/cpufreq/cpufreq.c | 59 ++++++++++++++++++++++++---------------
> > >  1 file changed, 36 insertions(+), 23 deletions(-)
> > >
> > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> > > index 0128de3603df..e798a1193bdf 100644
> > > --- a/drivers/cpufreq/cpufreq.c
> > > +++ b/drivers/cpufreq/cpufreq.c
> > > @@ -621,6 +621,24 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
> > >     return NULL;
> > >  }
> > >
> > > +static struct cpufreq_governor *get_governor(const char *str_governor)
> > > +{
> > > +   struct cpufreq_governor *t;
> > > +
> > > +   mutex_lock(&cpufreq_governor_mutex);
> > > +   t = find_governor(str_governor);
> > > +   if (!t)
> > > +           goto unlock;
> > > +
> > > +   if (!try_module_get(t->owner))
> > > +           t = NULL;
> > > +
> > > +unlock:
> > > +   mutex_unlock(&cpufreq_governor_mutex);
> > > +
> > > +   return t;
> > > +}
> > > +
> > >  static unsigned int cpufreq_parse_policy(char *str_governor)
> > >  {
> > >     if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
> > > @@ -640,28 +658,14 @@ static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
> > >  {
> > >     struct cpufreq_governor *t;
> > >
> > > -   mutex_lock(&cpufreq_governor_mutex);
> > > -
> > > -   t = find_governor(str_governor);
> > > -   if (!t) {
> > > -           int ret;
> > > -
> > > -           mutex_unlock(&cpufreq_governor_mutex);
> > > -
> > > -           ret = request_module("cpufreq_%s", str_governor);
> > > -           if (ret)
> > > -                   return NULL;
> > > -
> > > -           mutex_lock(&cpufreq_governor_mutex);
> > > +   t = get_governor(str_governor);
> > > +   if (t)
> > > +           return t;
> > >
> > > -           t = find_governor(str_governor);
> > > -   }
> > > -   if (t && !try_module_get(t->owner))
> > > -           t = NULL;
> > > -
> > > -   mutex_unlock(&cpufreq_governor_mutex);
> > > +   if (request_module("cpufreq_%s", str_governor))
> > > +           return NULL;
> > >
> > > -   return t;
> > > +   return get_governor(str_governor);
> > >  }
> > >
> > >  /**
> > > @@ -815,12 +819,14 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy,
> > >             goto out;
> > >     }
> > >
> > > +   mutex_lock(&cpufreq_governor_mutex);
> > >     for_each_governor(t) {
> > >             if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
> > >                 - (CPUFREQ_NAME_LEN + 2)))
> > > -                   goto out;
> > > +                   break;
> > >             i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
> > >     }
> > > +   mutex_unlock(&cpufreq_governor_mutex);
> > >  out:
> > >     i += sprintf(&buf[i], "\n");
> > >     return i;
> > > @@ -1058,11 +1064,14 @@ 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;
> > > +   bool put_governor = false;
> > > +   int ret;
> > >
> > >     if (has_target()) {
> > >             /* Update policy governor to the one used before hotplug. */
> > > -           gov = find_governor(policy->last_governor);
> > > +           gov = get_governor(policy->last_governor);
> > >             if (gov) {
> > > +                   put_governor = true;
> > >                     pr_debug("Restoring governor %s for cpu %d\n",
> > >                              policy->governor->name, policy->cpu);
> > >             } else if (def_gov) {
> > > @@ -1089,7 +1098,11 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
> > >                     return -ENODATA;
> > >     }
> > >
> > > -   return cpufreq_set_policy(policy, gov, pol);
> > > +   ret = cpufreq_set_policy(policy, gov, pol);
> > > +   if (put_governor)
> > > +           module_put(gov->owner);
> >
> > Nit: I think you could safely do
> >
> >       if (gov)
> >               module_put(gov->owner);
> >
> > and get rid of 'put_governor', given that try_module_get() and
> > module_put() are nops if owner is NULL (which is guaranteed for
> > the result of cpufreq_default_governor() as it is builtin).
>
> I described why I chose to keep it that way in the other email, but I
> am all for dropping the variable. And so what about this ?

Works for me.

> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index e798a1193bdf..d9e9ae7051bb 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -1064,18 +1064,17 @@ 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;
> -       bool put_governor = false;
>         int ret;
>
>         if (has_target()) {
>                 /* Update policy governor to the one used before hotplug. */
>                 gov = get_governor(policy->last_governor);
>                 if (gov) {
> -                       put_governor = true;
>                         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);
>                 } else {
>                         return -ENODATA;
>                 }
> @@ -1099,7 +1098,7 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
>         }
>
>         ret = cpufreq_set_policy(policy, gov, pol);
> -       if (put_governor)
> +       if (gov)
>                 module_put(gov->owner);
>
>         return ret;
>
> --
> viresh

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, back to index

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-26  3:51 [PATCH v3 0/3] cpufreq: Allow default governor on cmdline and fix locking issues Viresh Kumar
2020-06-26  3:51 ` [PATCH V3 1/3] cpufreq: Fix locking issues with governors Viresh Kumar
2020-06-26  8:24   ` Quentin Perret
2020-06-29  2:13     ` Viresh Kumar
2020-06-29  8:05       ` Quentin Perret
2020-06-29 13:13       ` Rafael J. Wysocki
2020-06-26  3:51 ` [PATCH V3 2/3] cpufreq: Register governors at core_initcall Viresh Kumar
2020-06-26  3:51 ` [PATCH V3 3/3] cpufreq: Specify default governor on command line Viresh Kumar
2020-06-26 15:57   ` Quentin Perret
2020-06-29  2:08     ` Viresh Kumar
2020-06-29  8:03       ` Quentin Perret

Linux-PM Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-pm/0 linux-pm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-pm linux-pm/ https://lore.kernel.org/linux-pm \
		linux-pm@vger.kernel.org
	public-inbox-index linux-pm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-pm


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git