linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically
@ 2012-10-29 20:01 Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 1/7] PM / devfreq: export update_devfreq Nishanth Menon
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

The following series is based on:
linux-next                e083feb Merge branch 'acpi-next' into linux-next
from git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
In addition, this series depends on the following to apply cleanly:
https://patchwork.kernel.org/patch/1649621/
https://patchwork.kernel.org/patch/1663331/

This series allows the devfreq governors to be built as modules and switched
on the fly using sysfs controls (inspired by cpufreq's ability to do the same).

Tested on BeagleBoard XM(3730) with dummy driver[1]:

/sys/devices/platform/iva.0/devfreq/iva.0 # ls
available_frequencies  governor               power
available_governors    max_freq               subsystem
cur_freq               min_freq               target_freq
device                 polling_interval       uevent
/sys/devices/platform/iva.0/devfreq/iva.0 # cat available_governors 
simple_ondemand
/sys/devices/platform/iva.0/devfreq/iva.0 # modprobe governor_userspace
/sys/devices/platform/iva.0/devfreq/iva.0 # cat available_governors 
userspace simple_ondemand
/sys/devices/platform/iva.0/devfreq/iva.0 # 
/sys/devices/platform/iva.0/devfreq/iva.0 # echo -n "userspace">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # ls
available_frequencies  max_freq               target_freq
available_governors    min_freq               uevent
cur_freq               polling_interval       userspace
device                 power
governor               subsystem
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor
userspace
/sys/devices/platform/iva.0/devfreq/iva.0 # echo -n "simple_ondemand">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor
simple_ondemand
/sys/devices/platform/iva.0/devfreq/iva.0 # ls
available_frequencies  governor               power
available_governors    max_freq               subsystem
cur_freq               min_freq               target_freq
device                 polling_interval       uevent

Nishanth Menon (7):
  PM / devfreq: export update_devfreq
  PM / devfreq: provide hooks for governors to be registered
  PM / devfreq: register governors with devfreq framework
  PM / devfreq: map devfreq drivers to governor using name
  PM / devfreq: governors: add GPL module license and allow module
    build
  PM / devfreq: allow sysfs governor node to switch governor
  PM / devfreq: Add sysfs node to expose available governors

 Documentation/ABI/testing/sysfs-class-devfreq |    9 +-
 drivers/devfreq/Kconfig                       |    8 +-
 drivers/devfreq/devfreq.c                     |  249 ++++++++++++++++++++++++-
 drivers/devfreq/exynos4_bus.c                 |    2 +-
 drivers/devfreq/governor.h                    |    4 +
 drivers/devfreq/governor_performance.c        |   22 ++-
 drivers/devfreq/governor_powersave.c          |   22 ++-
 drivers/devfreq/governor_simpleondemand.c     |   22 ++-
 drivers/devfreq/governor_userspace.c          |   22 ++-
 include/linux/devfreq.h                       |   24 +--
 10 files changed, 348 insertions(+), 36 deletions(-)

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

[1] http://pastebin.pandaboard.org/index.php/view/85100576

Regards,
Nishanth Menon
-- 
1.7.9.5


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

* [linux-next PATCH 1/7] PM / devfreq: export update_devfreq
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 2/7] PM / devfreq: provide hooks for governors to be registered Nishanth Menon
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

Allow update_devfreq to be used by devfreq governor built
as modules

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 drivers/devfreq/devfreq.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index c071ea0..6d3070d 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -115,6 +115,7 @@ int update_devfreq(struct devfreq *devfreq)
 	devfreq->previous_freq = freq;
 	return err;
 }
+EXPORT_SYMBOL(update_devfreq);
 
 /**
  * devfreq_monitor() - Periodically poll devfreq objects.
-- 
1.7.9.5


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

* [linux-next PATCH 2/7] PM / devfreq: provide hooks for governors to be registered
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 1/7] PM / devfreq: export update_devfreq Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 3/7] PM / devfreq: register governors with devfreq framework Nishanth Menon
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

Add devfreq_add_governor and devfreq_remove_governor which
can be invoked by governors to register with devfreq.

This sets up the stage to dynamically switch governors and
allow governors to be dynamically loaded as well.

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 drivers/devfreq/devfreq.c  |   91 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/devfreq/governor.h |    4 ++
 include/linux/devfreq.h    |    3 ++
 3 files changed, 98 insertions(+)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 6d3070d..9c079d2 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -36,6 +36,8 @@ static struct class *devfreq_class;
  */
 static struct workqueue_struct *devfreq_wq;
 
+/* The list of all device-devfreq governors */
+static LIST_HEAD(devfreq_governor_list);
 /* The list of all device-devfreq */
 static LIST_HEAD(devfreq_list);
 static DEFINE_MUTEX(devfreq_list_lock);
@@ -66,6 +68,32 @@ static struct devfreq *find_device_devfreq(struct device *dev)
 	return ERR_PTR(-ENODEV);
 }
 
+/**
+ * find_devfreq_governor() - find devfreq governor from name
+ * @name:	name of the governor
+ *
+ * Search the list of devfreq governors and return the matched
+ * governor's pointer. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq_governor *find_devfreq_governor(const char *name)
+{
+	struct devfreq_governor *tmp_governor;
+
+	if (unlikely(IS_ERR_OR_NULL(name))) {
+		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+	WARN(!mutex_is_locked(&devfreq_list_lock),
+	     "devfreq_list_lock must be locked.");
+
+	list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
+		if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+			return tmp_governor;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
 /* Load monitoring helper functions for governors use */
 
 /**
@@ -456,6 +484,69 @@ int devfreq_resume_device(struct devfreq *devfreq)
 }
 EXPORT_SYMBOL(devfreq_resume_device);
 
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor:	the devfreq governor to be added
+ */
+int devfreq_add_governor(struct devfreq_governor *governor)
+{
+	struct devfreq_governor *g;
+	int err = 0;
+
+	if (!governor) {
+		pr_err("%s: Invalid parameters.\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&devfreq_list_lock);
+	g = find_devfreq_governor(governor->name);
+	if (!IS_ERR(g)) {
+		pr_err("%s: governor %s already registered\n", __func__,
+		       g->name);
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	list_add(&governor->node, &devfreq_governor_list);
+
+err_out:
+	mutex_unlock(&devfreq_list_lock);
+
+	return err;
+}
+EXPORT_SYMBOL(devfreq_add_governor);
+
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @governor:	the devfreq governor to be removed
+ */
+int devfreq_remove_governor(struct devfreq_governor *governor)
+{
+	struct devfreq_governor *g;
+	int err = 0;
+
+	if (!governor) {
+		pr_err("%s: Invalid parameters.\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&devfreq_list_lock);
+	g = find_devfreq_governor(governor->name);
+	if (IS_ERR(g)) {
+		pr_err("%s: governor %s not registered\n", __func__,
+		       g->name);
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	list_del(&governor->node);
+err_out:
+	mutex_unlock(&devfreq_list_lock);
+
+	return err;
+}
+EXPORT_SYMBOL(devfreq_remove_governor);
+
 static ssize_t show_governor(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index 26432ac..fad7d63 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -34,4 +34,8 @@ extern void devfreq_monitor_suspend(struct devfreq *devfreq);
 extern void devfreq_monitor_resume(struct devfreq *devfreq);
 extern void devfreq_interval_update(struct devfreq *devfreq,
 					unsigned int *delay);
+
+extern int devfreq_add_governor(struct devfreq_governor *governor);
+extern int devfreq_remove_governor(struct devfreq_governor *governor);
+
 #endif /* _GOVERNOR_H */
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 1461fb2..a28d935 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -87,6 +87,7 @@ struct devfreq_dev_profile {
 
 /**
  * struct devfreq_governor - Devfreq policy governor
+ * @node:		list node - contains registered devfreq governors
  * @name:		Governor's name
  * @get_target_freq:	Returns desired operating frequency for the device.
  *			Basically, get_target_freq will run
@@ -102,6 +103,8 @@ struct devfreq_dev_profile {
  * Note that the callbacks are called with devfreq->lock locked by devfreq.
  */
 struct devfreq_governor {
+	struct list_head node;
+
 	const char name[DEVFREQ_NAME_LEN];
 	int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
 	int (*event_handler)(struct devfreq *devfreq,
-- 
1.7.9.5


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

* [linux-next PATCH 3/7] PM / devfreq: register governors with devfreq framework
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 1/7] PM / devfreq: export update_devfreq Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 2/7] PM / devfreq: provide hooks for governors to be registered Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 4/7] PM / devfreq: map devfreq drivers to governor using name Nishanth Menon
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

With the new registration functions, governors can be now
registered with devfreq framework.

NOTE: generates 'discards qualifiers from pointer target type'
build warnings, which the next patche in this series fixes

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 drivers/devfreq/governor_performance.c    |   18 ++++++++++++++++++
 drivers/devfreq/governor_powersave.c      |   18 ++++++++++++++++++
 drivers/devfreq/governor_simpleondemand.c |   18 ++++++++++++++++++
 drivers/devfreq/governor_userspace.c      |   18 ++++++++++++++++++
 4 files changed, 72 insertions(+)

diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index eea3f9b..db8ff77 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -45,3 +45,21 @@ const struct devfreq_governor devfreq_performance = {
 	.get_target_freq = devfreq_performance_func,
 	.event_handler = devfreq_performance_handler,
 };
+
+static int __init devfreq_performance_init(void)
+{
+	return devfreq_add_governor(&devfreq_performance);
+}
+subsys_initcall(devfreq_performance_init);
+
+static void __exit devfreq_performance_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&devfreq_performance);
+	if (ret)
+		pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+	return;
+}
+module_exit(devfreq_performance_exit);
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index 2868d98..30f0fca 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -42,3 +42,21 @@ const struct devfreq_governor devfreq_powersave = {
 	.get_target_freq = devfreq_powersave_func,
 	.event_handler = devfreq_powersave_handler,
 };
+
+static int __init devfreq_powersave_init(void)
+{
+	return devfreq_add_governor(&devfreq_powersave);
+}
+subsys_initcall(devfreq_powersave_init);
+
+static void __exit devfreq_powersave_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&devfreq_powersave);
+	if (ret)
+		pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+	return;
+}
+module_exit(devfreq_powersave_exit);
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index b5cf0fb..85f9ed5 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -125,3 +125,21 @@ const struct devfreq_governor devfreq_simple_ondemand = {
 	.get_target_freq = devfreq_simple_ondemand_func,
 	.event_handler = devfreq_simple_ondemand_handler,
 };
+
+static int __init devfreq_simple_ondemand_init(void)
+{
+	return devfreq_add_governor(&devfreq_simple_ondemand);
+}
+subsys_initcall(devfreq_simple_ondemand_init);
+
+static void __exit devfreq_simple_ondemand_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&devfreq_simple_ondemand);
+	if (ret)
+		pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+	return;
+}
+module_exit(devfreq_simple_ondemand_exit);
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 7067555..110f178 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -140,3 +140,21 @@ const struct devfreq_governor devfreq_userspace = {
 	.get_target_freq = devfreq_userspace_func,
 	.event_handler = devfreq_userspace_handler,
 };
+
+static int __init devfreq_userspace_init(void)
+{
+	return devfreq_add_governor(&devfreq_userspace);
+}
+subsys_initcall(devfreq_userspace_init);
+
+static void __exit devfreq_userspace_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&devfreq_userspace);
+	if (ret)
+		pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+	return;
+}
+module_exit(devfreq_userspace_exit);
-- 
1.7.9.5


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

* [linux-next PATCH 4/7] PM / devfreq: map devfreq drivers to governor using name
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
                   ` (2 preceding siblings ...)
  2012-10-29 20:01 ` [linux-next PATCH 3/7] PM / devfreq: register governors with devfreq framework Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 5/7] PM / devfreq: governors: add GPL module license and allow module build Nishanth Menon
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

Allow devfreq drivers to register a preferred governor name
and when the devfreq governor loads itself at a later point
required drivers are managed appropriately, at the time of
unload of a devfreq governor, stop managing those drivers
as well.

Since the governor structures do not need to be exposed
anymore, remove the definitions and make them static

NOTE: devfreq_list_lock is now used to protect governor
start and stop - as this allows us to protect governors and
devfreq with the proper dependencies as needed.

As part of this change, change the registration of exynos
bus driver to request for ondemand using the governor name.

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 drivers/devfreq/devfreq.c                 |   95 ++++++++++++++++++++++++++---
 drivers/devfreq/exynos4_bus.c             |    2 +-
 drivers/devfreq/governor_performance.c    |    2 +-
 drivers/devfreq/governor_powersave.c      |    2 +-
 drivers/devfreq/governor_simpleondemand.c |    2 +-
 drivers/devfreq/governor_userspace.c      |    2 +-
 include/linux/devfreq.h                   |   21 ++-----
 7 files changed, 96 insertions(+), 30 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 9c079d2..bd96e32 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -114,6 +114,9 @@ int update_devfreq(struct devfreq *devfreq)
 		return -EINVAL;
 	}
 
+	if (!devfreq->governor)
+		return -EINVAL;
+
 	/* Reevaluate the proper frequency */
 	err = devfreq->governor->get_target_freq(devfreq, &freq);
 	if (err)
@@ -329,7 +332,9 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
 	list_del(&devfreq->node);
 	mutex_unlock(&devfreq_list_lock);
 
-	devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_STOP, NULL);
+	if (devfreq->governor)
+		devfreq->governor->event_handler(devfreq,
+						 DEVFREQ_GOV_STOP, NULL);
 
 	if (devfreq->profile->exit)
 		devfreq->profile->exit(devfreq->dev.parent);
@@ -362,19 +367,20 @@ static void devfreq_dev_release(struct device *dev)
  * devfreq_add_device() - Add devfreq feature to the device
  * @dev:	the device to add devfreq feature.
  * @profile:	device-specific profile to run devfreq.
- * @governor:	the policy to choose frequency.
+ * @governor_name:	name of the policy to choose frequency.
  * @data:	private data for the governor. The devfreq framework does not
  *		touch this value.
  */
 struct devfreq *devfreq_add_device(struct device *dev,
 				   struct devfreq_dev_profile *profile,
-				   const struct devfreq_governor *governor,
+				   const char *governor_name,
 				   void *data)
 {
 	struct devfreq *devfreq;
+	struct devfreq_governor *governor;
 	int err = 0;
 
-	if (!dev || !profile || !governor) {
+	if (!dev || !profile || !governor_name) {
 		dev_err(dev, "%s: Invalid parameters.\n", __func__);
 		return ERR_PTR(-EINVAL);
 	}
@@ -402,7 +408,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
 	devfreq->dev.class = devfreq_class;
 	devfreq->dev.release = devfreq_dev_release;
 	devfreq->profile = profile;
-	devfreq->governor = governor;
+	strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
 	devfreq->previous_freq = profile->initial_freq;
 	devfreq->data = data;
 	devfreq->nb.notifier_call = devfreq_notifier_call;
@@ -419,10 +425,14 @@ struct devfreq *devfreq_add_device(struct device *dev,
 
 	mutex_lock(&devfreq_list_lock);
 	list_add(&devfreq->node, &devfreq_list);
-	mutex_unlock(&devfreq_list_lock);
 
-	err = devfreq->governor->event_handler(devfreq,
-				DEVFREQ_GOV_START, NULL);
+	governor = find_devfreq_governor(devfreq->governor_name);
+	if (!IS_ERR(governor))
+		devfreq->governor = governor;
+	if (devfreq->governor)
+		err = devfreq->governor->event_handler(devfreq,
+					DEVFREQ_GOV_START, NULL);
+	mutex_unlock(&devfreq_list_lock);
 	if (err) {
 		dev_err(dev, "%s: Unable to start governor for the device\n",
 			__func__);
@@ -465,6 +475,9 @@ int devfreq_suspend_device(struct devfreq *devfreq)
 	if (!devfreq)
 		return -EINVAL;
 
+	if (!devfreq->governor)
+		return 0;
+
 	return devfreq->governor->event_handler(devfreq,
 				DEVFREQ_GOV_SUSPEND, NULL);
 }
@@ -479,6 +492,9 @@ int devfreq_resume_device(struct devfreq *devfreq)
 	if (!devfreq)
 		return -EINVAL;
 
+	if (!devfreq->governor)
+		return 0;
+
 	return devfreq->governor->event_handler(devfreq,
 				DEVFREQ_GOV_RESUME, NULL);
 }
@@ -491,6 +507,7 @@ EXPORT_SYMBOL(devfreq_resume_device);
 int devfreq_add_governor(struct devfreq_governor *governor)
 {
 	struct devfreq_governor *g;
+	struct devfreq *devfreq;
 	int err = 0;
 
 	if (!governor) {
@@ -509,6 +526,38 @@ int devfreq_add_governor(struct devfreq_governor *governor)
 
 	list_add(&governor->node, &devfreq_governor_list);
 
+	list_for_each_entry(devfreq, &devfreq_list, node) {
+		int ret = 0;
+		struct device *dev = devfreq->dev.parent;
+
+		if (!strncmp(devfreq->governor_name, governor->name,
+			     DEVFREQ_NAME_LEN)) {
+			/* The following should never occur */
+			if (devfreq->governor) {
+				dev_warn(dev,
+					 "%s: Governor %s already present\n",
+					 __func__, devfreq->governor->name);
+				ret = devfreq->governor->event_handler(devfreq,
+							DEVFREQ_GOV_STOP, NULL);
+				if (ret) {
+					dev_warn(dev,
+						 "%s: Governor %s stop = %d\n",
+						 __func__,
+						 devfreq->governor->name, ret);
+				}
+				/* Fall through */
+			}
+			devfreq->governor = governor;
+			ret = devfreq->governor->event_handler(devfreq,
+						DEVFREQ_GOV_START, NULL);
+			if (ret) {
+				dev_warn(dev, "%s: Governor %s start=%d\n",
+					 __func__, devfreq->governor->name,
+					 ret);
+			}
+		}
+	}
+
 err_out:
 	mutex_unlock(&devfreq_list_lock);
 
@@ -523,6 +572,7 @@ EXPORT_SYMBOL(devfreq_add_governor);
 int devfreq_remove_governor(struct devfreq_governor *governor)
 {
 	struct devfreq_governor *g;
+	struct devfreq *devfreq;
 	int err = 0;
 
 	if (!governor) {
@@ -538,6 +588,29 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
 		err = -EINVAL;
 		goto err_out;
 	}
+	list_for_each_entry(devfreq, &devfreq_list, node) {
+		int ret;
+		struct device *dev = devfreq->dev.parent;
+
+		if (!strncmp(devfreq->governor_name, governor->name,
+			     DEVFREQ_NAME_LEN)) {
+			/* we should have a devfreq governor! */
+			if (!devfreq->governor) {
+				dev_warn(dev, "%s: Governor %s NOT present\n",
+					 __func__, governor->name);
+				continue;
+				/* Fall through */
+			}
+			ret = devfreq->governor->event_handler(devfreq,
+						DEVFREQ_GOV_STOP, NULL);
+			if (ret) {
+				dev_warn(dev, "%s: Governor %s stop=%d\n",
+					 __func__, devfreq->governor->name,
+					 ret);
+			}
+			devfreq->governor = NULL;
+		}
+	}
 
 	list_del(&governor->node);
 err_out:
@@ -550,6 +623,9 @@ EXPORT_SYMBOL(devfreq_remove_governor);
 static ssize_t show_governor(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
+	if (!to_devfreq(dev)->governor)
+		return -EINVAL;
+
 	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
 }
 
@@ -586,6 +662,9 @@ static ssize_t store_polling_interval(struct device *dev,
 	unsigned int value;
 	int ret;
 
+	if (!df->governor)
+		return -EINVAL;
+
 	ret = sscanf(buf, "%u", &value);
 	if (ret != 1)
 		return -EINVAL;
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 88ddc77..b8b1a00 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -1045,7 +1045,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
 	busfreq_mon_reset(data);
 
 	data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
-					   &devfreq_simple_ondemand, NULL);
+					   "simple_ondemand", NULL);
 	if (IS_ERR(data->devfreq)) {
 		err = PTR_ERR(data->devfreq);
 		goto err_opp_add;
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index db8ff77..865a369 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -40,7 +40,7 @@ static int devfreq_performance_handler(struct devfreq *devfreq,
 	return ret;
 }
 
-const struct devfreq_governor devfreq_performance = {
+static struct devfreq_governor devfreq_performance = {
 	.name = "performance",
 	.get_target_freq = devfreq_performance_func,
 	.event_handler = devfreq_performance_handler,
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index 30f0fca..8612c0f 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -37,7 +37,7 @@ static int devfreq_powersave_handler(struct devfreq *devfreq,
 	return ret;
 }
 
-const struct devfreq_governor devfreq_powersave = {
+static struct devfreq_governor devfreq_powersave = {
 	.name = "powersave",
 	.get_target_freq = devfreq_powersave_func,
 	.event_handler = devfreq_powersave_handler,
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index 85f9ed5..a870a24 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -120,7 +120,7 @@ static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
 	return 0;
 }
 
-const struct devfreq_governor devfreq_simple_ondemand = {
+static struct devfreq_governor devfreq_simple_ondemand = {
 	.name = "simple_ondemand",
 	.get_target_freq = devfreq_simple_ondemand_func,
 	.event_handler = devfreq_simple_ondemand_handler,
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 110f178..34fb80f 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -135,7 +135,7 @@ static int devfreq_userspace_handler(struct devfreq *devfreq,
 	return ret;
 }
 
-const struct devfreq_governor devfreq_userspace = {
+static struct devfreq_governor devfreq_userspace = {
 	.name = "userspace",
 	.get_target_freq = devfreq_userspace_func,
 	.event_handler = devfreq_userspace_handler,
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index a28d935..092fe72 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -120,6 +120,7 @@ struct devfreq_governor {
  *		using devfreq.
  * @profile:	device-specific devfreq profile
  * @governor:	method how to choose frequency based on the usage.
+ * @governor_name:	devfreq governor name for use with this devfreq
  * @nb:		notifier block used to notify devfreq object that it should
  *		reevaluate operable frequencies. Devfreq users may use
  *		devfreq.nb to the corresponding register notifier call chain.
@@ -146,6 +147,7 @@ struct devfreq {
 	struct device dev;
 	struct devfreq_dev_profile *profile;
 	const struct devfreq_governor *governor;
+	char governor_name[DEVFREQ_NAME_LEN];
 	struct notifier_block nb;
 	struct delayed_work work;
 
@@ -161,7 +163,7 @@ struct devfreq {
 #if defined(CONFIG_PM_DEVFREQ)
 extern struct devfreq *devfreq_add_device(struct device *dev,
 				  struct devfreq_dev_profile *profile,
-				  const struct devfreq_governor *governor,
+				  const char *governor_name,
 				  void *data);
 extern int devfreq_remove_device(struct devfreq *devfreq);
 extern int devfreq_suspend_device(struct devfreq *devfreq);
@@ -175,17 +177,7 @@ extern int devfreq_register_opp_notifier(struct device *dev,
 extern int devfreq_unregister_opp_notifier(struct device *dev,
 					   struct devfreq *devfreq);
 
-#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
-extern const struct devfreq_governor devfreq_powersave;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
-extern const struct devfreq_governor devfreq_performance;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
-extern const struct devfreq_governor devfreq_userspace;
-#endif
 #ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
-extern const struct devfreq_governor devfreq_simple_ondemand;
 /**
  * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
  *	and devfreq_add_device
@@ -208,7 +200,7 @@ struct devfreq_simple_ondemand_data {
 #else /* !CONFIG_PM_DEVFREQ */
 static struct devfreq *devfreq_add_device(struct device *dev,
 					  struct devfreq_dev_profile *profile,
-					  struct devfreq_governor *governor,
+					  const char *governor_name,
 					  void *data)
 {
 	return NULL;
@@ -247,11 +239,6 @@ static int devfreq_unregister_opp_notifier(struct device *dev,
 	return -EINVAL;
 }
 
-#define devfreq_powersave	NULL
-#define devfreq_performance	NULL
-#define devfreq_userspace	NULL
-#define devfreq_simple_ondemand	NULL
-
 #endif /* CONFIG_PM_DEVFREQ */
 
 #endif /* __LINUX_DEVFREQ_H__ */
-- 
1.7.9.5


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

* [linux-next PATCH 5/7] PM / devfreq: governors: add GPL module license and allow module build
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
                   ` (3 preceding siblings ...)
  2012-10-29 20:01 ` [linux-next PATCH 4/7] PM / devfreq: map devfreq drivers to governor using name Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 7/7] PM / devfreq: Add sysfs node to expose available governors Nishanth Menon
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

Add GPL module license and remove the static build
restrictions for building governors. This allows governors now
to be loaded on a need basis and reloaded independently of kernel
build

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 drivers/devfreq/Kconfig                   |    8 ++++----
 drivers/devfreq/governor_performance.c    |    2 ++
 drivers/devfreq/governor_powersave.c      |    2 ++
 drivers/devfreq/governor_simpleondemand.c |    2 ++
 drivers/devfreq/governor_userspace.c      |    2 ++
 5 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index f6b0a6e2..0f079be 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -30,7 +30,7 @@ if PM_DEVFREQ
 comment "DEVFREQ Governors"
 
 config DEVFREQ_GOV_SIMPLE_ONDEMAND
-	bool "Simple Ondemand"
+	tristate "Simple Ondemand"
 	help
 	  Chooses frequency based on the recent load on the device. Works
 	  similar as ONDEMAND governor of CPUFREQ does. A device with
@@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND
 	  values to the governor with data field at devfreq_add_device().
 
 config DEVFREQ_GOV_PERFORMANCE
-	bool "Performance"
+	tristate "Performance"
 	help
 	  Sets the frequency at the maximum available frequency.
 	  This governor always returns UINT_MAX as frequency so that
@@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE
 	  at any time.
 
 config DEVFREQ_GOV_POWERSAVE
-	bool "Powersave"
+	tristate "Powersave"
 	help
 	  Sets the frequency at the minimum available frequency.
 	  This governor always returns 0 as frequency so that
@@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE
 	  at any time.
 
 config DEVFREQ_GOV_USERSPACE
-	bool "Userspace"
+	tristate "Userspace"
 	help
 	  Sets the frequency at the user specified one.
 	  This governor returns the user configured frequency if there
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index 865a369..c72f942 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include <linux/module.h>
 #include "governor.h"
 
 static int devfreq_performance_func(struct devfreq *df,
@@ -63,3 +64,4 @@ static void __exit devfreq_performance_exit(void)
 	return;
 }
 module_exit(devfreq_performance_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index 8612c0f..0c6bed5 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include <linux/module.h>
 #include "governor.h"
 
 static int devfreq_powersave_func(struct devfreq *df,
@@ -60,3 +61,4 @@ static void __exit devfreq_powersave_exit(void)
 	return;
 }
 module_exit(devfreq_powersave_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index a870a24..0720ba8 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/devfreq.h>
 #include <linux/math64.h>
 #include "governor.h"
@@ -143,3 +144,4 @@ static void __exit devfreq_simple_ondemand_exit(void)
 	return;
 }
 module_exit(devfreq_simple_ondemand_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 34fb80f..35de6e8 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -14,6 +14,7 @@
 #include <linux/devfreq.h>
 #include <linux/pm.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include "governor.h"
 
 struct userspace_data {
@@ -158,3 +159,4 @@ static void __exit devfreq_userspace_exit(void)
 	return;
 }
 module_exit(devfreq_userspace_exit);
+MODULE_LICENSE("GPL");
-- 
1.7.9.5


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

* [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
                   ` (4 preceding siblings ...)
  2012-10-29 20:01 ` [linux-next PATCH 5/7] PM / devfreq: governors: add GPL module license and allow module build Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  2012-10-29 20:01 ` [linux-next PATCH 7/7] PM / devfreq: Add sysfs node to expose available governors Nishanth Menon
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

This allows us to select governor runtime from the
default configuration without having to rebuild kernel
or the devfreq driver using the sysfs node:
/sys/class/devfreq/.../governor
cat of the governor will return valid governor
and an echo 'governor_name'>governor will switch
governor

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 Documentation/ABI/testing/sysfs-class-devfreq |    2 +-
 drivers/devfreq/devfreq.c                     |   40 ++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
index e672ccb..293f6b2 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -11,7 +11,7 @@ What:		/sys/class/devfreq/.../governor
 Date:		September 2011
 Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
-		The /sys/class/devfreq/.../governor shows the name of the
+		The /sys/class/devfreq/.../governor show or set the name of the
 		governor used by the corresponding devfreq object.
 
 What:		/sys/class/devfreq/.../cur_freq
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index bd96e32..8535f8c 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -629,6 +629,44 @@ static ssize_t show_governor(struct device *dev,
 	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
 }
 
+static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct devfreq *df = to_devfreq(dev);
+	int ret = 0;
+	struct devfreq_governor *governor;
+
+	mutex_lock(&devfreq_list_lock);
+	governor = find_devfreq_governor(buf);
+	if (IS_ERR(governor)) {
+		ret = PTR_ERR(governor);
+		goto out;
+	}
+	if (df->governor == governor)
+		goto out;
+
+	if (df->governor) {
+		ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+		if (ret) {
+			dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+				 __func__, df->governor->name, ret);
+			goto out;
+		}
+	}
+	df->governor = governor;
+	strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
+	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+	if (ret)
+		dev_warn(dev, "%s: Governor %s not started(%d)\n",
+			 __func__, df->governor->name, ret);
+out:
+	mutex_unlock(&devfreq_list_lock);
+
+	if (!ret)
+		ret = count;
+	return ret;
+}
+
 static ssize_t show_freq(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
@@ -773,7 +811,7 @@ static ssize_t show_available_freqs(struct device *d,
 }
 
 static struct device_attribute devfreq_attrs[] = {
-	__ATTR(governor, S_IRUGO, show_governor, NULL),
+	__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
 	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
 	__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
 	__ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
-- 
1.7.9.5


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

* [linux-next PATCH 7/7] PM / devfreq: Add sysfs node to expose available governors
  2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
                   ` (5 preceding siblings ...)
  2012-10-29 20:01 ` [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor Nishanth Menon
@ 2012-10-29 20:01 ` Nishanth Menon
  6 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-10-29 20:01 UTC (permalink / raw)
  To: linux-pm
  Cc: Nishanth Menon, Rajagopal Venkat, MyungJoo Ham, Kyungmin Park,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

Now that governor list can be variable, knowing the available governors
is useful to be able to select a governor using relevant sysfs node.

Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 Documentation/ABI/testing/sysfs-class-devfreq |    7 +++++++
 drivers/devfreq/devfreq.c                     |   22 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
index 293f6b2..0daa83f 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -60,3 +60,10 @@ Description:
 		the available frequencies of the corresponding devfreq object.
 		This is a snapshot of available frequencies and not limited
 		by the min/max frequency restrictions.
+
+What:		/sys/class/devfreq/.../available_governors
+Date:		October 2012
+Contact:	Nishanth Menon <nm@ti.com>
+Description:
+		The /sys/class/devfreq/.../available_governors shows
+		currently available governors in the system.
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 8535f8c..9ed3ca5 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -666,6 +666,27 @@ out:
 		ret = count;
 	return ret;
 }
+static ssize_t show_available_governors(struct device *d,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct devfreq_governor *tmp_governor;
+	ssize_t count = 0;
+
+	mutex_lock(&devfreq_list_lock);
+	list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
+		count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+				   "%s ", tmp_governor->name);
+	mutex_unlock(&devfreq_list_lock);
+
+	/* Truncate the trailing space */
+	if (count)
+		count--;
+
+	count += sprintf(&buf[count], "\n");
+
+	return count;
+}
 
 static ssize_t show_freq(struct device *dev,
 			 struct device_attribute *attr, char *buf)
@@ -812,6 +833,7 @@ static ssize_t show_available_freqs(struct device *d,
 
 static struct device_attribute devfreq_attrs[] = {
 	__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
+	__ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
 	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
 	__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
 	__ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
-- 
1.7.9.5


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

* Re: [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor
       [not found] ` <CAJ0PZbSe7Orhww-amHNRkbvUvJr6x9CtisHw2hoLpcJdyBSKCA@mail.gmail.com>
@ 2012-11-06 21:28   ` Nishanth Menon
  0 siblings, 0 replies; 10+ messages in thread
From: Nishanth Menon @ 2012-11-06 21:28 UTC (permalink / raw)
  To: MyungJoo Ham
  Cc: myungjoo.ham, LKML, Kevin Hilman, linux-pm, Rajagopal Venkat,
	박경민,
	Rafael J. Wysocki

On 18:18-20121106, MyungJoo Ham wrote:
> 2012. 11. 6. 오후 6:02에 "MyungJoo Ham" <myungjoo.ham@samsung.com>님이 작성:
> >
> > > --- a/drivers/devfreq/devfreq.c
> > > +++ b/drivers/devfreq/devfreq.c
> > > @@ -629,6 +629,44 @@ static ssize_t show_governor(struct device *dev,
> > >       return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
> > >  }
> > >
> > > +static ssize_t store_governor(struct device *dev, struct
> device_attribute *attr,
> > > +                           const char *buf, size_t count)
> > > +{
> > > +     struct devfreq *df = to_devfreq(dev);
> > > +     int ret = 0;
> > > +     struct devfreq_governor *governor;
> > > +
> > > +     mutex_lock(&devfreq_list_lock);
> >
> > Please remove the trailing \n from buf here.
> > When user enters "userspace", buf gets "userspace\n".
> >
> > With some printks in find_devfreq_governor (printing the buf and governor
> names):
> >
> > # echo userspace > /sys/class/devfreq/exynos4210-busfreq.0/governor
> > [   65.975000] [userspace
> > [   65.975000] ].[userspace]
> > [   65.980000] [userspace
> > [   65.980000] ].[powersave]
> > [   65.985000] [userspace
> > [   65.985000] ].[performance]
> > [   65.990000] [userspace
> > [   65.990000] ].[simple_ondemand]
> > [   65.995000] err no = -19
> > #
> >
> 
> Anyway this seems quite wierd. I will look more into this one in my target
> system.
Thanks for catching this.
:( I missed the \n (been using echo -n toooo often now grr..)
What do you think of the following change to the patch?

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 586b6fd..9a4e898 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -614,11 +614,16 @@ static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
-	int ret = 0;
+	int ret;
+	char str_governor[DEVFREQ_NAME_LEN + 1];
 	struct devfreq_governor *governor;
 
+	ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
+	if (ret != 1)
+	        return -EINVAL;
+
 	mutex_lock(&devfreq_list_lock);
-	governor = find_devfreq_governor(buf);
+	governor = find_devfreq_governor(str_governor);
 	if (IS_ERR(governor)) {
 		ret = PTR_ERR(governor);
 		goto out;
-- 
Regards,
Nishanth Menon

output:
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor 
simple_ondemand
/sys/devices/platform/iva.0/devfreq/iva.0 # echo -n "userspace">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # echo -n "simple_ondeman">governor 
sh: write error: No such device
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor 
userspace
/sys/devices/platform/iva.0/devfreq/iva.0 # echo -n "simple_ondemand">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor 
simple_ondemand
/sys/devices/platform/iva.0/devfreq/iva.0 # echo "userspace">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor 
userspace
/sys/devices/platform/iva.0/devfreq/iva.0 # echo  "simple_ondemand">governor 
/sys/devices/platform/iva.0/devfreq/iva.0 # echo "userspace123123213123213123212
3123123131231">governor 
sh: write error: No such device
/sys/devices/platform/iva.0/devfreq/iva.0 # cat governor 
simple_ondemand


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

* Re: [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor
@ 2012-11-06  9:02 MyungJoo Ham
       [not found] ` <CAJ0PZbSe7Orhww-amHNRkbvUvJr6x9CtisHw2hoLpcJdyBSKCA@mail.gmail.com>
  0 siblings, 1 reply; 10+ messages in thread
From: MyungJoo Ham @ 2012-11-06  9:02 UTC (permalink / raw)
  To: Nishanth Menon, linux-pm
  Cc: Rajagopal Venkat, 박경민,
	Rafael J. Wysocki, Kevin Hilman, linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=euc-kr, Size: 1977 bytes --]

> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -629,6 +629,44 @@ static ssize_t show_governor(struct device *dev,
>  	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
>  }
>  
> +static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
> +			      const char *buf, size_t count)
> +{
> +	struct devfreq *df = to_devfreq(dev);
> +	int ret = 0;
> +	struct devfreq_governor *governor;
> +
> +	mutex_lock(&devfreq_list_lock);

Please remove the trailing \n from buf here.
When user enters "userspace", buf gets "userspace\n".

With some printks in find_devfreq_governor (printing the buf and governor names):

# echo userspace > /sys/class/devfreq/exynos4210-busfreq.0/governor
[   65.975000] [userspace
[   65.975000] ].[userspace]
[   65.980000] [userspace
[   65.980000] ].[powersave]
[   65.985000] [userspace
[   65.985000] ].[performance]
[   65.990000] [userspace
[   65.990000] ].[simple_ondemand]
[   65.995000] err no = -19
# 





Cheers,
MyungJoo

> +	governor = find_devfreq_governor(buf);
> +	if (IS_ERR(governor)) {
> +		ret = PTR_ERR(governor);
> +		goto out;
> +	}
> +	if (df->governor == governor)
> +		goto out;
> +
> +	if (df->governor) {
> +		ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
> +		if (ret) {
> +			dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
> +				 __func__, df->governor->name, ret);
> +			goto out;
> +		}
> +	}
> +	df->governor = governor;
> +	strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
> +	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
> +	if (ret)
> +		dev_warn(dev, "%s: Governor %s not started(%d)\n",
> +			 __func__, df->governor->name, ret);
> +out:
> +	mutex_unlock(&devfreq_list_lock);
> +
> +	if (!ret)
> +		ret = count;
> +	return ret;
> +}
> +
[]
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

end of thread, other threads:[~2012-11-06 21:28 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-29 20:01 [linux-next PATCH 0/7] PM / devfreq: allow governors to be modules and switch dynamically Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 1/7] PM / devfreq: export update_devfreq Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 2/7] PM / devfreq: provide hooks for governors to be registered Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 3/7] PM / devfreq: register governors with devfreq framework Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 4/7] PM / devfreq: map devfreq drivers to governor using name Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 5/7] PM / devfreq: governors: add GPL module license and allow module build Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor Nishanth Menon
2012-10-29 20:01 ` [linux-next PATCH 7/7] PM / devfreq: Add sysfs node to expose available governors Nishanth Menon
2012-11-06  9:02 [linux-next PATCH 6/7] PM / devfreq: allow sysfs governor node to switch governor MyungJoo Ham
     [not found] ` <CAJ0PZbSe7Orhww-amHNRkbvUvJr6x9CtisHw2hoLpcJdyBSKCA@mail.gmail.com>
2012-11-06 21:28   ` Nishanth Menon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).