summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_governor.h
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2016-02-10 06:30:25 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-03-09 14:40:59 +0100
commitc54df0718423ea2941151d8516eb76ca6a32a4b4 (patch)
tree815146ab0eff04a46129e523a8255ba3ca07ab83 /drivers/cpufreq/cpufreq_governor.h
parentRevert "cpufreq: Drop rwsem lock around CPUFREQ_GOV_POLICY_EXIT" (diff)
downloadlinux-c54df0718423ea2941151d8516eb76ca6a32a4b4.tar.xz
linux-c54df0718423ea2941151d8516eb76ca6a32a4b4.zip
cpufreq: governor: Create and traverse list of policy_dbs to avoid deadlock
The dbs_data_mutex lock is currently used in two places. First, cpufreq_governor_dbs() uses it to guarantee mutual exclusion between invocations of governor operations from the core. Second, it is used by ondemand governor's update_sampling_rate() to ensure the stability of data structures walked by it. The second usage is quite problematic, because update_sampling_rate() is called from a governor sysfs attribute's ->store callback and that leads to a deadlock scenario involving cpufreq_governor_exit() which runs under dbs_data_mutex. Thus it is better to rework the code so update_sampling_rate() doesn't need to acquire dbs_data_mutex. To that end, rework update_sampling_rate() to walk a list of policy_dbs objects supported by the dbs_data one it has been called for (instead of walking cpu_dbs_info object for all CPUs). The list manipulation is protected with dbs_data->mutex which also is held around the execution of update_sampling_rate(), it is not necessary to hold dbs_data_mutex in that function any more. Reported-by: Juri Lelli <juri.lelli@arm.com> Reported-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> [ rjw: Subject & changelog ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq_governor.h')
-rw-r--r--drivers/cpufreq/cpufreq_governor.h7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 0eb66a6c9503..8bf4775ce03c 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -73,7 +73,11 @@ struct dbs_data {
unsigned int up_threshold;
struct kobject kobj;
- /* Protect concurrent updates to governor tunables from sysfs */
+ struct list_head policy_dbs_list;
+ /*
+ * Protect concurrent updates to governor tunables from sysfs,
+ * policy_dbs_list and usage_count.
+ */
struct mutex mutex;
};
@@ -125,6 +129,7 @@ struct policy_dbs_info {
struct work_struct work;
/* dbs_data may be shared between multiple policy objects */
struct dbs_data *dbs_data;
+ struct list_head list;
};
static inline void gov_update_sample_delay(struct policy_dbs_info *policy_dbs,