aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorChander Kashyap <k.chander@samsung.com>2014-05-22 01:06:26 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-05-26 18:50:26 -0400
commit64ce854578de82e9e16280298562721ced971668 (patch)
tree29c2b8582a71ecdcfc2b2fe64fb26eb61608408a /drivers/base
parent049d595a4db3b3a20fc252298010f0545ef659a3 (diff)
PM / OPP: discard duplicate OPPs
We don't have any protection against addition of duplicate OPPs currently and in case some code tries to add them, it will end up corrupting OPP tables. We need to handle some duplication cases separately as returning error might not be the right thing always. The new list of return values for dev_pm_opp_add() are: 0: On success OR Duplicate OPPs (both freq and volt are same) and opp->available -EEXIST: Freq are same and volt are different OR Duplicate OPPs (both freq and volt are same) and !opp->available -ENOMEM: Memory allocation failure Acked-by: Nishanth Menon <nm@ti.com> Signed-off-by: Chander Kashyap <k.chander@samsung.com> Signed-off-by: Inderpal Singh <inderpal.s@samsung.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/opp.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index c539d70b97ab..39412c15db70 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -394,6 +394,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
394 * to keep the integrity of the internal data structures. Callers should ensure 394 * to keep the integrity of the internal data structures. Callers should ensure
395 * that this function is *NOT* called under RCU protection or in contexts where 395 * that this function is *NOT* called under RCU protection or in contexts where
396 * mutex cannot be locked. 396 * mutex cannot be locked.
397 *
398 * Return:
399 * 0: On success OR
400 * Duplicate OPPs (both freq and volt are same) and opp->available
401 * -EEXIST: Freq are same and volt are different OR
402 * Duplicate OPPs (both freq and volt are same) and !opp->available
403 * -ENOMEM: Memory allocation failure
397 */ 404 */
398int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) 405int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
399{ 406{
@@ -443,15 +450,31 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
443 new_opp->u_volt = u_volt; 450 new_opp->u_volt = u_volt;
444 new_opp->available = true; 451 new_opp->available = true;
445 452
446 /* Insert new OPP in order of increasing frequency */ 453 /*
454 * Insert new OPP in order of increasing frequency
455 * and discard if already present
456 */
447 head = &dev_opp->opp_list; 457 head = &dev_opp->opp_list;
448 list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) { 458 list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
449 if (new_opp->rate < opp->rate) 459 if (new_opp->rate <= opp->rate)
450 break; 460 break;
451 else 461 else
452 head = &opp->node; 462 head = &opp->node;
453 } 463 }
454 464
465 /* Duplicate OPPs ? */
466 if (new_opp->rate == opp->rate) {
467 int ret = opp->available && new_opp->u_volt == opp->u_volt ?
468 0 : -EEXIST;
469
470 dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
471 __func__, opp->rate, opp->u_volt, opp->available,
472 new_opp->rate, new_opp->u_volt, new_opp->available);
473 mutex_unlock(&dev_opp_list_lock);
474 kfree(new_opp);
475 return ret;
476 }
477
455 list_add_rcu(&new_opp->node, head); 478 list_add_rcu(&new_opp->node, head);
456 mutex_unlock(&dev_opp_list_lock); 479 mutex_unlock(&dev_opp_list_lock);
457 480