aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2017-01-22 23:41:48 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-01-30 03:22:22 -0500
commit5b650b388844f26c61c70564865598836d05dcb3 (patch)
tree93ae6faaad201381793f8322b6d9c227e2c489b0 /drivers/base
parent8a31d9d94297b1ecae3012069d35d78c959693c2 (diff)
PM / OPP: Take kref from _find_opp_table()
Take reference of the OPP table from within _find_opp_table(). Also update the callers of _find_opp_table() to call dev_pm_opp_put_opp_table() after they have used the OPP table. Note that _find_opp_table() increments the reference under the opp_table_lock. Now that the OPP table wouldn't get freed until the callers of _find_opp_table() call dev_pm_opp_put_opp_table(), there is no need to take the opp_table_lock or rcu_read_lock() around it. Drop them. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/opp/core.c191
-rw-r--r--drivers/base/power/opp/cpu.c26
2 files changed, 95 insertions, 122 deletions
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index a6efa818029a..69452a4bcda7 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -54,6 +54,21 @@ static struct opp_device *_find_opp_dev(const struct device *dev,
54 return NULL; 54 return NULL;
55} 55}
56 56
57struct opp_table *_find_opp_table_unlocked(struct device *dev)
58{
59 struct opp_table *opp_table;
60
61 list_for_each_entry(opp_table, &opp_tables, node) {
62 if (_find_opp_dev(dev, opp_table)) {
63 _get_opp_table_kref(opp_table);
64
65 return opp_table;
66 }
67 }
68
69 return ERR_PTR(-ENODEV);
70}
71
57/** 72/**
58 * _find_opp_table() - find opp_table struct using device pointer 73 * _find_opp_table() - find opp_table struct using device pointer
59 * @dev: device pointer used to lookup OPP table 74 * @dev: device pointer used to lookup OPP table
@@ -64,28 +79,22 @@ static struct opp_device *_find_opp_dev(const struct device *dev,
64 * Return: pointer to 'struct opp_table' if found, otherwise -ENODEV or 79 * Return: pointer to 'struct opp_table' if found, otherwise -ENODEV or
65 * -EINVAL based on type of error. 80 * -EINVAL based on type of error.
66 * 81 *
67 * Locking: For readers, this function must be called under rcu_read_lock(). 82 * The callers must call dev_pm_opp_put_opp_table() after the table is used.
68 * opp_table is a RCU protected pointer, which means that opp_table is valid
69 * as long as we are under RCU lock.
70 *
71 * For Writers, this function must be called with opp_table_lock held.
72 */ 83 */
73struct opp_table *_find_opp_table(struct device *dev) 84struct opp_table *_find_opp_table(struct device *dev)
74{ 85{
75 struct opp_table *opp_table; 86 struct opp_table *opp_table;
76 87
77 opp_rcu_lockdep_assert();
78
79 if (IS_ERR_OR_NULL(dev)) { 88 if (IS_ERR_OR_NULL(dev)) {
80 pr_err("%s: Invalid parameters\n", __func__); 89 pr_err("%s: Invalid parameters\n", __func__);
81 return ERR_PTR(-EINVAL); 90 return ERR_PTR(-EINVAL);
82 } 91 }
83 92
84 list_for_each_entry_rcu(opp_table, &opp_tables, node) 93 mutex_lock(&opp_table_lock);
85 if (_find_opp_dev(dev, opp_table)) 94 opp_table = _find_opp_table_unlocked(dev);
86 return opp_table; 95 mutex_unlock(&opp_table_lock);
87 96
88 return ERR_PTR(-ENODEV); 97 return opp_table;
89} 98}
90 99
91/** 100/**
@@ -175,23 +184,20 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
175 * @dev: device for which we do this operation 184 * @dev: device for which we do this operation
176 * 185 *
177 * Return: This function returns the max clock latency in nanoseconds. 186 * Return: This function returns the max clock latency in nanoseconds.
178 *
179 * Locking: This function takes rcu_read_lock().
180 */ 187 */
181unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev) 188unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
182{ 189{
183 struct opp_table *opp_table; 190 struct opp_table *opp_table;
184 unsigned long clock_latency_ns; 191 unsigned long clock_latency_ns;
185 192
186 rcu_read_lock();
187
188 opp_table = _find_opp_table(dev); 193 opp_table = _find_opp_table(dev);
189 if (IS_ERR(opp_table)) 194 if (IS_ERR(opp_table))
190 clock_latency_ns = 0; 195 return 0;
191 else 196
192 clock_latency_ns = opp_table->clock_latency_ns_max; 197 clock_latency_ns = opp_table->clock_latency_ns_max;
198
199 dev_pm_opp_put_opp_table(opp_table);
193 200
194 rcu_read_unlock();
195 return clock_latency_ns; 201 return clock_latency_ns;
196} 202}
197EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); 203EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
@@ -201,15 +207,13 @@ static int _get_regulator_count(struct device *dev)
201 struct opp_table *opp_table; 207 struct opp_table *opp_table;
202 int count; 208 int count;
203 209
204 rcu_read_lock();
205
206 opp_table = _find_opp_table(dev); 210 opp_table = _find_opp_table(dev);
207 if (!IS_ERR(opp_table)) 211 if (IS_ERR(opp_table))
208 count = opp_table->regulator_count; 212 return 0;
209 else
210 count = 0;
211 213
212 rcu_read_unlock(); 214 count = opp_table->regulator_count;
215
216 dev_pm_opp_put_opp_table(opp_table);
213 217
214 return count; 218 return count;
215} 219}
@@ -248,13 +252,11 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
248 if (!uV) 252 if (!uV)
249 goto free_regulators; 253 goto free_regulators;
250 254
251 rcu_read_lock();
252
253 opp_table = _find_opp_table(dev); 255 opp_table = _find_opp_table(dev);
254 if (IS_ERR(opp_table)) { 256 if (IS_ERR(opp_table))
255 rcu_read_unlock();
256 goto free_uV; 257 goto free_uV;
257 } 258
259 rcu_read_lock();
258 260
259 memcpy(regulators, opp_table->regulators, count * sizeof(*regulators)); 261 memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
260 262
@@ -274,6 +276,7 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
274 } 276 }
275 277
276 rcu_read_unlock(); 278 rcu_read_unlock();
279 dev_pm_opp_put_opp_table(opp_table);
277 280
278 /* 281 /*
279 * The caller needs to ensure that opp_table (and hence the regulator) 282 * The caller needs to ensure that opp_table (and hence the regulator)
@@ -323,17 +326,15 @@ unsigned long dev_pm_opp_get_suspend_opp_freq(struct device *dev)
323 struct opp_table *opp_table; 326 struct opp_table *opp_table;
324 unsigned long freq = 0; 327 unsigned long freq = 0;
325 328
326 rcu_read_lock();
327
328 opp_table = _find_opp_table(dev); 329 opp_table = _find_opp_table(dev);
329 if (IS_ERR(opp_table) || !opp_table->suspend_opp || 330 if (IS_ERR(opp_table))
330 !opp_table->suspend_opp->available) 331 return 0;
331 goto unlock;
332 332
333 freq = dev_pm_opp_get_freq(opp_table->suspend_opp); 333 if (opp_table->suspend_opp && opp_table->suspend_opp->available)
334 freq = dev_pm_opp_get_freq(opp_table->suspend_opp);
335
336 dev_pm_opp_put_opp_table(opp_table);
334 337
335unlock:
336 rcu_read_unlock();
337 return freq; 338 return freq;
338} 339}
339EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq); 340EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp_freq);
@@ -353,23 +354,24 @@ int dev_pm_opp_get_opp_count(struct device *dev)
353 struct dev_pm_opp *temp_opp; 354 struct dev_pm_opp *temp_opp;
354 int count = 0; 355 int count = 0;
355 356
356 rcu_read_lock();
357
358 opp_table = _find_opp_table(dev); 357 opp_table = _find_opp_table(dev);
359 if (IS_ERR(opp_table)) { 358 if (IS_ERR(opp_table)) {
360 count = PTR_ERR(opp_table); 359 count = PTR_ERR(opp_table);
361 dev_err(dev, "%s: OPP table not found (%d)\n", 360 dev_err(dev, "%s: OPP table not found (%d)\n",
362 __func__, count); 361 __func__, count);
363 goto out_unlock; 362 return count;
364 } 363 }
365 364
365 rcu_read_lock();
366
366 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) { 367 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
367 if (temp_opp->available) 368 if (temp_opp->available)
368 count++; 369 count++;
369 } 370 }
370 371
371out_unlock:
372 rcu_read_unlock(); 372 rcu_read_unlock();
373 dev_pm_opp_put_opp_table(opp_table);
374
373 return count; 375 return count;
374} 376}
375EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); 377EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
@@ -404,17 +406,16 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
404 struct opp_table *opp_table; 406 struct opp_table *opp_table;
405 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); 407 struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
406 408
407 rcu_read_lock();
408
409 opp_table = _find_opp_table(dev); 409 opp_table = _find_opp_table(dev);
410 if (IS_ERR(opp_table)) { 410 if (IS_ERR(opp_table)) {
411 int r = PTR_ERR(opp_table); 411 int r = PTR_ERR(opp_table);
412 412
413 dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r); 413 dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r);
414 rcu_read_unlock();
415 return ERR_PTR(r); 414 return ERR_PTR(r);
416 } 415 }
417 416
417 rcu_read_lock();
418
418 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) { 419 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
419 if (temp_opp->available == available && 420 if (temp_opp->available == available &&
420 temp_opp->rate == freq) { 421 temp_opp->rate == freq) {
@@ -427,6 +428,7 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
427 } 428 }
428 429
429 rcu_read_unlock(); 430 rcu_read_unlock();
431 dev_pm_opp_put_opp_table(opp_table);
430 432
431 return opp; 433 return opp;
432} 434}
@@ -480,17 +482,16 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
480 return ERR_PTR(-EINVAL); 482 return ERR_PTR(-EINVAL);
481 } 483 }
482 484
483 rcu_read_lock();
484
485 opp_table = _find_opp_table(dev); 485 opp_table = _find_opp_table(dev);
486 if (IS_ERR(opp_table)) { 486 if (IS_ERR(opp_table))
487 rcu_read_unlock();
488 return ERR_CAST(opp_table); 487 return ERR_CAST(opp_table);
489 } 488
489 rcu_read_lock();
490 490
491 opp = _find_freq_ceil(opp_table, freq); 491 opp = _find_freq_ceil(opp_table, freq);
492 492
493 rcu_read_unlock(); 493 rcu_read_unlock();
494 dev_pm_opp_put_opp_table(opp_table);
494 495
495 return opp; 496 return opp;
496} 497}
@@ -525,13 +526,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
525 return ERR_PTR(-EINVAL); 526 return ERR_PTR(-EINVAL);
526 } 527 }
527 528
528 rcu_read_lock();
529
530 opp_table = _find_opp_table(dev); 529 opp_table = _find_opp_table(dev);
531 if (IS_ERR(opp_table)) { 530 if (IS_ERR(opp_table))
532 rcu_read_unlock();
533 return ERR_CAST(opp_table); 531 return ERR_CAST(opp_table);
534 } 532
533 rcu_read_lock();
535 534
536 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) { 535 list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
537 if (temp_opp->available) { 536 if (temp_opp->available) {
@@ -547,6 +546,7 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
547 if (!IS_ERR(opp)) 546 if (!IS_ERR(opp))
548 dev_pm_opp_get(opp); 547 dev_pm_opp_get(opp);
549 rcu_read_unlock(); 548 rcu_read_unlock();
549 dev_pm_opp_put_opp_table(opp_table);
550 550
551 if (!IS_ERR(opp)) 551 if (!IS_ERR(opp))
552 *freq = opp->rate; 552 *freq = opp->rate;
@@ -564,22 +564,18 @@ static struct clk *_get_opp_clk(struct device *dev)
564 struct opp_table *opp_table; 564 struct opp_table *opp_table;
565 struct clk *clk; 565 struct clk *clk;
566 566
567 rcu_read_lock();
568
569 opp_table = _find_opp_table(dev); 567 opp_table = _find_opp_table(dev);
570 if (IS_ERR(opp_table)) { 568 if (IS_ERR(opp_table)) {
571 dev_err(dev, "%s: device opp doesn't exist\n", __func__); 569 dev_err(dev, "%s: device opp doesn't exist\n", __func__);
572 clk = ERR_CAST(opp_table); 570 return ERR_CAST(opp_table);
573 goto unlock;
574 } 571 }
575 572
576 clk = opp_table->clk; 573 clk = opp_table->clk;
577 if (IS_ERR(clk)) 574 if (IS_ERR(clk))
578 dev_err(dev, "%s: No clock available for the device\n", 575 dev_err(dev, "%s: No clock available for the device\n",
579 __func__); 576 __func__);
577 dev_pm_opp_put_opp_table(opp_table);
580 578
581unlock:
582 rcu_read_unlock();
583 return clk; 579 return clk;
584} 580}
585 581
@@ -715,15 +711,14 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
715 return 0; 711 return 0;
716 } 712 }
717 713
718 rcu_read_lock();
719
720 opp_table = _find_opp_table(dev); 714 opp_table = _find_opp_table(dev);
721 if (IS_ERR(opp_table)) { 715 if (IS_ERR(opp_table)) {
722 dev_err(dev, "%s: device opp doesn't exist\n", __func__); 716 dev_err(dev, "%s: device opp doesn't exist\n", __func__);
723 rcu_read_unlock();
724 return PTR_ERR(opp_table); 717 return PTR_ERR(opp_table);
725 } 718 }
726 719
720 rcu_read_lock();
721
727 old_opp = _find_freq_ceil(opp_table, &old_freq); 722 old_opp = _find_freq_ceil(opp_table, &old_freq);
728 if (IS_ERR(old_opp)) { 723 if (IS_ERR(old_opp)) {
729 dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n", 724 dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
@@ -738,6 +733,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
738 if (!IS_ERR(old_opp)) 733 if (!IS_ERR(old_opp))
739 dev_pm_opp_put(old_opp); 734 dev_pm_opp_put(old_opp);
740 rcu_read_unlock(); 735 rcu_read_unlock();
736 dev_pm_opp_put_opp_table(opp_table);
741 return ret; 737 return ret;
742 } 738 }
743 739
@@ -752,6 +748,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
752 if (!IS_ERR(old_opp)) 748 if (!IS_ERR(old_opp))
753 dev_pm_opp_put(old_opp); 749 dev_pm_opp_put(old_opp);
754 rcu_read_unlock(); 750 rcu_read_unlock();
751 dev_pm_opp_put_opp_table(opp_table);
755 return _generic_set_opp_clk_only(dev, clk, old_freq, freq); 752 return _generic_set_opp_clk_only(dev, clk, old_freq, freq);
756 } 753 }
757 754
@@ -780,6 +777,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
780 if (!IS_ERR(old_opp)) 777 if (!IS_ERR(old_opp))
781 dev_pm_opp_put(old_opp); 778 dev_pm_opp_put(old_opp);
782 rcu_read_unlock(); 779 rcu_read_unlock();
780 dev_pm_opp_put_opp_table(opp_table);
783 781
784 return set_opp(data); 782 return set_opp(data);
785} 783}
@@ -893,11 +891,9 @@ struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
893 /* Hold our table modification lock here */ 891 /* Hold our table modification lock here */
894 mutex_lock(&opp_table_lock); 892 mutex_lock(&opp_table_lock);
895 893
896 opp_table = _find_opp_table(dev); 894 opp_table = _find_opp_table_unlocked(dev);
897 if (!IS_ERR(opp_table)) { 895 if (!IS_ERR(opp_table))
898 _get_opp_table_kref(opp_table);
899 goto unlock; 896 goto unlock;
900 }
901 897
902 opp_table = _allocate_opp_table(dev); 898 opp_table = _allocate_opp_table(dev);
903 899
@@ -1004,12 +1000,9 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
1004 struct opp_table *opp_table; 1000 struct opp_table *opp_table;
1005 bool found = false; 1001 bool found = false;
1006 1002
1007 /* Hold our table modification lock here */
1008 mutex_lock(&opp_table_lock);
1009
1010 opp_table = _find_opp_table(dev); 1003 opp_table = _find_opp_table(dev);
1011 if (IS_ERR(opp_table)) 1004 if (IS_ERR(opp_table))
1012 goto unlock; 1005 return;
1013 1006
1014 mutex_lock(&opp_table->lock); 1007 mutex_lock(&opp_table->lock);
1015 1008
@@ -1022,15 +1015,14 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
1022 1015
1023 mutex_unlock(&opp_table->lock); 1016 mutex_unlock(&opp_table->lock);
1024 1017
1025 if (!found) { 1018 if (found) {
1019 dev_pm_opp_put(opp);
1020 } else {
1026 dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n", 1021 dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
1027 __func__, freq); 1022 __func__, freq);
1028 goto unlock;
1029 } 1023 }
1030 1024
1031 dev_pm_opp_put(opp); 1025 dev_pm_opp_put_opp_table(opp_table);
1032unlock:
1033 mutex_unlock(&opp_table_lock);
1034} 1026}
1035EXPORT_SYMBOL_GPL(dev_pm_opp_remove); 1027EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
1036 1028
@@ -1648,14 +1640,12 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
1648 if (!new_opp) 1640 if (!new_opp)
1649 return -ENOMEM; 1641 return -ENOMEM;
1650 1642
1651 mutex_lock(&opp_table_lock);
1652
1653 /* Find the opp_table */ 1643 /* Find the opp_table */
1654 opp_table = _find_opp_table(dev); 1644 opp_table = _find_opp_table(dev);
1655 if (IS_ERR(opp_table)) { 1645 if (IS_ERR(opp_table)) {
1656 r = PTR_ERR(opp_table); 1646 r = PTR_ERR(opp_table);
1657 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r); 1647 dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
1658 goto unlock; 1648 goto free_opp;
1659 } 1649 }
1660 1650
1661 mutex_lock(&opp_table->lock); 1651 mutex_lock(&opp_table->lock);
@@ -1668,8 +1658,6 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
1668 } 1658 }
1669 } 1659 }
1670 1660
1671 mutex_unlock(&opp_table->lock);
1672
1673 if (IS_ERR(opp)) { 1661 if (IS_ERR(opp)) {
1674 r = PTR_ERR(opp); 1662 r = PTR_ERR(opp);
1675 goto unlock; 1663 goto unlock;
@@ -1685,7 +1673,6 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
1685 new_opp->available = availability_req; 1673 new_opp->available = availability_req;
1686 1674
1687 list_replace_rcu(&opp->node, &new_opp->node); 1675 list_replace_rcu(&opp->node, &new_opp->node);
1688 mutex_unlock(&opp_table_lock);
1689 call_srcu(&opp_table->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu); 1676 call_srcu(&opp_table->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
1690 1677
1691 /* Notify the change of the OPP availability */ 1678 /* Notify the change of the OPP availability */
@@ -1696,10 +1683,14 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
1696 srcu_notifier_call_chain(&opp_table->srcu_head, 1683 srcu_notifier_call_chain(&opp_table->srcu_head,
1697 OPP_EVENT_DISABLE, new_opp); 1684 OPP_EVENT_DISABLE, new_opp);
1698 1685
1686 mutex_unlock(&opp_table->lock);
1687 dev_pm_opp_put_opp_table(opp_table);
1699 return 0; 1688 return 0;
1700 1689
1701unlock: 1690unlock:
1702 mutex_unlock(&opp_table_lock); 1691 mutex_unlock(&opp_table->lock);
1692 dev_pm_opp_put_opp_table(opp_table);
1693free_opp:
1703 kfree(new_opp); 1694 kfree(new_opp);
1704 return r; 1695 return r;
1705} 1696}
@@ -1767,18 +1758,16 @@ int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb)
1767 struct opp_table *opp_table; 1758 struct opp_table *opp_table;
1768 int ret; 1759 int ret;
1769 1760
1770 rcu_read_lock();
1771
1772 opp_table = _find_opp_table(dev); 1761 opp_table = _find_opp_table(dev);
1773 if (IS_ERR(opp_table)) { 1762 if (IS_ERR(opp_table))
1774 ret = PTR_ERR(opp_table); 1763 return PTR_ERR(opp_table);
1775 goto unlock; 1764
1776 } 1765 rcu_read_lock();
1777 1766
1778 ret = srcu_notifier_chain_register(&opp_table->srcu_head, nb); 1767 ret = srcu_notifier_chain_register(&opp_table->srcu_head, nb);
1779 1768
1780unlock:
1781 rcu_read_unlock(); 1769 rcu_read_unlock();
1770 dev_pm_opp_put_opp_table(opp_table);
1782 1771
1783 return ret; 1772 return ret;
1784} 1773}
@@ -1797,18 +1786,14 @@ int dev_pm_opp_unregister_notifier(struct device *dev,
1797 struct opp_table *opp_table; 1786 struct opp_table *opp_table;
1798 int ret; 1787 int ret;
1799 1788
1800 rcu_read_lock();
1801
1802 opp_table = _find_opp_table(dev); 1789 opp_table = _find_opp_table(dev);
1803 if (IS_ERR(opp_table)) { 1790 if (IS_ERR(opp_table))
1804 ret = PTR_ERR(opp_table); 1791 return PTR_ERR(opp_table);
1805 goto unlock;
1806 }
1807 1792
1808 ret = srcu_notifier_chain_unregister(&opp_table->srcu_head, nb); 1793 ret = srcu_notifier_chain_unregister(&opp_table->srcu_head, nb);
1809 1794
1810unlock:
1811 rcu_read_unlock(); 1795 rcu_read_unlock();
1796 dev_pm_opp_put_opp_table(opp_table);
1812 1797
1813 return ret; 1798 return ret;
1814} 1799}
@@ -1839,9 +1824,6 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all)
1839{ 1824{
1840 struct opp_table *opp_table; 1825 struct opp_table *opp_table;
1841 1826
1842 /* Hold our table modification lock here */
1843 mutex_lock(&opp_table_lock);
1844
1845 /* Check for existing table for 'dev' */ 1827 /* Check for existing table for 'dev' */
1846 opp_table = _find_opp_table(dev); 1828 opp_table = _find_opp_table(dev);
1847 if (IS_ERR(opp_table)) { 1829 if (IS_ERR(opp_table)) {
@@ -1852,13 +1834,12 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all)
1852 IS_ERR_OR_NULL(dev) ? 1834 IS_ERR_OR_NULL(dev) ?
1853 "Invalid device" : dev_name(dev), 1835 "Invalid device" : dev_name(dev),
1854 error); 1836 error);
1855 goto unlock; 1837 return;
1856 } 1838 }
1857 1839
1858 _dev_pm_opp_remove_table(opp_table, dev, remove_all); 1840 _dev_pm_opp_remove_table(opp_table, dev, remove_all);
1859 1841
1860unlock: 1842 dev_pm_opp_put_opp_table(opp_table);
1861 mutex_unlock(&opp_table_lock);
1862} 1843}
1863 1844
1864/** 1845/**
diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c
index adef788862d5..df29f08eecc4 100644
--- a/drivers/base/power/opp/cpu.c
+++ b/drivers/base/power/opp/cpu.c
@@ -174,13 +174,9 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
174 struct device *dev; 174 struct device *dev;
175 int cpu, ret = 0; 175 int cpu, ret = 0;
176 176
177 mutex_lock(&opp_table_lock);
178
179 opp_table = _find_opp_table(cpu_dev); 177 opp_table = _find_opp_table(cpu_dev);
180 if (IS_ERR(opp_table)) { 178 if (IS_ERR(opp_table))
181 ret = PTR_ERR(opp_table); 179 return PTR_ERR(opp_table);
182 goto unlock;
183 }
184 180
185 for_each_cpu(cpu, cpumask) { 181 for_each_cpu(cpu, cpumask) {
186 if (cpu == cpu_dev->id) 182 if (cpu == cpu_dev->id)
@@ -203,8 +199,8 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
203 /* Mark opp-table as multiple CPUs are sharing it now */ 199 /* Mark opp-table as multiple CPUs are sharing it now */
204 opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED; 200 opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
205 } 201 }
206unlock: 202
207 mutex_unlock(&opp_table_lock); 203 dev_pm_opp_put_opp_table(opp_table);
208 204
209 return ret; 205 return ret;
210} 206}
@@ -232,17 +228,13 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
232 struct opp_table *opp_table; 228 struct opp_table *opp_table;
233 int ret = 0; 229 int ret = 0;
234 230
235 mutex_lock(&opp_table_lock);
236
237 opp_table = _find_opp_table(cpu_dev); 231 opp_table = _find_opp_table(cpu_dev);
238 if (IS_ERR(opp_table)) { 232 if (IS_ERR(opp_table))
239 ret = PTR_ERR(opp_table); 233 return PTR_ERR(opp_table);
240 goto unlock;
241 }
242 234
243 if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) { 235 if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) {
244 ret = -EINVAL; 236 ret = -EINVAL;
245 goto unlock; 237 goto put_opp_table;
246 } 238 }
247 239
248 cpumask_clear(cpumask); 240 cpumask_clear(cpumask);
@@ -254,8 +246,8 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
254 cpumask_set_cpu(cpu_dev->id, cpumask); 246 cpumask_set_cpu(cpu_dev->id, cpumask);
255 } 247 }
256 248
257unlock: 249put_opp_table:
258 mutex_unlock(&opp_table_lock); 250 dev_pm_opp_put_opp_table(opp_table);
259 251
260 return ret; 252 return ret;
261} 253}