提交 031299b3 编写于 作者: V Viresh Kumar 提交者: Rafael J. Wysocki

cpufreq: governors: Avoid unnecessary per cpu timer interrupts

Following patch has introduced per cpu timers or works for ondemand and
conservative governors.

	commit 2abfa876
	Author: Rickard Andersson <rickard.andersson@stericsson.com>
	Date:   Thu Dec 27 14:55:38 2012 +0000

	    cpufreq: handle SW coordinated CPUs

This causes additional unnecessary interrupts on all cpus when the load is
recently evaluated by any other cpu. i.e. When load is recently evaluated by cpu
x, we don't really need any other cpu to evaluate this load again for the next
sampling_rate time.

Some sort of code is present to avoid that but we are still getting timer
interrupts for all cpus. A good way of avoiding this would be to modify delays
for all cpus (policy->cpus) whenever any cpu has evaluated load.

This patch does this change and some related code cleanup.
Signed-off-by: NViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
上级 9d445920
...@@ -107,7 +107,6 @@ static void cs_check_cpu(int cpu, unsigned int load) ...@@ -107,7 +107,6 @@ static void cs_check_cpu(int cpu, unsigned int load)
static void cs_dbs_timer(struct work_struct *work) static void cs_dbs_timer(struct work_struct *work)
{ {
struct delayed_work *dw = to_delayed_work(work);
struct cs_cpu_dbs_info_s *dbs_info = container_of(work, struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
struct cs_cpu_dbs_info_s, cdbs.work.work); struct cs_cpu_dbs_info_s, cdbs.work.work);
unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; unsigned int cpu = dbs_info->cdbs.cur_policy->cpu;
...@@ -116,12 +115,15 @@ static void cs_dbs_timer(struct work_struct *work) ...@@ -116,12 +115,15 @@ static void cs_dbs_timer(struct work_struct *work)
struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data; struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data;
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
int delay = delay_for_sampling_rate(cs_tuners->sampling_rate); int delay = delay_for_sampling_rate(cs_tuners->sampling_rate);
bool modify_all = true;
mutex_lock(&core_dbs_info->cdbs.timer_mutex); mutex_lock(&core_dbs_info->cdbs.timer_mutex);
if (need_load_eval(&core_dbs_info->cdbs, cs_tuners->sampling_rate)) if (!need_load_eval(&core_dbs_info->cdbs, cs_tuners->sampling_rate))
modify_all = false;
else
dbs_check_cpu(dbs_data, cpu); dbs_check_cpu(dbs_data, cpu);
schedule_delayed_work_on(smp_processor_id(), dw, delay); gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all);
mutex_unlock(&core_dbs_info->cdbs.timer_mutex); mutex_unlock(&core_dbs_info->cdbs.timer_mutex);
} }
......
...@@ -178,20 +178,38 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) ...@@ -178,20 +178,38 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
} }
EXPORT_SYMBOL_GPL(dbs_check_cpu); EXPORT_SYMBOL_GPL(dbs_check_cpu);
static inline void dbs_timer_init(struct dbs_data *dbs_data, int cpu, static inline void __gov_queue_work(int cpu, struct dbs_data *dbs_data,
unsigned int sampling_rate) unsigned int delay)
{ {
int delay = delay_for_sampling_rate(sampling_rate);
struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
schedule_delayed_work_on(cpu, &cdbs->work, delay); mod_delayed_work_on(cpu, system_wq, &cdbs->work, delay);
} }
static inline void dbs_timer_exit(struct dbs_data *dbs_data, int cpu) void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
unsigned int delay, bool all_cpus)
{ {
struct cpu_dbs_common_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu); int i;
if (!all_cpus) {
__gov_queue_work(smp_processor_id(), dbs_data, delay);
} else {
for_each_cpu(i, policy->cpus)
__gov_queue_work(i, dbs_data, delay);
}
}
EXPORT_SYMBOL_GPL(gov_queue_work);
static inline void gov_cancel_work(struct dbs_data *dbs_data,
struct cpufreq_policy *policy)
{
struct cpu_dbs_common_info *cdbs;
int i;
cancel_delayed_work_sync(&cdbs->work); for_each_cpu(i, policy->cpus) {
cdbs = dbs_data->cdata->get_cpu_cdbs(i);
cancel_delayed_work_sync(&cdbs->work);
}
} }
/* Will return if we need to evaluate cpu load again or not */ /* Will return if we need to evaluate cpu load again or not */
...@@ -380,16 +398,15 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, ...@@ -380,16 +398,15 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
/* Initiate timer time stamp */ /* Initiate timer time stamp */
cpu_cdbs->time_stamp = ktime_get(); cpu_cdbs->time_stamp = ktime_get();
for_each_cpu(j, policy->cpus) gov_queue_work(dbs_data, policy,
dbs_timer_init(dbs_data, j, sampling_rate); delay_for_sampling_rate(sampling_rate), true);
break; break;
case CPUFREQ_GOV_STOP: case CPUFREQ_GOV_STOP:
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) if (dbs_data->cdata->governor == GOV_CONSERVATIVE)
cs_dbs_info->enable = 0; cs_dbs_info->enable = 0;
for_each_cpu(j, policy->cpus) gov_cancel_work(dbs_data, policy);
dbs_timer_exit(dbs_data, j);
mutex_lock(&dbs_data->mutex); mutex_lock(&dbs_data->mutex);
mutex_destroy(&cpu_cdbs->timer_mutex); mutex_destroy(&cpu_cdbs->timer_mutex);
......
...@@ -262,4 +262,6 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs, ...@@ -262,4 +262,6 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
unsigned int sampling_rate); unsigned int sampling_rate);
int cpufreq_governor_dbs(struct cpufreq_policy *policy, int cpufreq_governor_dbs(struct cpufreq_policy *policy,
struct common_dbs_data *cdata, unsigned int event); struct common_dbs_data *cdata, unsigned int event);
void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
unsigned int delay, bool all_cpus);
#endif /* _CPUFREQ_GOVERNER_H */ #endif /* _CPUFREQ_GOVERNER_H */
...@@ -216,7 +216,6 @@ static void od_check_cpu(int cpu, unsigned int load_freq) ...@@ -216,7 +216,6 @@ static void od_check_cpu(int cpu, unsigned int load_freq)
static void od_dbs_timer(struct work_struct *work) static void od_dbs_timer(struct work_struct *work)
{ {
struct delayed_work *dw = to_delayed_work(work);
struct od_cpu_dbs_info_s *dbs_info = struct od_cpu_dbs_info_s *dbs_info =
container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work); container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
unsigned int cpu = dbs_info->cdbs.cur_policy->cpu; unsigned int cpu = dbs_info->cdbs.cur_policy->cpu;
...@@ -225,10 +224,13 @@ static void od_dbs_timer(struct work_struct *work) ...@@ -225,10 +224,13 @@ static void od_dbs_timer(struct work_struct *work)
struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data; struct dbs_data *dbs_data = dbs_info->cdbs.cur_policy->governor_data;
struct od_dbs_tuners *od_tuners = dbs_data->tuners; struct od_dbs_tuners *od_tuners = dbs_data->tuners;
int delay = 0, sample_type = core_dbs_info->sample_type; int delay = 0, sample_type = core_dbs_info->sample_type;
bool modify_all = true;
mutex_lock(&core_dbs_info->cdbs.timer_mutex); mutex_lock(&core_dbs_info->cdbs.timer_mutex);
if (!need_load_eval(&core_dbs_info->cdbs, od_tuners->sampling_rate)) if (!need_load_eval(&core_dbs_info->cdbs, od_tuners->sampling_rate)) {
modify_all = false;
goto max_delay; goto max_delay;
}
/* Common NORMAL_SAMPLE setup */ /* Common NORMAL_SAMPLE setup */
core_dbs_info->sample_type = OD_NORMAL_SAMPLE; core_dbs_info->sample_type = OD_NORMAL_SAMPLE;
...@@ -250,7 +252,7 @@ static void od_dbs_timer(struct work_struct *work) ...@@ -250,7 +252,7 @@ static void od_dbs_timer(struct work_struct *work)
delay = delay_for_sampling_rate(od_tuners->sampling_rate delay = delay_for_sampling_rate(od_tuners->sampling_rate
* core_dbs_info->rate_mult); * core_dbs_info->rate_mult);
schedule_delayed_work_on(smp_processor_id(), dw, delay); gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy, delay, modify_all);
mutex_unlock(&core_dbs_info->cdbs.timer_mutex); mutex_unlock(&core_dbs_info->cdbs.timer_mutex);
} }
...@@ -310,8 +312,8 @@ static void update_sampling_rate(struct dbs_data *dbs_data, ...@@ -310,8 +312,8 @@ static void update_sampling_rate(struct dbs_data *dbs_data,
cancel_delayed_work_sync(&dbs_info->cdbs.work); cancel_delayed_work_sync(&dbs_info->cdbs.work);
mutex_lock(&dbs_info->cdbs.timer_mutex); mutex_lock(&dbs_info->cdbs.timer_mutex);
schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, gov_queue_work(dbs_data, dbs_info->cdbs.cur_policy,
usecs_to_jiffies(new_rate)); usecs_to_jiffies(new_rate), true);
} }
mutex_unlock(&dbs_info->cdbs.timer_mutex); mutex_unlock(&dbs_info->cdbs.timer_mutex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册