Skip to content

Commit 2abfa87

Browse files
Rickard Anderssonrafaeljw
authored andcommitted
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 <[email protected]> Signed-off-by: Fabio Baltieri <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 88b62b9 commit 2abfa87

File tree

4 files changed

+43
-8
lines changed

4 files changed

+43
-8
lines changed

drivers/cpufreq/cpufreq_conservative.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ static void cs_dbs_timer(struct work_struct *work)
122122

123123
dbs_check_cpu(&cs_dbs_data, cpu);
124124

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);
126127
mutex_unlock(&dbs_info->cdbs.timer_mutex);
127128
}
128129

drivers/cpufreq/cpufreq_governor.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,23 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
161161
}
162162
EXPORT_SYMBOL_GPL(dbs_check_cpu);
163163

164+
bool 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+
}
170+
EXPORT_SYMBOL_GPL(dbs_sw_coordinated_cpus);
171+
164172
static 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)
166176
{
167177
int delay = delay_for_sampling_rate(sampling_rate);
178+
struct cpu_dbs_common_info *cdbs_local = dbs_data->get_cpu_cdbs(cpu);
168179

169-
INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer);
170-
schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
180+
schedule_delayed_work_on(cpu, &cdbs_local->work, delay);
171181
}
172182

173183
static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
@@ -217,6 +227,10 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
217227
if (ignore_nice)
218228
j_cdbs->prev_cpu_nice =
219229
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);
220234
}
221235

222236
/*
@@ -275,15 +289,33 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
275289
}
276290
mutex_unlock(&dbs_data->mutex);
277291

278-
mutex_init(&cpu_cdbs->timer_mutex);
279-
dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate);
292+
if (dbs_sw_coordinated_cpus(cpu_cdbs)) {
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+
}
280303
break;
281304

282305
case CPUFREQ_GOV_STOP:
283306
if (dbs_data->governor == GOV_CONSERVATIVE)
284307
cs_dbs_info->enable = 0;
285308

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+
}
287319

288320
mutex_lock(&dbs_data->mutex);
289321
mutex_destroy(&cpu_cdbs->timer_mutex);

drivers/cpufreq/cpufreq_governor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ static inline int delay_for_sampling_rate(unsigned int sampling_rate)
171171

172172
u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
173173
void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
174+
bool dbs_sw_coordinated_cpus(struct cpu_dbs_common_info *cdbs);
174175
int cpufreq_governor_dbs(struct dbs_data *dbs_data,
175176
struct cpufreq_policy *policy, unsigned int event);
176177
#endif /* _CPUFREQ_GOVERNER_H */

drivers/cpufreq/cpufreq_ondemand.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ static void od_dbs_timer(struct work_struct *work)
243243
}
244244
}
245245

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);
247248
mutex_unlock(&dbs_info->cdbs.timer_mutex);
248249
}
249250

0 commit comments

Comments
 (0)