aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/power_supply_core.c38
-rw-r--r--include/linux/power_supply.h3
2 files changed, 35 insertions, 6 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 3b2d5df45e7a..00e667296360 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -67,23 +67,42 @@ static int __power_supply_changed_work(struct device *dev, void *data)
67 67
68static void power_supply_changed_work(struct work_struct *work) 68static void power_supply_changed_work(struct work_struct *work)
69{ 69{
70 unsigned long flags;
70 struct power_supply *psy = container_of(work, struct power_supply, 71 struct power_supply *psy = container_of(work, struct power_supply,
71 changed_work); 72 changed_work);
72 73
73 dev_dbg(psy->dev, "%s\n", __func__); 74 dev_dbg(psy->dev, "%s\n", __func__);
74 75
75 class_for_each_device(power_supply_class, NULL, psy, 76 spin_lock_irqsave(&psy->changed_lock, flags);
76 __power_supply_changed_work); 77 if (psy->changed) {
77 78 psy->changed = false;
78 power_supply_update_leds(psy); 79 spin_unlock_irqrestore(&psy->changed_lock, flags);
79 80 class_for_each_device(power_supply_class, NULL, psy,
80 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); 81 __power_supply_changed_work);
82 power_supply_update_leds(psy);
83 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
84 spin_lock_irqsave(&psy->changed_lock, flags);
85 }
86 /*
87 * Dependent power supplies (e.g. battery) may have changed state
88 * as a result of this event, so poll again and hold the
89 * wakeup_source until all events are processed.
90 */
91 if (!psy->changed)
92 pm_relax(psy->dev);
93 spin_unlock_irqrestore(&psy->changed_lock, flags);
81} 94}
82 95
83void power_supply_changed(struct power_supply *psy) 96void power_supply_changed(struct power_supply *psy)
84{ 97{
98 unsigned long flags;
99
85 dev_dbg(psy->dev, "%s\n", __func__); 100 dev_dbg(psy->dev, "%s\n", __func__);
86 101
102 spin_lock_irqsave(&psy->changed_lock, flags);
103 psy->changed = true;
104 pm_stay_awake(psy->dev);
105 spin_unlock_irqrestore(&psy->changed_lock, flags);
87 schedule_work(&psy->changed_work); 106 schedule_work(&psy->changed_work);
88} 107}
89EXPORT_SYMBOL_GPL(power_supply_changed); 108EXPORT_SYMBOL_GPL(power_supply_changed);
@@ -500,6 +519,11 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
500 goto check_supplies_failed; 519 goto check_supplies_failed;
501 } 520 }
502 521
522 spin_lock_init(&psy->changed_lock);
523 rc = device_init_wakeup(dev, true);
524 if (rc)
525 goto wakeup_init_failed;
526
503 rc = kobject_set_name(&dev->kobj, "%s", psy->name); 527 rc = kobject_set_name(&dev->kobj, "%s", psy->name);
504 if (rc) 528 if (rc)
505 goto kobject_set_name_failed; 529 goto kobject_set_name_failed;
@@ -529,6 +553,7 @@ create_triggers_failed:
529register_cooler_failed: 553register_cooler_failed:
530 psy_unregister_thermal(psy); 554 psy_unregister_thermal(psy);
531register_thermal_failed: 555register_thermal_failed:
556wakeup_init_failed:
532 device_del(dev); 557 device_del(dev);
533kobject_set_name_failed: 558kobject_set_name_failed:
534device_add_failed: 559device_add_failed:
@@ -546,6 +571,7 @@ void power_supply_unregister(struct power_supply *psy)
546 power_supply_remove_triggers(psy); 571 power_supply_remove_triggers(psy);
547 psy_unregister_cooler(psy); 572 psy_unregister_cooler(psy);
548 psy_unregister_thermal(psy); 573 psy_unregister_thermal(psy);
574 device_init_wakeup(psy->dev, false);
549 device_unregister(psy->dev); 575 device_unregister(psy->dev);
550} 576}
551EXPORT_SYMBOL_GPL(power_supply_unregister); 577EXPORT_SYMBOL_GPL(power_supply_unregister);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 804b90643a85..5c2600630dc9 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -15,6 +15,7 @@
15 15
16#include <linux/workqueue.h> 16#include <linux/workqueue.h>
17#include <linux/leds.h> 17#include <linux/leds.h>
18#include <linux/spinlock.h>
18 19
19struct device; 20struct device;
20 21
@@ -194,6 +195,8 @@ struct power_supply {
194 /* private */ 195 /* private */
195 struct device *dev; 196 struct device *dev;
196 struct work_struct changed_work; 197 struct work_struct changed_work;
198 spinlock_t changed_lock;
199 bool changed;
197#ifdef CONFIG_THERMAL 200#ifdef CONFIG_THERMAL
198 struct thermal_zone_device *tzd; 201 struct thermal_zone_device *tzd;
199 struct thermal_cooling_device *tcd; 202 struct thermal_cooling_device *tcd;