aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-12-29 15:23:13 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-12-29 15:23:13 -0500
commite0288b0e9e2a5dbad612ef6c7dba1f9b52cef27f (patch)
tree1e7aad545ee41ff93d724930f2ed57bdaa5993d4
parentb7392d2247cfe6771f95d256374f1a8e6a6f48d6 (diff)
parentb4718c02f49ab5e1452353f0fae78beabe81467c (diff)
Merge branch 'pm-opp'
* pm-opp: PM / OPP: take RCU lock in dev_pm_opp_get_opp_count PM / OPP: fix warning in of_free_opp_table() PM / OPP: add some lockdep annotations
-rw-r--r--drivers/base/power/opp.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index d24dd614a0bd..106c69359306 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -108,6 +108,14 @@ static LIST_HEAD(dev_opp_list);
108/* Lock to allow exclusive modification to the device and opp lists */ 108/* Lock to allow exclusive modification to the device and opp lists */
109static DEFINE_MUTEX(dev_opp_list_lock); 109static DEFINE_MUTEX(dev_opp_list_lock);
110 110
111#define opp_rcu_lockdep_assert() \
112do { \
113 rcu_lockdep_assert(rcu_read_lock_held() || \
114 lockdep_is_held(&dev_opp_list_lock), \
115 "Missing rcu_read_lock() or " \
116 "dev_opp_list_lock protection"); \
117} while (0)
118
111/** 119/**
112 * find_device_opp() - find device_opp struct using device pointer 120 * find_device_opp() - find device_opp struct using device pointer
113 * @dev: device pointer used to lookup device OPPs 121 * @dev: device pointer used to lookup device OPPs
@@ -208,9 +216,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
208 * This function returns the number of available opps if there are any, 216 * This function returns the number of available opps if there are any,
209 * else returns 0 if none or the corresponding error value. 217 * else returns 0 if none or the corresponding error value.
210 * 218 *
211 * Locking: This function must be called under rcu_read_lock(). This function 219 * Locking: This function takes rcu_read_lock().
212 * internally references two RCU protected structures: device_opp and opp which
213 * are safe as long as we are under a common RCU locked section.
214 */ 220 */
215int dev_pm_opp_get_opp_count(struct device *dev) 221int dev_pm_opp_get_opp_count(struct device *dev)
216{ 222{
@@ -218,11 +224,14 @@ int dev_pm_opp_get_opp_count(struct device *dev)
218 struct dev_pm_opp *temp_opp; 224 struct dev_pm_opp *temp_opp;
219 int count = 0; 225 int count = 0;
220 226
227 rcu_read_lock();
228
221 dev_opp = find_device_opp(dev); 229 dev_opp = find_device_opp(dev);
222 if (IS_ERR(dev_opp)) { 230 if (IS_ERR(dev_opp)) {
223 int r = PTR_ERR(dev_opp); 231 count = PTR_ERR(dev_opp);
224 dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r); 232 dev_err(dev, "%s: device OPP not found (%d)\n",
225 return r; 233 __func__, count);
234 goto out_unlock;
226 } 235 }
227 236
228 list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) { 237 list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
@@ -230,6 +239,8 @@ int dev_pm_opp_get_opp_count(struct device *dev)
230 count++; 239 count++;
231 } 240 }
232 241
242out_unlock:
243 rcu_read_unlock();
233 return count; 244 return count;
234} 245}
235EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); 246EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
@@ -267,6 +278,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
267 struct device_opp *dev_opp; 278 struct device_opp *dev_opp;
268 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 279 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
269 280
281 opp_rcu_lockdep_assert();
282
270 dev_opp = find_device_opp(dev); 283 dev_opp = find_device_opp(dev);
271 if (IS_ERR(dev_opp)) { 284 if (IS_ERR(dev_opp)) {
272 int r = PTR_ERR(dev_opp); 285 int r = PTR_ERR(dev_opp);
@@ -313,6 +326,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
313 struct device_opp *dev_opp; 326 struct device_opp *dev_opp;
314 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 327 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
315 328
329 opp_rcu_lockdep_assert();
330
316 if (!dev || !freq) { 331 if (!dev || !freq) {
317 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); 332 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
318 return ERR_PTR(-EINVAL); 333 return ERR_PTR(-EINVAL);
@@ -361,6 +376,8 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
361 struct device_opp *dev_opp; 376 struct device_opp *dev_opp;
362 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 377 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
363 378
379 opp_rcu_lockdep_assert();
380
364 if (!dev || !freq) { 381 if (!dev || !freq) {
365 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq); 382 dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
366 return ERR_PTR(-EINVAL); 383 return ERR_PTR(-EINVAL);
@@ -783,9 +800,15 @@ void of_free_opp_table(struct device *dev)
783 800
784 /* Check for existing list for 'dev' */ 801 /* Check for existing list for 'dev' */
785 dev_opp = find_device_opp(dev); 802 dev_opp = find_device_opp(dev);
786 if (WARN(IS_ERR(dev_opp), "%s: dev_opp: %ld\n", dev_name(dev), 803 if (IS_ERR(dev_opp)) {
787 PTR_ERR(dev_opp))) 804 int error = PTR_ERR(dev_opp);
805 if (error != -ENODEV)
806 WARN(1, "%s: dev_opp: %d\n",
807 IS_ERR_OR_NULL(dev) ?
808 "Invalid device" : dev_name(dev),
809 error);
788 return; 810 return;
811 }
789 812
790 /* Hold our list modification lock here */ 813 /* Hold our list modification lock here */
791 mutex_lock(&dev_opp_list_lock); 814 mutex_lock(&dev_opp_list_lock);