aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/power_supply_core.c
diff options
context:
space:
mode:
authorAnton Vorontsov <cbouatmailru@gmail.com>2010-05-18 15:49:51 -0400
committerAnton Vorontsov <cbouatmailru@gmail.com>2010-05-19 04:14:28 -0400
commit5f487cd34f4337f9bc27ca19da72a39d1b0a0ab4 (patch)
treef3204e0cf64a7202c42d1f397fd978ccd61f8225 /drivers/power/power_supply_core.c
parenta1e50fd4452b2ed57376ece465a17276b59fad9c (diff)
power_supply: Use attribute groups
This fixes a race between power supply device and initial attributes creation, plus makes it possible to implement writable properties. [Daniel Mack - removed superflous return statement and dropped .mode attribute from POWER_SUPPLY_ATTR] Suggested-by: Greg KH <gregkh@suse.de> Suggested-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com> Tested-by: Daniel Mack <daniel@caiaq.de>
Diffstat (limited to 'drivers/power/power_supply_core.c')
-rw-r--r--drivers/power/power_supply_core.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index cce75b40b435..91606bb55318 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/slab.h>
16#include <linux/device.h> 17#include <linux/device.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <linux/power_supply.h> 19#include <linux/power_supply.h>
@@ -22,6 +23,8 @@
22struct class *power_supply_class; 23struct class *power_supply_class;
23EXPORT_SYMBOL_GPL(power_supply_class); 24EXPORT_SYMBOL_GPL(power_supply_class);
24 25
26static struct device_type power_supply_dev_type;
27
25static int __power_supply_changed_work(struct device *dev, void *data) 28static int __power_supply_changed_work(struct device *dev, void *data)
26{ 29{
27 struct power_supply *psy = (struct power_supply *)data; 30 struct power_supply *psy = (struct power_supply *)data;
@@ -144,22 +147,39 @@ struct power_supply *power_supply_get_by_name(char *name)
144} 147}
145EXPORT_SYMBOL_GPL(power_supply_get_by_name); 148EXPORT_SYMBOL_GPL(power_supply_get_by_name);
146 149
150static void power_supply_dev_release(struct device *dev)
151{
152 pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
153 kfree(dev);
154}
155
147int power_supply_register(struct device *parent, struct power_supply *psy) 156int power_supply_register(struct device *parent, struct power_supply *psy)
148{ 157{
149 int rc = 0; 158 struct device *dev;
159 int rc;
150 160
151 psy->dev = device_create(power_supply_class, parent, 0, psy, 161 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
152 "%s", psy->name); 162 if (!dev)
153 if (IS_ERR(psy->dev)) { 163 return -ENOMEM;
154 rc = PTR_ERR(psy->dev);
155 goto dev_create_failed;
156 }
157 164
158 INIT_WORK(&psy->changed_work, power_supply_changed_work); 165 device_initialize(dev);
159 166
160 rc = power_supply_create_attrs(psy); 167 dev->class = power_supply_class;
168 dev->type = &power_supply_dev_type;
169 dev->parent = parent;
170 dev->release = power_supply_dev_release;
171 dev_set_drvdata(dev, psy);
172 psy->dev = dev;
173
174 rc = kobject_set_name(&dev->kobj, "%s", psy->name);
175 if (rc)
176 goto kobject_set_name_failed;
177
178 rc = device_add(dev);
161 if (rc) 179 if (rc)
162 goto create_attrs_failed; 180 goto device_add_failed;
181
182 INIT_WORK(&psy->changed_work, power_supply_changed_work);
163 183
164 rc = power_supply_create_triggers(psy); 184 rc = power_supply_create_triggers(psy);
165 if (rc) 185 if (rc)
@@ -170,10 +190,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy)
170 goto success; 190 goto success;
171 191
172create_triggers_failed: 192create_triggers_failed:
173 power_supply_remove_attrs(psy);
174create_attrs_failed:
175 device_unregister(psy->dev); 193 device_unregister(psy->dev);
176dev_create_failed: 194kobject_set_name_failed:
195device_add_failed:
196 kfree(dev);
177success: 197success:
178 return rc; 198 return rc;
179} 199}
@@ -183,7 +203,6 @@ void power_supply_unregister(struct power_supply *psy)
183{ 203{
184 flush_scheduled_work(); 204 flush_scheduled_work();
185 power_supply_remove_triggers(psy); 205 power_supply_remove_triggers(psy);
186 power_supply_remove_attrs(psy);
187 device_unregister(psy->dev); 206 device_unregister(psy->dev);
188} 207}
189EXPORT_SYMBOL_GPL(power_supply_unregister); 208EXPORT_SYMBOL_GPL(power_supply_unregister);
@@ -196,6 +215,7 @@ static int __init power_supply_class_init(void)
196 return PTR_ERR(power_supply_class); 215 return PTR_ERR(power_supply_class);
197 216
198 power_supply_class->dev_uevent = power_supply_uevent; 217 power_supply_class->dev_uevent = power_supply_uevent;
218 power_supply_init_attrs(&power_supply_dev_type);
199 219
200 return 0; 220 return 0;
201} 221}