aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRickard Andersson <rickard.andersson@stericsson.com>2012-12-27 09:55:38 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-01 18:01:13 -0500
commit2abfa876f1117b0ab45f191fb1f82c41b1cbc8fe (patch)
tree929f7c181cead27bc5c1d320c53ba0e99a9f0544
parent88b62b915b0b7e25870eb0604ed9a92ba4bfc9f7 (diff)
cpufreq: handle SW coordinated CPUs
This patch fixes a bug that occurred when we had load on a secondary CPU and the primary CPU was sleeping. Only one sampling timer was spawned and it was spawned as a deferred timer on the primary CPU, so when a secondary CPU had a change in load this was not detected by the cpufreq governor (both ondemand and conservative). This patch make sure that deferred timers are run on all CPUs in the case of software controlled CPUs that run on the same frequency. Signed-off-by: Rickard Andersson <rickard.andersson@stericsson.com> Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c3
-rw-r--r--drivers/cpufreq/cpufreq_governor.c44
-rw-r--r--drivers/cpufreq/cpufreq_governor.h1
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c3
4 files changed, 43 insertions, 8 deletions
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 64ef737e7e72..b9d7f14d7d3d 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -122,7 +122,8 @@ static void cs_dbs_timer(struct work_struct *work)
122 122
123 dbs_check_cpu(&cs_dbs_data, cpu); 123 dbs_check_cpu(&cs_dbs_data, cpu);
124 124
125 schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay); 125 schedule_delayed_work_on(smp_processor_id(), &dbs_info->cdbs.work,
126 delay);
126 mutex_unlock(&dbs_info->cdbs.timer_mutex); 127 mutex_unlock(&dbs_info->cdbs.timer_mutex);
127} 128}
128 129
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 6c5f1d383cdc..b0e4506f2cae 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -161,13 +161,23 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
161} 161}
162EXPORT_SYMBOL_GPL(dbs_check_cpu); 162EXPORT_SYMBOL_GPL(dbs_check_cpu);
163 163
164bool dbs_sw_coordinated_cpus(struct cpu_dbs_common_info *cdbs)
165{
166 struct cpufreq_policy *policy = cdbs->cur_policy;
167
168 return cpumask_weight(policy->cpus) > 1;
169}
170EXPORT_SYMBOL_GPL(dbs_sw_coordinated_cpus);
171
164static inline void dbs_timer_init(struct dbs_data *dbs_data, 172static inline void dbs_timer_init(struct dbs_data *dbs_data,
165 struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate) 173 struct cpu_dbs_common_info *cdbs,
174 unsigned int sampling_rate,
175 int cpu)
166{ 176{
167 int delay = delay_for_sampling_rate(sampling_rate); 177 int delay = delay_for_sampling_rate(sampling_rate);
178 struct cpu_dbs_common_info *cdbs_local = dbs_data->get_cpu_cdbs(cpu);
168 179
169 INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer); 180 schedule_delayed_work_on(cpu, &cdbs_local->work, delay);
170 schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
171} 181}
172 182
173static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs) 183static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
@@ -217,6 +227,10 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
217 if (ignore_nice) 227 if (ignore_nice)
218 j_cdbs->prev_cpu_nice = 228 j_cdbs->prev_cpu_nice =
219 kcpustat_cpu(j).cpustat[CPUTIME_NICE]; 229 kcpustat_cpu(j).cpustat[CPUTIME_NICE];
230
231 mutex_init(&j_cdbs->timer_mutex);
232 INIT_DEFERRABLE_WORK(&j_cdbs->work,
233 dbs_data->gov_dbs_timer);
220 } 234 }
221 235
222 /* 236 /*
@@ -275,15 +289,33 @@ second_time:
275 } 289 }
276 mutex_unlock(&dbs_data->mutex); 290 mutex_unlock(&dbs_data->mutex);
277 291
278 mutex_init(&cpu_cdbs->timer_mutex); 292 if (dbs_sw_coordinated_cpus(cpu_cdbs)) {
279 dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate); 293 for_each_cpu(j, policy->cpus) {
294 struct cpu_dbs_common_info *j_cdbs;
295
296 j_cdbs = dbs_data->get_cpu_cdbs(j);
297 dbs_timer_init(dbs_data, j_cdbs,
298 *sampling_rate, j);
299 }
300 } else {
301 dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate, cpu);
302 }
280 break; 303 break;
281 304
282 case CPUFREQ_GOV_STOP: 305 case CPUFREQ_GOV_STOP:
283 if (dbs_data->governor == GOV_CONSERVATIVE) 306 if (dbs_data->governor == GOV_CONSERVATIVE)
284 cs_dbs_info->enable = 0; 307 cs_dbs_info->enable = 0;
285 308
286 dbs_timer_exit(cpu_cdbs); 309 if (dbs_sw_coordinated_cpus(cpu_cdbs)) {
310 for_each_cpu(j, policy->cpus) {
311 struct cpu_dbs_common_info *j_cdbs;
312
313 j_cdbs = dbs_data->get_cpu_cdbs(j);
314 dbs_timer_exit(j_cdbs);
315 }
316 } else {
317 dbs_timer_exit(cpu_cdbs);
318 }
287 319
288 mutex_lock(&dbs_data->mutex); 320 mutex_lock(&dbs_data->mutex);
289 mutex_destroy(&cpu_cdbs->timer_mutex); 321 mutex_destroy(&cpu_cdbs->timer_mutex);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index f6616540c53d..5bf6fb8023ef 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -171,6 +171,7 @@ static inline int delay_for_sampling_rate(unsigned int sampling_rate)
171 171
172u64 get_cpu_idle_time(unsigned int cpu, u64 *wall); 172u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
173void dbs_check_cpu(struct dbs_data *dbs_data, int cpu); 173void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
174bool dbs_sw_coordinated_cpus(struct cpu_dbs_common_info *cdbs);
174int cpufreq_governor_dbs(struct dbs_data *dbs_data, 175int cpufreq_governor_dbs(struct dbs_data *dbs_data,
175 struct cpufreq_policy *policy, unsigned int event); 176 struct cpufreq_policy *policy, unsigned int event);
176#endif /* _CPUFREQ_GOVERNER_H */ 177#endif /* _CPUFREQ_GOVERNER_H */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 7731f7c7e79a..93bb56d14cfa 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -243,7 +243,8 @@ static void od_dbs_timer(struct work_struct *work)
243 } 243 }
244 } 244 }
245 245
246 schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay); 246 schedule_delayed_work_on(smp_processor_id(), &dbs_info->cdbs.work,
247 delay);
247 mutex_unlock(&dbs_info->cdbs.timer_mutex); 248 mutex_unlock(&dbs_info->cdbs.timer_mutex);
248} 249}
249 250