aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-06-02 17:24:15 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-06-02 17:24:15 -0400
commite788892ba3cc71d385b75895f7a375fbc659ce86 (patch)
treef8a66153a91408f050eb7eb8d909c98d85a75ba9
parenta92604b419f47e1c5098632742d8e031f6e8fab1 (diff)
cpufreq: governor: Get rid of governor events
The design of the cpufreq governor API is not very straightforward, as struct cpufreq_governor provides only one callback to be invoked from different code paths for different purposes. The purpose it is invoked for is determined by its second "event" argument, causing it to act as a "callback multiplexer" of sorts. Unfortunately, that leads to extra complexity in governors, some of which implement the ->governor() callback as a switch statement that simply checks the event argument and invokes a separate function to handle that specific event. That extra complexity can be eliminated by replacing the all-purpose ->governor() callback with a family of callbacks to carry out specific governor operations: initialization and exit, start and stop and policy limits updates. That also turns out to reduce the code size too, so do it. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c72
-rw-r--r--drivers/cpufreq/cpufreq.c31
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c7
-rw-r--r--drivers/cpufreq/cpufreq_governor.c39
-rw-r--r--drivers/cpufreq/cpufreq_governor.h20
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c7
-rw-r--r--drivers/cpufreq/cpufreq_performance.c17
-rw-r--r--drivers/cpufreq/cpufreq_powersave.c17
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c104
-rw-r--r--include/linux/cpufreq.h14
-rw-r--r--kernel/sched/cpufreq_schedutil.c34
11 files changed, 158 insertions, 204 deletions
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index 82607d621aca..88301e53f085 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -85,61 +85,57 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
85 cancel_delayed_work_sync(&info->work); 85 cancel_delayed_work_sync(&info->work);
86} 86}
87 87
88static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event) 88static int spu_gov_start(struct cpufreq_policy *policy)
89{ 89{
90 unsigned int cpu = policy->cpu; 90 unsigned int cpu = policy->cpu;
91 struct spu_gov_info_struct *info, *affected_info; 91 struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
92 struct spu_gov_info_struct *affected_info;
92 int i; 93 int i;
93 int ret = 0;
94 94
95 info = &per_cpu(spu_gov_info, cpu); 95 if (!cpu_online(cpu)) {
96 96 printk(KERN_ERR "cpu %d is not online\n", cpu);
97 switch (event) { 97 return -EINVAL;
98 case CPUFREQ_GOV_START: 98 }
99 if (!cpu_online(cpu)) {
100 printk(KERN_ERR "cpu %d is not online\n", cpu);
101 ret = -EINVAL;
102 break;
103 }
104 99
105 if (!policy->cur) { 100 if (!policy->cur) {
106 printk(KERN_ERR "no cpu specified in policy\n"); 101 printk(KERN_ERR "no cpu specified in policy\n");
107 ret = -EINVAL; 102 return -EINVAL;
108 break; 103 }
109 }
110 104
111 /* initialize spu_gov_info for all affected cpus */ 105 /* initialize spu_gov_info for all affected cpus */
112 for_each_cpu(i, policy->cpus) { 106 for_each_cpu(i, policy->cpus) {
113 affected_info = &per_cpu(spu_gov_info, i); 107 affected_info = &per_cpu(spu_gov_info, i);
114 affected_info->policy = policy; 108 affected_info->policy = policy;
115 } 109 }
116 110
117 info->poll_int = POLL_TIME; 111 info->poll_int = POLL_TIME;
118 112
119 /* setup timer */ 113 /* setup timer */
120 spu_gov_init_work(info); 114 spu_gov_init_work(info);
121 115
122 break; 116 return 0;
117}
123 118
124 case CPUFREQ_GOV_STOP: 119static void spu_gov_stop(struct cpufreq_policy *policy)
125 /* cancel timer */ 120{
126 spu_gov_cancel_work(info); 121 unsigned int cpu = policy->cpu;
122 struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
123 int i;
127 124
128 /* clean spu_gov_info for all affected cpus */ 125 /* cancel timer */
129 for_each_cpu (i, policy->cpus) { 126 spu_gov_cancel_work(info);
130 info = &per_cpu(spu_gov_info, i);
131 info->policy = NULL;
132 }
133 127
134 break; 128 /* clean spu_gov_info for all affected cpus */
129 for_each_cpu (i, policy->cpus) {
130 info = &per_cpu(spu_gov_info, i);
131 info->policy = NULL;
135 } 132 }
136
137 return ret;
138} 133}
139 134
140static struct cpufreq_governor spu_governor = { 135static struct cpufreq_governor spu_governor = {
141 .name = "spudemand", 136 .name = "spudemand",
142 .governor = spu_gov_govern, 137 .start = spu_gov_start,
138 .stop = spu_gov_stop,
143 .owner = THIS_MODULE, 139 .owner = THIS_MODULE,
144}; 140};
145 141
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 268566e40684..d98ff688b2f1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2023,10 +2023,12 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)
2023 2023
2024 pr_debug("%s: for CPU %u\n", __func__, policy->cpu); 2024 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2025 2025
2026 ret = policy->governor->governor(policy, CPUFREQ_GOV_POLICY_INIT); 2026 if (policy->governor->init) {
2027 if (ret) { 2027 ret = policy->governor->init(policy);
2028 module_put(policy->governor->owner); 2028 if (ret) {
2029 return ret; 2029 module_put(policy->governor->owner);
2030 return ret;
2031 }
2030 } 2032 }
2031 2033
2032 policy->governor->initialized++; 2034 policy->governor->initialized++;
@@ -2040,7 +2042,8 @@ static void cpufreq_exit_governor(struct cpufreq_policy *policy)
2040 2042
2041 pr_debug("%s: for CPU %u\n", __func__, policy->cpu); 2043 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2042 2044
2043 policy->governor->governor(policy, CPUFREQ_GOV_POLICY_EXIT); 2045 if (policy->governor->exit)
2046 policy->governor->exit(policy);
2044 2047
2045 policy->governor->initialized--; 2048 policy->governor->initialized--;
2046 module_put(policy->governor->owner); 2049 module_put(policy->governor->owner);
@@ -2061,11 +2064,15 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy)
2061 if (cpufreq_driver->get && !cpufreq_driver->setpolicy) 2064 if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
2062 cpufreq_update_current_freq(policy); 2065 cpufreq_update_current_freq(policy);
2063 2066
2064 ret = policy->governor->governor(policy, CPUFREQ_GOV_START); 2067 if (policy->governor->start) {
2065 if (ret) 2068 ret = policy->governor->start(policy);
2066 return ret; 2069 if (ret)
2070 return ret;
2071 }
2072
2073 if (policy->governor->limits)
2074 policy->governor->limits(policy);
2067 2075
2068 policy->governor->governor(policy, CPUFREQ_GOV_LIMITS);
2069 return 0; 2076 return 0;
2070} 2077}
2071 2078
@@ -2076,7 +2083,8 @@ static void cpufreq_stop_governor(struct cpufreq_policy *policy)
2076 2083
2077 pr_debug("%s: for CPU %u\n", __func__, policy->cpu); 2084 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2078 2085
2079 policy->governor->governor(policy, CPUFREQ_GOV_STOP); 2086 if (policy->governor->stop)
2087 policy->governor->stop(policy);
2080} 2088}
2081 2089
2082static void cpufreq_governor_limits(struct cpufreq_policy *policy) 2090static void cpufreq_governor_limits(struct cpufreq_policy *policy)
@@ -2086,7 +2094,8 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy)
2086 2094
2087 pr_debug("%s: for CPU %u\n", __func__, policy->cpu); 2095 pr_debug("%s: for CPU %u\n", __func__, policy->cpu);
2088 2096
2089 policy->governor->governor(policy, CPUFREQ_GOV_LIMITS); 2097 if (policy->governor->limits)
2098 policy->governor->limits(policy);
2090} 2099}
2091 2100
2092int cpufreq_register_governor(struct cpufreq_governor *governor) 2101int cpufreq_register_governor(struct cpufreq_governor *governor)
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 316df247e00d..2568508fca38 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -313,12 +313,7 @@ static void cs_start(struct cpufreq_policy *policy)
313} 313}
314 314
315static struct dbs_governor cs_dbs_gov = { 315static struct dbs_governor cs_dbs_gov = {
316 .gov = { 316 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
317 .name = "conservative",
318 .governor = cpufreq_governor_dbs,
319 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
320 .owner = THIS_MODULE,
321 },
322 .kobj_type = { .default_attrs = cs_attributes }, 317 .kobj_type = { .default_attrs = cs_attributes },
323 .gov_dbs_timer = cs_dbs_timer, 318 .gov_dbs_timer = cs_dbs_timer,
324 .alloc = cs_alloc, 319 .alloc = cs_alloc,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index be498d56dd69..ca9927c15a71 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -389,7 +389,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
389 gov->free(policy_dbs); 389 gov->free(policy_dbs);
390} 390}
391 391
392static int cpufreq_governor_init(struct cpufreq_policy *policy) 392int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
393{ 393{
394 struct dbs_governor *gov = dbs_governor_of(policy); 394 struct dbs_governor *gov = dbs_governor_of(policy);
395 struct dbs_data *dbs_data; 395 struct dbs_data *dbs_data;
@@ -474,8 +474,9 @@ out:
474 mutex_unlock(&gov_dbs_data_mutex); 474 mutex_unlock(&gov_dbs_data_mutex);
475 return ret; 475 return ret;
476} 476}
477EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_init);
477 478
478static int cpufreq_governor_exit(struct cpufreq_policy *policy) 479void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy)
479{ 480{
480 struct dbs_governor *gov = dbs_governor_of(policy); 481 struct dbs_governor *gov = dbs_governor_of(policy);
481 struct policy_dbs_info *policy_dbs = policy->governor_data; 482 struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -500,10 +501,10 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
500 free_policy_dbs_info(policy_dbs, gov); 501 free_policy_dbs_info(policy_dbs, gov);
501 502
502 mutex_unlock(&gov_dbs_data_mutex); 503 mutex_unlock(&gov_dbs_data_mutex);
503 return 0;
504} 504}
505EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_exit);
505 506
506static int cpufreq_governor_start(struct cpufreq_policy *policy) 507int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
507{ 508{
508 struct dbs_governor *gov = dbs_governor_of(policy); 509 struct dbs_governor *gov = dbs_governor_of(policy);
509 struct policy_dbs_info *policy_dbs = policy->governor_data; 510 struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -539,14 +540,15 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
539 gov_set_update_util(policy_dbs, sampling_rate); 540 gov_set_update_util(policy_dbs, sampling_rate);
540 return 0; 541 return 0;
541} 542}
543EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_start);
542 544
543static int cpufreq_governor_stop(struct cpufreq_policy *policy) 545void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy)
544{ 546{
545 gov_cancel_work(policy); 547 gov_cancel_work(policy);
546 return 0;
547} 548}
549EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
548 550
549static int cpufreq_governor_limits(struct cpufreq_policy *policy) 551void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
550{ 552{
551 struct policy_dbs_info *policy_dbs = policy->governor_data; 553 struct policy_dbs_info *policy_dbs = policy->governor_data;
552 554
@@ -560,26 +562,5 @@ static int cpufreq_governor_limits(struct cpufreq_policy *policy)
560 gov_update_sample_delay(policy_dbs, 0); 562 gov_update_sample_delay(policy_dbs, 0);
561 563
562 mutex_unlock(&policy_dbs->timer_mutex); 564 mutex_unlock(&policy_dbs->timer_mutex);
563
564 return 0;
565}
566
567int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
568{
569 if (event == CPUFREQ_GOV_POLICY_INIT) {
570 return cpufreq_governor_init(policy);
571 } else if (policy->governor_data) {
572 switch (event) {
573 case CPUFREQ_GOV_POLICY_EXIT:
574 return cpufreq_governor_exit(policy);
575 case CPUFREQ_GOV_START:
576 return cpufreq_governor_start(policy);
577 case CPUFREQ_GOV_STOP:
578 return cpufreq_governor_stop(policy);
579 case CPUFREQ_GOV_LIMITS:
580 return cpufreq_governor_limits(policy);
581 }
582 }
583 return -EINVAL;
584} 565}
585EXPORT_SYMBOL_GPL(cpufreq_governor_dbs); 566EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 34eb214b6d57..36f0d19dd869 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
148 return container_of(policy->governor, struct dbs_governor, gov); 148 return container_of(policy->governor, struct dbs_governor, gov);
149} 149}
150 150
151/* Governor callback routines */
152int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
153void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
154int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
155void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy);
156void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
157
158#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \
159 { \
160 .name = _name_, \
161 .max_transition_latency = TRANSITION_LATENCY_LIMIT, \
162 .owner = THIS_MODULE, \
163 .init = cpufreq_dbs_governor_init, \
164 .exit = cpufreq_dbs_governor_exit, \
165 .start = cpufreq_dbs_governor_start, \
166 .stop = cpufreq_dbs_governor_stop, \
167 .limits = cpufreq_dbs_governor_limits, \
168 }
169
151/* Governor specific operations */ 170/* Governor specific operations */
152struct od_ops { 171struct od_ops {
153 unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, 172 unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
@@ -155,7 +174,6 @@ struct od_ops {
155}; 174};
156 175
157unsigned int dbs_update(struct cpufreq_policy *policy); 176unsigned int dbs_update(struct cpufreq_policy *policy);
158int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
159void od_register_powersave_bias_handler(unsigned int (*f) 177void od_register_powersave_bias_handler(unsigned int (*f)
160 (struct cpufreq_policy *, unsigned int, unsigned int), 178 (struct cpufreq_policy *, unsigned int, unsigned int),
161 unsigned int powersave_bias); 179 unsigned int powersave_bias);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 300163430516..09d6c0c405e4 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -420,12 +420,7 @@ static struct od_ops od_ops = {
420}; 420};
421 421
422static struct dbs_governor od_dbs_gov = { 422static struct dbs_governor od_dbs_gov = {
423 .gov = { 423 .gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
424 .name = "ondemand",
425 .governor = cpufreq_governor_dbs,
426 .max_transition_latency = TRANSITION_LATENCY_LIMIT,
427 .owner = THIS_MODULE,
428 },
429 .kobj_type = { .default_attrs = od_attributes }, 424 .kobj_type = { .default_attrs = od_attributes },
430 .gov_dbs_timer = od_dbs_timer, 425 .gov_dbs_timer = od_dbs_timer,
431 .alloc = od_alloc, 426 .alloc = od_alloc,
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index dd4dca3ab844..dafb679adc58 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -16,25 +16,16 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19static int cpufreq_governor_performance(struct cpufreq_policy *policy, 19static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
20 unsigned int event)
21{ 20{
22 switch (event) { 21 pr_debug("setting to %u kHz\n", policy->max);
23 case CPUFREQ_GOV_LIMITS: 22 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
24 pr_debug("setting to %u kHz\n", policy->max);
25 __cpufreq_driver_target(policy, policy->max,
26 CPUFREQ_RELATION_H);
27 break;
28 default:
29 break;
30 }
31 return 0;
32} 23}
33 24
34static struct cpufreq_governor cpufreq_gov_performance = { 25static struct cpufreq_governor cpufreq_gov_performance = {
35 .name = "performance", 26 .name = "performance",
36 .governor = cpufreq_governor_performance,
37 .owner = THIS_MODULE, 27 .owner = THIS_MODULE,
28 .limits = cpufreq_gov_performance_limits,
38}; 29};
39 30
40static int __init cpufreq_gov_performance_init(void) 31static int __init cpufreq_gov_performance_init(void)
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index 691e573e46ee..78a651038faf 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -16,24 +16,15 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19static int cpufreq_governor_powersave(struct cpufreq_policy *policy, 19static void cpufreq_gov_powersave_limits(struct cpufreq_policy *policy)
20 unsigned int event)
21{ 20{
22 switch (event) { 21 pr_debug("setting to %u kHz\n", policy->min);
23 case CPUFREQ_GOV_LIMITS: 22 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
24 pr_debug("setting to %u kHz\n", policy->min);
25 __cpufreq_driver_target(policy, policy->min,
26 CPUFREQ_RELATION_L);
27 break;
28 default:
29 break;
30 }
31 return 0;
32} 23}
33 24
34static struct cpufreq_governor cpufreq_gov_powersave = { 25static struct cpufreq_governor cpufreq_gov_powersave = {
35 .name = "powersave", 26 .name = "powersave",
36 .governor = cpufreq_governor_powersave, 27 .limits = cpufreq_gov_powersave_limits,
37 .owner = THIS_MODULE, 28 .owner = THIS_MODULE,
38}; 29};
39 30
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 9f3dec9a3f36..bd897e3e134d 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -65,66 +65,66 @@ static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
65 return 0; 65 return 0;
66} 66}
67 67
68static int cpufreq_governor_userspace(struct cpufreq_policy *policy, 68static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
69 unsigned int event) 69{
70 mutex_lock(&userspace_mutex);
71 kfree(policy->governor_data);
72 policy->governor_data = NULL;
73 mutex_unlock(&userspace_mutex);
74}
75
76static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
70{ 77{
71 unsigned int *setspeed = policy->governor_data; 78 unsigned int *setspeed = policy->governor_data;
72 unsigned int cpu = policy->cpu;
73 int rc = 0;
74 79
75 if (event == CPUFREQ_GOV_POLICY_INIT) 80 BUG_ON(!policy->cur);
76 return cpufreq_userspace_policy_init(policy); 81 pr_debug("started managing cpu %u\n", policy->cpu);
77 82
78 if (!setspeed) 83 mutex_lock(&userspace_mutex);
79 return -EINVAL; 84 per_cpu(cpu_is_managed, policy->cpu) = 1;
80 85 *setspeed = policy->cur;
81 switch (event) { 86 mutex_unlock(&userspace_mutex);
82 case CPUFREQ_GOV_POLICY_EXIT: 87 return 0;
83 mutex_lock(&userspace_mutex); 88}
84 policy->governor_data = NULL; 89
85 kfree(setspeed); 90static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
86 mutex_unlock(&userspace_mutex); 91{
87 break; 92 unsigned int *setspeed = policy->governor_data;
88 case CPUFREQ_GOV_START: 93
89 BUG_ON(!policy->cur); 94 pr_debug("managing cpu %u stopped\n", policy->cpu);
90 pr_debug("started managing cpu %u\n", cpu); 95
91 96 mutex_lock(&userspace_mutex);
92 mutex_lock(&userspace_mutex); 97 per_cpu(cpu_is_managed, policy->cpu) = 0;
93 per_cpu(cpu_is_managed, cpu) = 1; 98 *setspeed = 0;
94 *setspeed = policy->cur; 99 mutex_unlock(&userspace_mutex);
95 mutex_unlock(&userspace_mutex); 100}
96 break; 101
97 case CPUFREQ_GOV_STOP: 102static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
98 pr_debug("managing cpu %u stopped\n", cpu); 103{
99 104 unsigned int *setspeed = policy->governor_data;
100 mutex_lock(&userspace_mutex); 105
101 per_cpu(cpu_is_managed, cpu) = 0; 106 mutex_lock(&userspace_mutex);
102 *setspeed = 0; 107
103 mutex_unlock(&userspace_mutex); 108 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
104 break; 109 policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
105 case CPUFREQ_GOV_LIMITS: 110
106 mutex_lock(&userspace_mutex); 111 if (policy->max < *setspeed)
107 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", 112 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
108 cpu, policy->min, policy->max, policy->cur, *setspeed); 113 else if (policy->min > *setspeed)
109 114 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
110 if (policy->max < *setspeed) 115 else
111 __cpufreq_driver_target(policy, policy->max, 116 __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
112 CPUFREQ_RELATION_H); 117
113 else if (policy->min > *setspeed) 118 mutex_unlock(&userspace_mutex);
114 __cpufreq_driver_target(policy, policy->min,
115 CPUFREQ_RELATION_L);
116 else
117 __cpufreq_driver_target(policy, *setspeed,
118 CPUFREQ_RELATION_L);
119 mutex_unlock(&userspace_mutex);
120 break;
121 }
122 return rc;
123} 119}
124 120
125static struct cpufreq_governor cpufreq_gov_userspace = { 121static struct cpufreq_governor cpufreq_gov_userspace = {
126 .name = "userspace", 122 .name = "userspace",
127 .governor = cpufreq_governor_userspace, 123 .init = cpufreq_userspace_policy_init,
124 .exit = cpufreq_userspace_policy_exit,
125 .start = cpufreq_userspace_policy_start,
126 .stop = cpufreq_userspace_policy_stop,
127 .limits = cpufreq_userspace_policy_limits,
128 .store_setspeed = cpufreq_set, 128 .store_setspeed = cpufreq_set,
129 .show_setspeed = show_speed, 129 .show_setspeed = show_speed,
130 .owner = THIS_MODULE, 130 .owner = THIS_MODULE,
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4e81e08db752..5bcda3e6aa9e 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -455,18 +455,14 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div,
455#define MIN_LATENCY_MULTIPLIER (20) 455#define MIN_LATENCY_MULTIPLIER (20)
456#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) 456#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000)
457 457
458/* Governor Events */
459#define CPUFREQ_GOV_START 1
460#define CPUFREQ_GOV_STOP 2
461#define CPUFREQ_GOV_LIMITS 3
462#define CPUFREQ_GOV_POLICY_INIT 4
463#define CPUFREQ_GOV_POLICY_EXIT 5
464
465struct cpufreq_governor { 458struct cpufreq_governor {
466 char name[CPUFREQ_NAME_LEN]; 459 char name[CPUFREQ_NAME_LEN];
467 int initialized; 460 int initialized;
468 int (*governor) (struct cpufreq_policy *policy, 461 int (*init)(struct cpufreq_policy *policy);
469 unsigned int event); 462 void (*exit)(struct cpufreq_policy *policy);
463 int (*start)(struct cpufreq_policy *policy);
464 void (*stop)(struct cpufreq_policy *policy);
465 void (*limits)(struct cpufreq_policy *policy);
470 ssize_t (*show_setspeed) (struct cpufreq_policy *policy, 466 ssize_t (*show_setspeed) (struct cpufreq_policy *policy,
471 char *buf); 467 char *buf);
472 int (*store_setspeed) (struct cpufreq_policy *policy, 468 int (*store_setspeed) (struct cpufreq_policy *policy,
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 14c4aa25cc45..fdcee3cf38fc 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -394,7 +394,7 @@ static int sugov_init(struct cpufreq_policy *policy)
394 return ret; 394 return ret;
395} 395}
396 396
397static int sugov_exit(struct cpufreq_policy *policy) 397static void sugov_exit(struct cpufreq_policy *policy)
398{ 398{
399 struct sugov_policy *sg_policy = policy->governor_data; 399 struct sugov_policy *sg_policy = policy->governor_data;
400 struct sugov_tunables *tunables = sg_policy->tunables; 400 struct sugov_tunables *tunables = sg_policy->tunables;
@@ -412,7 +412,6 @@ static int sugov_exit(struct cpufreq_policy *policy)
412 mutex_unlock(&global_tunables_lock); 412 mutex_unlock(&global_tunables_lock);
413 413
414 sugov_policy_free(sg_policy); 414 sugov_policy_free(sg_policy);
415 return 0;
416} 415}
417 416
418static int sugov_start(struct cpufreq_policy *policy) 417static int sugov_start(struct cpufreq_policy *policy)
@@ -444,7 +443,7 @@ static int sugov_start(struct cpufreq_policy *policy)
444 return 0; 443 return 0;
445} 444}
446 445
447static int sugov_stop(struct cpufreq_policy *policy) 446static void sugov_stop(struct cpufreq_policy *policy)
448{ 447{
449 struct sugov_policy *sg_policy = policy->governor_data; 448 struct sugov_policy *sg_policy = policy->governor_data;
450 unsigned int cpu; 449 unsigned int cpu;
@@ -456,10 +455,9 @@ static int sugov_stop(struct cpufreq_policy *policy)
456 455
457 irq_work_sync(&sg_policy->irq_work); 456 irq_work_sync(&sg_policy->irq_work);
458 cancel_work_sync(&sg_policy->work); 457 cancel_work_sync(&sg_policy->work);
459 return 0;
460} 458}
461 459
462static int sugov_limits(struct cpufreq_policy *policy) 460static void sugov_limits(struct cpufreq_policy *policy)
463{ 461{
464 struct sugov_policy *sg_policy = policy->governor_data; 462 struct sugov_policy *sg_policy = policy->governor_data;
465 463
@@ -477,32 +475,16 @@ static int sugov_limits(struct cpufreq_policy *policy)
477 } 475 }
478 476
479 sg_policy->need_freq_update = true; 477 sg_policy->need_freq_update = true;
480 return 0;
481}
482
483int sugov_governor(struct cpufreq_policy *policy, unsigned int event)
484{
485 if (event == CPUFREQ_GOV_POLICY_INIT) {
486 return sugov_init(policy);
487 } else if (policy->governor_data) {
488 switch (event) {
489 case CPUFREQ_GOV_POLICY_EXIT:
490 return sugov_exit(policy);
491 case CPUFREQ_GOV_START:
492 return sugov_start(policy);
493 case CPUFREQ_GOV_STOP:
494 return sugov_stop(policy);
495 case CPUFREQ_GOV_LIMITS:
496 return sugov_limits(policy);
497 }
498 }
499 return -EINVAL;
500} 478}
501 479
502static struct cpufreq_governor schedutil_gov = { 480static struct cpufreq_governor schedutil_gov = {
503 .name = "schedutil", 481 .name = "schedutil",
504 .governor = sugov_governor,
505 .owner = THIS_MODULE, 482 .owner = THIS_MODULE,
483 .init = sugov_init,
484 .exit = sugov_exit,
485 .start = sugov_start,
486 .stop = sugov_stop,
487 .limits = sugov_limits,
506}; 488};
507 489
508static int __init sugov_module_init(void) 490static int __init sugov_module_init(void)