aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_governor.h
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-08 21:44:05 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-09 22:26:13 +0100
commit2dd3e724b4e2237cfaaf155cab72af02c1c420cc (patch)
tree5c66a069efca038756228ee65e71e0dd7e4807a1 /drivers/cpufreq/cpufreq_governor.h
parentcpufreq: ondemand: update update_sampling_rate() to make it more efficient (diff)
downloadlinux-dev-2dd3e724b4e2237cfaaf155cab72af02c1c420cc.tar.xz
linux-dev-2dd3e724b4e2237cfaaf155cab72af02c1c420cc.zip
cpufreq: governor: Use lockless timer function
It is possible to get rid of the timer_lock spinlock used by the governor timer function for synchronization, but a couple of races need to be avoided. The first race is between multiple dbs_timer_handler() instances that may be running in parallel with each other on different CPUs. Namely, one of them has to queue up the work item, but it cannot be queued up more than once. To achieve that, atomic_inc_return() can be used on the skip_work field of struct cpu_common_dbs_info. The second race is between an already running dbs_timer_handler() and gov_cancel_work(). In that case the dbs_timer_handler() might not notice the skip_work incrementation in gov_cancel_work() and it might queue up its work item after gov_cancel_work() had returned (and that work item would corrupt skip_work going forward). To prevent that from happening, gov_cancel_work() can be made wait for the timer function to complete (on all CPUs) right after skip_work has been incremented. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/cpufreq/cpufreq_governor.h')
-rw-r--r--drivers/cpufreq/cpufreq_governor.h9
1 files changed, 2 insertions, 7 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 76742902491e..91e767a058a7 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -17,6 +17,7 @@
#ifndef _CPUFREQ_GOVERNOR_H
#define _CPUFREQ_GOVERNOR_H
+#include <linux/atomic.h>
#include <linux/cpufreq.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
@@ -137,14 +138,8 @@ struct cpu_common_dbs_info {
*/
struct mutex timer_mutex;
- /*
- * Per policy lock that serializes access to queuing work from timer
- * handlers.
- */
- spinlock_t timer_lock;
-
ktime_t time_stamp;
- unsigned int skip_work;
+ atomic_t skip_work;
struct work_struct work;
};