aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/power_supply_core.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index bcff7fdf733a..26518c8218ea 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -78,7 +78,14 @@ static void power_supply_changed_work(struct work_struct *work)
78 dev_dbg(psy->dev, "%s\n", __func__); 78 dev_dbg(psy->dev, "%s\n", __func__);
79 79
80 spin_lock_irqsave(&psy->changed_lock, flags); 80 spin_lock_irqsave(&psy->changed_lock, flags);
81 if (psy->changed) { 81 /*
82 * Check 'changed' here to avoid issues due to race between
83 * power_supply_changed() and this routine. In worst case
84 * power_supply_changed() can be called again just before we take above
85 * lock. During the first call of this routine we will mark 'changed' as
86 * false and it will stay false for the next call as well.
87 */
88 if (likely(psy->changed)) {
82 psy->changed = false; 89 psy->changed = false;
83 spin_unlock_irqrestore(&psy->changed_lock, flags); 90 spin_unlock_irqrestore(&psy->changed_lock, flags);
84 class_for_each_device(power_supply_class, NULL, psy, 91 class_for_each_device(power_supply_class, NULL, psy,
@@ -89,12 +96,13 @@ static void power_supply_changed_work(struct work_struct *work)
89 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); 96 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
90 spin_lock_irqsave(&psy->changed_lock, flags); 97 spin_lock_irqsave(&psy->changed_lock, flags);
91 } 98 }
99
92 /* 100 /*
93 * Dependent power supplies (e.g. battery) may have changed state 101 * Hold the wakeup_source until all events are processed.
94 * as a result of this event, so poll again and hold the 102 * power_supply_changed() might have called again and have set 'changed'
95 * wakeup_source until all events are processed. 103 * to true.
96 */ 104 */
97 if (!psy->changed) 105 if (likely(!psy->changed))
98 pm_relax(psy->dev); 106 pm_relax(psy->dev);
99 spin_unlock_irqrestore(&psy->changed_lock, flags); 107 spin_unlock_irqrestore(&psy->changed_lock, flags);
100} 108}