aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2007-10-02 16:28:12 -0400
committerDave Jones <davej@redhat.com>2007-10-04 18:40:57 -0400
commit1c2562459faedc35927546cfa5273ec6c2884cce (patch)
treea6133aa5c0ac2b4a8cb12fa37c28e755a458aef0
parent8122c6cea033e8034e99d3b10a4e3f377ce23994 (diff)
[CPUFREQ] allow ondemand and conservative cpufreq governors to be used as default
Depending on the transition latency of the HW for cpufreq switches, the ondemand or conservative governor cannot be used with certain cpufreq drivers. Still the ondemand should be the default governor on a wide range of systems. This patch allows this and lets the governor fallback to the performance governor at cpufreq driver load time, if the driver does not support fast enough frequency switching. Main benefit is that on e.g. installation or other systems without userspace support a working dynamic cpufreq support can be achieved on most systems by simply loading the cpufreq driver. This is especially essential for recent x86(_64) laptop hardware which may rely on working dynamic cpufreq OS support. Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Bryan Wu <bryan.wu@analog.com> Cc: Andi Kleen <ak@suse.de> Cc: "Luck, Tony" <tony.luck@intel.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mundt <lethal@linux-sh.org> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--drivers/cpufreq/Kconfig27
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c19
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c22
-rw-r--r--include/linux/cpufreq.h20
5 files changed, 70 insertions, 30 deletions
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 993fa7b89253..721f86f4f008 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -56,10 +56,6 @@ config CPU_FREQ_STAT_DETAILS
56 56
57 If in doubt, say N. 57 If in doubt, say N.
58 58
59# Note that it is not currently possible to set the other governors (such as ondemand)
60# as the default, since if they fail to initialise, cpufreq will be
61# left in an undefined state.
62
63choice 59choice
64 prompt "Default CPUFreq governor" 60 prompt "Default CPUFreq governor"
65 default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110 61 default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
@@ -85,6 +81,29 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
85 program shall be able to set the CPU dynamically without having 81 program shall be able to set the CPU dynamically without having
86 to enable the userspace governor manually. 82 to enable the userspace governor manually.
87 83
84config CPU_FREQ_DEFAULT_GOV_ONDEMAND
85 bool "ondemand"
86 select CPU_FREQ_GOV_ONDEMAND
87 select CPU_FREQ_GOV_PERFORMANCE
88 help
89 Use the CPUFreq governor 'ondemand' as default. This allows
90 you to get a full dynamic frequency capable system by simply
91 loading your cpufreq low-level hardware driver.
92 Be aware that not all cpufreq drivers support the ondemand
93 governor. If unsure have a look at the help section of the
94 driver. Fallback governor will be the performance governor.
95
96config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
97 bool "conservative"
98 select CPU_FREQ_GOV_CONSERVATIVE
99 select CPU_FREQ_GOV_PERFORMANCE
100 help
101 Use the CPUFreq governor 'conservative' as default. This allows
102 you to get a full dynamic frequency capable system by simply
103 loading your cpufreq low-level hardware driver.
104 Be aware that not all cpufreq drivers support the conservative
105 governor. If unsure have a look at the help section of the
106 driver. Fallback governor will be the performance governor.
88endchoice 107endchoice
89 108
90config CPU_FREQ_GOV_PERFORMANCE 109config CPU_FREQ_GOV_PERFORMANCE
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9528bd577365..418522f88f73 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1484,6 +1484,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
1484 unsigned int event) 1484 unsigned int event)
1485{ 1485{
1486 int ret; 1486 int ret;
1487 struct cpufreq_governor *gov = CPUFREQ_PERFORMANCE_GOVERNOR;
1488
1489 if (policy->governor->max_transition_latency &&
1490 policy->cpuinfo.transition_latency >
1491 policy->governor->max_transition_latency) {
1492 printk(KERN_WARNING "%s governor failed, too long"
1493 " transition latency of HW, fallback"
1494 " to %s governor\n",
1495 policy->governor->name,
1496 gov->name);
1497 policy->governor = gov;
1498 }
1487 1499
1488 if (!try_module_get(policy->governor->owner)) 1500 if (!try_module_get(policy->governor->owner))
1489 return -EINVAL; 1501 return -EINVAL;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 26f440ccc3fb..4bd33ce8a6f3 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -58,7 +58,7 @@ static unsigned int def_sampling_rate;
58#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) 58#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
59#define DEF_SAMPLING_DOWN_FACTOR (1) 59#define DEF_SAMPLING_DOWN_FACTOR (1)
60#define MAX_SAMPLING_DOWN_FACTOR (10) 60#define MAX_SAMPLING_DOWN_FACTOR (10)
61#define TRANSITION_LATENCY_LIMIT (10 * 1000) 61#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
62 62
63static void do_dbs_timer(struct work_struct *work); 63static void do_dbs_timer(struct work_struct *work);
64 64
@@ -466,9 +466,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
466 (!policy->cur)) 466 (!policy->cur))
467 return -EINVAL; 467 return -EINVAL;
468 468
469 if (policy->cpuinfo.transition_latency >
470 (TRANSITION_LATENCY_LIMIT * 1000))
471 return -EINVAL;
472 if (this_dbs_info->enable) /* Already enabled */ 469 if (this_dbs_info->enable) /* Already enabled */
473 break; 470 break;
474 471
@@ -551,15 +548,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
551 return 0; 548 return 0;
552} 549}
553 550
554static struct cpufreq_governor cpufreq_gov_dbs = { 551struct cpufreq_governor cpufreq_gov_conservative = {
555 .name = "conservative", 552 .name = "conservative",
556 .governor = cpufreq_governor_dbs, 553 .governor = cpufreq_governor_dbs,
557 .owner = THIS_MODULE, 554 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
555 .owner = THIS_MODULE,
558}; 556};
557EXPORT_SYMBOL(cpufreq_gov_conservative);
559 558
560static int __init cpufreq_gov_dbs_init(void) 559static int __init cpufreq_gov_dbs_init(void)
561{ 560{
562 return cpufreq_register_governor(&cpufreq_gov_dbs); 561 return cpufreq_register_governor(&cpufreq_gov_conservative);
563} 562}
564 563
565static void __exit cpufreq_gov_dbs_exit(void) 564static void __exit cpufreq_gov_dbs_exit(void)
@@ -567,7 +566,7 @@ static void __exit cpufreq_gov_dbs_exit(void)
567 /* Make sure that the scheduled work is indeed not running */ 566 /* Make sure that the scheduled work is indeed not running */
568 flush_scheduled_work(); 567 flush_scheduled_work();
569 568
570 cpufreq_unregister_governor(&cpufreq_gov_dbs); 569 cpufreq_unregister_governor(&cpufreq_gov_conservative);
571} 570}
572 571
573 572
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e794527e4925..369f44595150 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -47,7 +47,7 @@ static unsigned int def_sampling_rate;
47 (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) 47 (def_sampling_rate / MIN_SAMPLING_RATE_RATIO)
48#define MAX_SAMPLING_RATE (500 * def_sampling_rate) 48#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
49#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) 49#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
50#define TRANSITION_LATENCY_LIMIT (10 * 1000) 50#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
51 51
52static void do_dbs_timer(struct work_struct *work); 52static void do_dbs_timer(struct work_struct *work);
53 53
@@ -508,12 +508,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
508 if ((!cpu_online(cpu)) || (!policy->cur)) 508 if ((!cpu_online(cpu)) || (!policy->cur))
509 return -EINVAL; 509 return -EINVAL;
510 510
511 if (policy->cpuinfo.transition_latency >
512 (TRANSITION_LATENCY_LIMIT * 1000)) {
513 printk(KERN_WARNING "ondemand governor failed to load "
514 "due to too long transition latency\n");
515 return -EINVAL;
516 }
517 if (this_dbs_info->enable) /* Already enabled */ 511 if (this_dbs_info->enable) /* Already enabled */
518 break; 512 break;
519 513
@@ -585,11 +579,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
585 return 0; 579 return 0;
586} 580}
587 581
588static struct cpufreq_governor cpufreq_gov_dbs = { 582struct cpufreq_governor cpufreq_gov_ondemand = {
589 .name = "ondemand", 583 .name = "ondemand",
590 .governor = cpufreq_governor_dbs, 584 .governor = cpufreq_governor_dbs,
591 .owner = THIS_MODULE, 585 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
586 .owner = THIS_MODULE,
592}; 587};
588EXPORT_SYMBOL(cpufreq_gov_ondemand);
593 589
594static int __init cpufreq_gov_dbs_init(void) 590static int __init cpufreq_gov_dbs_init(void)
595{ 591{
@@ -598,12 +594,12 @@ static int __init cpufreq_gov_dbs_init(void)
598 printk(KERN_ERR "Creation of kondemand failed\n"); 594 printk(KERN_ERR "Creation of kondemand failed\n");
599 return -EFAULT; 595 return -EFAULT;
600 } 596 }
601 return cpufreq_register_governor(&cpufreq_gov_dbs); 597 return cpufreq_register_governor(&cpufreq_gov_ondemand);
602} 598}
603 599
604static void __exit cpufreq_gov_dbs_exit(void) 600static void __exit cpufreq_gov_dbs_exit(void)
605{ 601{
606 cpufreq_unregister_governor(&cpufreq_gov_dbs); 602 cpufreq_unregister_governor(&cpufreq_gov_ondemand);
607 destroy_workqueue(kondemand_wq); 603 destroy_workqueue(kondemand_wq);
608} 604}
609 605
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3ec6e7ff5fbd..9e5f5d0c87f3 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -155,6 +155,9 @@ struct cpufreq_governor {
155 char name[CPUFREQ_NAME_LEN]; 155 char name[CPUFREQ_NAME_LEN];
156 int (*governor) (struct cpufreq_policy *policy, 156 int (*governor) (struct cpufreq_policy *policy,
157 unsigned int event); 157 unsigned int event);
158 unsigned int max_transition_latency; /* HW must be able to switch to
159 next freq faster than this value in nano secs or we
160 will fallback to performance governor */
158 struct list_head governor_list; 161 struct list_head governor_list;
159 struct module *owner; 162 struct module *owner;
160}; 163};
@@ -279,12 +282,23 @@ static inline unsigned int cpufreq_quick_get(unsigned int cpu)
279 *********************************************************************/ 282 *********************************************************************/
280 283
281 284
282#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE 285/*
286 Performance governor is fallback governor if any other gov failed to
287 auto load due latency restrictions
288*/
283extern struct cpufreq_governor cpufreq_gov_performance; 289extern struct cpufreq_governor cpufreq_gov_performance;
284#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance 290#define CPUFREQ_PERFORMANCE_GOVERNOR (&cpufreq_gov_performance)
291#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
292#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance)
285#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) 293#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
286extern struct cpufreq_governor cpufreq_gov_userspace; 294extern struct cpufreq_governor cpufreq_gov_userspace;
287#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace 295#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace)
296#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND)
297extern struct cpufreq_governor cpufreq_gov_ondemand;
298#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand)
299#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
300extern struct cpufreq_governor cpufreq_gov_conservative;
301#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
288#endif 302#endif
289 303
290 304