diff options
author | Jacob Shin <jacob.shin@amd.com> | 2013-04-02 10:56:56 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-10 07:19:26 -0400 |
commit | fb30809efa3edeb692a6b29125a07c9eceb322dc (patch) | |
tree | 2664f62ce2ca5f280defc9c3b96009007118c48f | |
parent | 5800043b2488a1c4c6e859af860644d37419d58b (diff) |
cpufreq: ondemand: allow custom powersave_bias_target handler to be registered
This allows for another [arch specific] driver to hook into existing
powersave bias function of the ondemand governor. i.e. This allows AMD
specific powersave bias function (in a separate AMD specific driver)
to aid ondemand governor's frequency transition decisions.
Signed-off-by: Jacob Shin <jacob.shin@amd.com>
Acked-by: Thomas Renninger <trenn@suse.de>
Acked-by: Borislav Petkov <bp@suse.de>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/cpufreq/cpufreq_governor.h | 4 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 61 |
2 files changed, 57 insertions, 8 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 513cc8234e5e..9f668e94dead 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h | |||
@@ -263,4 +263,8 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
263 | struct common_dbs_data *cdata, unsigned int event); | 263 | struct common_dbs_data *cdata, unsigned int event); |
264 | void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, | 264 | void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, |
265 | unsigned int delay, bool all_cpus); | 265 | unsigned int delay, bool all_cpus); |
266 | void od_register_powersave_bias_handler(unsigned int (*f) | ||
267 | (struct cpufreq_policy *, unsigned int, unsigned int), | ||
268 | unsigned int powersave_bias); | ||
269 | void od_unregister_powersave_bias_handler(void); | ||
266 | #endif /* _CPUFREQ_GOVERNER_H */ | 270 | #endif /* _CPUFREQ_GOVERNER_H */ |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 14714787b724..b0ffef96bf77 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/sysfs.h> | 24 | #include <linux/sysfs.h> |
25 | #include <linux/tick.h> | 25 | #include <linux/tick.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/cpu.h> | ||
27 | 28 | ||
28 | #include "cpufreq_governor.h" | 29 | #include "cpufreq_governor.h" |
29 | 30 | ||
@@ -40,6 +41,8 @@ | |||
40 | 41 | ||
41 | static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); | 42 | static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); |
42 | 43 | ||
44 | static struct od_ops od_ops; | ||
45 | |||
43 | #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND | 46 | #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND |
44 | static struct cpufreq_governor cpufreq_gov_ondemand; | 47 | static struct cpufreq_governor cpufreq_gov_ondemand; |
45 | #endif | 48 | #endif |
@@ -80,7 +83,7 @@ static int should_io_be_busy(void) | |||
80 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | 83 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, |
81 | * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. | 84 | * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. |
82 | */ | 85 | */ |
83 | static unsigned int powersave_bias_target(struct cpufreq_policy *policy, | 86 | static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy, |
84 | unsigned int freq_next, unsigned int relation) | 87 | unsigned int freq_next, unsigned int relation) |
85 | { | 88 | { |
86 | unsigned int freq_req, freq_reduc, freq_avg; | 89 | unsigned int freq_req, freq_reduc, freq_avg; |
@@ -145,7 +148,8 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) | |||
145 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; | 148 | struct od_dbs_tuners *od_tuners = dbs_data->tuners; |
146 | 149 | ||
147 | if (od_tuners->powersave_bias) | 150 | if (od_tuners->powersave_bias) |
148 | freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H); | 151 | freq = od_ops.powersave_bias_target(p, freq, |
152 | CPUFREQ_RELATION_H); | ||
149 | else if (p->cur == p->max) | 153 | else if (p->cur == p->max) |
150 | return; | 154 | return; |
151 | 155 | ||
@@ -205,12 +209,12 @@ static void od_check_cpu(int cpu, unsigned int load_freq) | |||
205 | if (!od_tuners->powersave_bias) { | 209 | if (!od_tuners->powersave_bias) { |
206 | __cpufreq_driver_target(policy, freq_next, | 210 | __cpufreq_driver_target(policy, freq_next, |
207 | CPUFREQ_RELATION_L); | 211 | CPUFREQ_RELATION_L); |
208 | } else { | 212 | return; |
209 | int freq = powersave_bias_target(policy, freq_next, | ||
210 | CPUFREQ_RELATION_L); | ||
211 | __cpufreq_driver_target(policy, freq, | ||
212 | CPUFREQ_RELATION_L); | ||
213 | } | 213 | } |
214 | |||
215 | freq_next = od_ops.powersave_bias_target(policy, freq_next, | ||
216 | CPUFREQ_RELATION_L); | ||
217 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); | ||
214 | } | 218 | } |
215 | } | 219 | } |
216 | 220 | ||
@@ -557,7 +561,7 @@ define_get_cpu_dbs_routines(od_cpu_dbs_info); | |||
557 | 561 | ||
558 | static struct od_ops od_ops = { | 562 | static struct od_ops od_ops = { |
559 | .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu, | 563 | .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu, |
560 | .powersave_bias_target = powersave_bias_target, | 564 | .powersave_bias_target = generic_powersave_bias_target, |
561 | .freq_increase = dbs_freq_increase, | 565 | .freq_increase = dbs_freq_increase, |
562 | }; | 566 | }; |
563 | 567 | ||
@@ -574,6 +578,47 @@ static struct common_dbs_data od_dbs_cdata = { | |||
574 | .exit = od_exit, | 578 | .exit = od_exit, |
575 | }; | 579 | }; |
576 | 580 | ||
581 | static void od_set_powersave_bias(unsigned int powersave_bias) | ||
582 | { | ||
583 | struct cpufreq_policy *policy; | ||
584 | struct dbs_data *dbs_data; | ||
585 | struct od_dbs_tuners *od_tuners; | ||
586 | unsigned int cpu; | ||
587 | cpumask_t done; | ||
588 | |||
589 | cpumask_clear(&done); | ||
590 | |||
591 | get_online_cpus(); | ||
592 | for_each_online_cpu(cpu) { | ||
593 | if (cpumask_test_cpu(cpu, &done)) | ||
594 | continue; | ||
595 | |||
596 | policy = per_cpu(od_cpu_dbs_info, cpu).cdbs.cur_policy; | ||
597 | dbs_data = policy->governor_data; | ||
598 | od_tuners = dbs_data->tuners; | ||
599 | od_tuners->powersave_bias = powersave_bias; | ||
600 | |||
601 | cpumask_or(&done, &done, policy->cpus); | ||
602 | } | ||
603 | put_online_cpus(); | ||
604 | } | ||
605 | |||
606 | void od_register_powersave_bias_handler(unsigned int (*f) | ||
607 | (struct cpufreq_policy *, unsigned int, unsigned int), | ||
608 | unsigned int powersave_bias) | ||
609 | { | ||
610 | od_ops.powersave_bias_target = f; | ||
611 | od_set_powersave_bias(powersave_bias); | ||
612 | } | ||
613 | EXPORT_SYMBOL_GPL(od_register_powersave_bias_handler); | ||
614 | |||
615 | void od_unregister_powersave_bias_handler(void) | ||
616 | { | ||
617 | od_ops.powersave_bias_target = generic_powersave_bias_target; | ||
618 | od_set_powersave_bias(0); | ||
619 | } | ||
620 | EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); | ||
621 | |||
577 | static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, | 622 | static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, |
578 | unsigned int event) | 623 | unsigned int event) |
579 | { | 624 | { |