aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2012-10-29 16:01:45 -0400
committerMyungJoo Ham <myungjoo.ham@samsung.com>2012-11-20 04:46:22 -0500
commit1b5c1be2c88e8445a20fa1929e26c37e7ca8c926 (patch)
tree5f5f32ef0452957689e16ace31287885b400bd77
parent83116e66a232184f733ecf09a41817cf893ede98 (diff)
PM / devfreq: map devfreq drivers to governor using name
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> [Merge conflict resolved by MyungJoo Ham] Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
-rw-r--r--drivers/devfreq/devfreq.c95
-rw-r--r--drivers/devfreq/exynos4_bus.c2
-rw-r--r--drivers/devfreq/governor_performance.c2
-rw-r--r--drivers/devfreq/governor_powersave.c2
-rw-r--r--drivers/devfreq/governor_simpleondemand.c2
-rw-r--r--drivers/devfreq/governor_userspace.c2
-rw-r--r--include/linux/devfreq.h21
7 files changed, 96 insertions, 30 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 679ac424472f..0d7be03d561f 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -159,6 +159,9 @@ int update_devfreq(struct devfreq *devfreq)
159 return -EINVAL; 159 return -EINVAL;
160 } 160 }
161 161
162 if (!devfreq->governor)
163 return -EINVAL;
164
162 /* Reevaluate the proper frequency */ 165 /* Reevaluate the proper frequency */
163 err = devfreq->governor->get_target_freq(devfreq, &freq); 166 err = devfreq->governor->get_target_freq(devfreq, &freq);
164 if (err) 167 if (err)
@@ -379,7 +382,9 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
379 list_del(&devfreq->node); 382 list_del(&devfreq->node);
380 mutex_unlock(&devfreq_list_lock); 383 mutex_unlock(&devfreq_list_lock);
381 384
382 devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_STOP, NULL); 385 if (devfreq->governor)
386 devfreq->governor->event_handler(devfreq,
387 DEVFREQ_GOV_STOP, NULL);
383 388
384 if (devfreq->profile->exit) 389 if (devfreq->profile->exit)
385 devfreq->profile->exit(devfreq->dev.parent); 390 devfreq->profile->exit(devfreq->dev.parent);
@@ -412,19 +417,20 @@ static void devfreq_dev_release(struct device *dev)
412 * devfreq_add_device() - Add devfreq feature to the device 417 * devfreq_add_device() - Add devfreq feature to the device
413 * @dev: the device to add devfreq feature. 418 * @dev: the device to add devfreq feature.
414 * @profile: device-specific profile to run devfreq. 419 * @profile: device-specific profile to run devfreq.
415 * @governor: the policy to choose frequency. 420 * @governor_name: name of the policy to choose frequency.
416 * @data: private data for the governor. The devfreq framework does not 421 * @data: private data for the governor. The devfreq framework does not
417 * touch this value. 422 * touch this value.
418 */ 423 */
419struct devfreq *devfreq_add_device(struct device *dev, 424struct devfreq *devfreq_add_device(struct device *dev,
420 struct devfreq_dev_profile *profile, 425 struct devfreq_dev_profile *profile,
421 const struct devfreq_governor *governor, 426 const char *governor_name,
422 void *data) 427 void *data)
423{ 428{
424 struct devfreq *devfreq; 429 struct devfreq *devfreq;
430 struct devfreq_governor *governor;
425 int err = 0; 431 int err = 0;
426 432
427 if (!dev || !profile || !governor) { 433 if (!dev || !profile || !governor_name) {
428 dev_err(dev, "%s: Invalid parameters.\n", __func__); 434 dev_err(dev, "%s: Invalid parameters.\n", __func__);
429 return ERR_PTR(-EINVAL); 435 return ERR_PTR(-EINVAL);
430 } 436 }
@@ -452,7 +458,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
452 devfreq->dev.class = devfreq_class; 458 devfreq->dev.class = devfreq_class;
453 devfreq->dev.release = devfreq_dev_release; 459 devfreq->dev.release = devfreq_dev_release;
454 devfreq->profile = profile; 460 devfreq->profile = profile;
455 devfreq->governor = governor; 461 strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
456 devfreq->previous_freq = profile->initial_freq; 462 devfreq->previous_freq = profile->initial_freq;
457 devfreq->data = data; 463 devfreq->data = data;
458 devfreq->nb.notifier_call = devfreq_notifier_call; 464 devfreq->nb.notifier_call = devfreq_notifier_call;
@@ -478,10 +484,14 @@ struct devfreq *devfreq_add_device(struct device *dev,
478 484
479 mutex_lock(&devfreq_list_lock); 485 mutex_lock(&devfreq_list_lock);
480 list_add(&devfreq->node, &devfreq_list); 486 list_add(&devfreq->node, &devfreq_list);
481 mutex_unlock(&devfreq_list_lock);
482 487
483 err = devfreq->governor->event_handler(devfreq, 488 governor = find_devfreq_governor(devfreq->governor_name);
484 DEVFREQ_GOV_START, NULL); 489 if (!IS_ERR(governor))
490 devfreq->governor = governor;
491 if (devfreq->governor)
492 err = devfreq->governor->event_handler(devfreq,
493 DEVFREQ_GOV_START, NULL);
494 mutex_unlock(&devfreq_list_lock);
485 if (err) { 495 if (err) {
486 dev_err(dev, "%s: Unable to start governor for the device\n", 496 dev_err(dev, "%s: Unable to start governor for the device\n",
487 __func__); 497 __func__);
@@ -524,6 +534,9 @@ int devfreq_suspend_device(struct devfreq *devfreq)
524 if (!devfreq) 534 if (!devfreq)
525 return -EINVAL; 535 return -EINVAL;
526 536
537 if (!devfreq->governor)
538 return 0;
539
527 return devfreq->governor->event_handler(devfreq, 540 return devfreq->governor->event_handler(devfreq,
528 DEVFREQ_GOV_SUSPEND, NULL); 541 DEVFREQ_GOV_SUSPEND, NULL);
529} 542}
@@ -538,6 +551,9 @@ int devfreq_resume_device(struct devfreq *devfreq)
538 if (!devfreq) 551 if (!devfreq)
539 return -EINVAL; 552 return -EINVAL;
540 553
554 if (!devfreq->governor)
555 return 0;
556
541 return devfreq->governor->event_handler(devfreq, 557 return devfreq->governor->event_handler(devfreq,
542 DEVFREQ_GOV_RESUME, NULL); 558 DEVFREQ_GOV_RESUME, NULL);
543} 559}
@@ -550,6 +566,7 @@ EXPORT_SYMBOL(devfreq_resume_device);
550int devfreq_add_governor(struct devfreq_governor *governor) 566int devfreq_add_governor(struct devfreq_governor *governor)
551{ 567{
552 struct devfreq_governor *g; 568 struct devfreq_governor *g;
569 struct devfreq *devfreq;
553 int err = 0; 570 int err = 0;
554 571
555 if (!governor) { 572 if (!governor) {
@@ -568,6 +585,38 @@ int devfreq_add_governor(struct devfreq_governor *governor)
568 585
569 list_add(&governor->node, &devfreq_governor_list); 586 list_add(&governor->node, &devfreq_governor_list);
570 587
588 list_for_each_entry(devfreq, &devfreq_list, node) {
589 int ret = 0;
590 struct device *dev = devfreq->dev.parent;
591
592 if (!strncmp(devfreq->governor_name, governor->name,
593 DEVFREQ_NAME_LEN)) {
594 /* The following should never occur */
595 if (devfreq->governor) {
596 dev_warn(dev,
597 "%s: Governor %s already present\n",
598 __func__, devfreq->governor->name);
599 ret = devfreq->governor->event_handler(devfreq,
600 DEVFREQ_GOV_STOP, NULL);
601 if (ret) {
602 dev_warn(dev,
603 "%s: Governor %s stop = %d\n",
604 __func__,
605 devfreq->governor->name, ret);
606 }
607 /* Fall through */
608 }
609 devfreq->governor = governor;
610 ret = devfreq->governor->event_handler(devfreq,
611 DEVFREQ_GOV_START, NULL);
612 if (ret) {
613 dev_warn(dev, "%s: Governor %s start=%d\n",
614 __func__, devfreq->governor->name,
615 ret);
616 }
617 }
618 }
619
571err_out: 620err_out:
572 mutex_unlock(&devfreq_list_lock); 621 mutex_unlock(&devfreq_list_lock);
573 622
@@ -582,6 +631,7 @@ EXPORT_SYMBOL(devfreq_add_governor);
582int devfreq_remove_governor(struct devfreq_governor *governor) 631int devfreq_remove_governor(struct devfreq_governor *governor)
583{ 632{
584 struct devfreq_governor *g; 633 struct devfreq_governor *g;
634 struct devfreq *devfreq;
585 int err = 0; 635 int err = 0;
586 636
587 if (!governor) { 637 if (!governor) {
@@ -597,6 +647,29 @@ int devfreq_remove_governor(struct devfreq_governor *governor)
597 err = -EINVAL; 647 err = -EINVAL;
598 goto err_out; 648 goto err_out;
599 } 649 }
650 list_for_each_entry(devfreq, &devfreq_list, node) {
651 int ret;
652 struct device *dev = devfreq->dev.parent;
653
654 if (!strncmp(devfreq->governor_name, governor->name,
655 DEVFREQ_NAME_LEN)) {
656 /* we should have a devfreq governor! */
657 if (!devfreq->governor) {
658 dev_warn(dev, "%s: Governor %s NOT present\n",
659 __func__, governor->name);
660 continue;
661 /* Fall through */
662 }
663 ret = devfreq->governor->event_handler(devfreq,
664 DEVFREQ_GOV_STOP, NULL);
665 if (ret) {
666 dev_warn(dev, "%s: Governor %s stop=%d\n",
667 __func__, devfreq->governor->name,
668 ret);
669 }
670 devfreq->governor = NULL;
671 }
672 }
600 673
601 list_del(&governor->node); 674 list_del(&governor->node);
602err_out: 675err_out:
@@ -609,6 +682,9 @@ EXPORT_SYMBOL(devfreq_remove_governor);
609static ssize_t show_governor(struct device *dev, 682static ssize_t show_governor(struct device *dev,
610 struct device_attribute *attr, char *buf) 683 struct device_attribute *attr, char *buf)
611{ 684{
685 if (!to_devfreq(dev)->governor)
686 return -EINVAL;
687
612 return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name); 688 return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
613} 689}
614 690
@@ -645,6 +721,9 @@ static ssize_t store_polling_interval(struct device *dev,
645 unsigned int value; 721 unsigned int value;
646 int ret; 722 int ret;
647 723
724 if (!df->governor)
725 return -EINVAL;
726
648 ret = sscanf(buf, "%u", &value); 727 ret = sscanf(buf, "%u", &value);
649 if (ret != 1) 728 if (ret != 1)
650 return -EINVAL; 729 return -EINVAL;
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 68145316c49c..b8ac28497b37 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -1040,7 +1040,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
1040 busfreq_mon_reset(data); 1040 busfreq_mon_reset(data);
1041 1041
1042 data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile, 1042 data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
1043 &devfreq_simple_ondemand, NULL); 1043 "simple_ondemand", NULL);
1044 if (IS_ERR(data->devfreq)) 1044 if (IS_ERR(data->devfreq))
1045 return PTR_ERR(data->devfreq); 1045 return PTR_ERR(data->devfreq);
1046 1046
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index db8ff77dbed2..865a36956917 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,
40 return ret; 40 return ret;
41} 41}
42 42
43const struct devfreq_governor devfreq_performance = { 43static struct devfreq_governor devfreq_performance = {
44 .name = "performance", 44 .name = "performance",
45 .get_target_freq = devfreq_performance_func, 45 .get_target_freq = devfreq_performance_func,
46 .event_handler = devfreq_performance_handler, 46 .event_handler = devfreq_performance_handler,
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index 30f0fca8d635..8612c0f96b79 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,
37 return ret; 37 return ret;
38} 38}
39 39
40const struct devfreq_governor devfreq_powersave = { 40static struct devfreq_governor devfreq_powersave = {
41 .name = "powersave", 41 .name = "powersave",
42 .get_target_freq = devfreq_powersave_func, 42 .get_target_freq = devfreq_powersave_func,
43 .event_handler = devfreq_powersave_handler, 43 .event_handler = devfreq_powersave_handler,
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index 85f9ed531b1e..a870a24bb56b 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,
120 return 0; 120 return 0;
121} 121}
122 122
123const struct devfreq_governor devfreq_simple_ondemand = { 123static struct devfreq_governor devfreq_simple_ondemand = {
124 .name = "simple_ondemand", 124 .name = "simple_ondemand",
125 .get_target_freq = devfreq_simple_ondemand_func, 125 .get_target_freq = devfreq_simple_ondemand_func,
126 .event_handler = devfreq_simple_ondemand_handler, 126 .event_handler = devfreq_simple_ondemand_handler,
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 110f178fec04..34fb80f50cf6 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,
135 return ret; 135 return ret;
136} 136}
137 137
138const struct devfreq_governor devfreq_userspace = { 138static struct devfreq_governor devfreq_userspace = {
139 .name = "userspace", 139 .name = "userspace",
140 .get_target_freq = devfreq_userspace_func, 140 .get_target_freq = devfreq_userspace_func,
141 .event_handler = devfreq_userspace_handler, 141 .event_handler = devfreq_userspace_handler,
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 6484a3f8dda8..235248cb2c93 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -125,6 +125,7 @@ struct devfreq_governor {
125 * using devfreq. 125 * using devfreq.
126 * @profile: device-specific devfreq profile 126 * @profile: device-specific devfreq profile
127 * @governor: method how to choose frequency based on the usage. 127 * @governor: method how to choose frequency based on the usage.
128 * @governor_name: devfreq governor name for use with this devfreq
128 * @nb: notifier block used to notify devfreq object that it should 129 * @nb: notifier block used to notify devfreq object that it should
129 * reevaluate operable frequencies. Devfreq users may use 130 * reevaluate operable frequencies. Devfreq users may use
130 * devfreq.nb to the corresponding register notifier call chain. 131 * devfreq.nb to the corresponding register notifier call chain.
@@ -155,6 +156,7 @@ struct devfreq {
155 struct device dev; 156 struct device dev;
156 struct devfreq_dev_profile *profile; 157 struct devfreq_dev_profile *profile;
157 const struct devfreq_governor *governor; 158 const struct devfreq_governor *governor;
159 char governor_name[DEVFREQ_NAME_LEN];
158 struct notifier_block nb; 160 struct notifier_block nb;
159 struct delayed_work work; 161 struct delayed_work work;
160 162
@@ -176,7 +178,7 @@ struct devfreq {
176#if defined(CONFIG_PM_DEVFREQ) 178#if defined(CONFIG_PM_DEVFREQ)
177extern struct devfreq *devfreq_add_device(struct device *dev, 179extern struct devfreq *devfreq_add_device(struct device *dev,
178 struct devfreq_dev_profile *profile, 180 struct devfreq_dev_profile *profile,
179 const struct devfreq_governor *governor, 181 const char *governor_name,
180 void *data); 182 void *data);
181extern int devfreq_remove_device(struct devfreq *devfreq); 183extern int devfreq_remove_device(struct devfreq *devfreq);
182extern int devfreq_suspend_device(struct devfreq *devfreq); 184extern int devfreq_suspend_device(struct devfreq *devfreq);
@@ -190,17 +192,7 @@ extern int devfreq_register_opp_notifier(struct device *dev,
190extern int devfreq_unregister_opp_notifier(struct device *dev, 192extern int devfreq_unregister_opp_notifier(struct device *dev,
191 struct devfreq *devfreq); 193 struct devfreq *devfreq);
192 194
193#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
194extern const struct devfreq_governor devfreq_powersave;
195#endif
196#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
197extern const struct devfreq_governor devfreq_performance;
198#endif
199#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
200extern const struct devfreq_governor devfreq_userspace;
201#endif
202#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND 195#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
203extern const struct devfreq_governor devfreq_simple_ondemand;
204/** 196/**
205 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 197 * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
206 * and devfreq_add_device 198 * and devfreq_add_device
@@ -223,7 +215,7 @@ struct devfreq_simple_ondemand_data {
223#else /* !CONFIG_PM_DEVFREQ */ 215#else /* !CONFIG_PM_DEVFREQ */
224static struct devfreq *devfreq_add_device(struct device *dev, 216static struct devfreq *devfreq_add_device(struct device *dev,
225 struct devfreq_dev_profile *profile, 217 struct devfreq_dev_profile *profile,
226 struct devfreq_governor *governor, 218 const char *governor_name,
227 void *data) 219 void *data)
228{ 220{
229 return NULL; 221 return NULL;
@@ -262,11 +254,6 @@ static int devfreq_unregister_opp_notifier(struct device *dev,
262 return -EINVAL; 254 return -EINVAL;
263} 255}
264 256
265#define devfreq_powersave NULL
266#define devfreq_performance NULL
267#define devfreq_userspace NULL
268#define devfreq_simple_ondemand NULL
269
270#endif /* CONFIG_PM_DEVFREQ */ 257#endif /* CONFIG_PM_DEVFREQ */
271 258
272#endif /* __LINUX_DEVFREQ_H__ */ 259#endif /* __LINUX_DEVFREQ_H__ */