diff options
author | Anton Vorontsov <cbouatmailru@gmail.com> | 2010-05-18 15:49:51 -0400 |
---|---|---|
committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2010-05-19 04:14:28 -0400 |
commit | 5f487cd34f4337f9bc27ca19da72a39d1b0a0ab4 (patch) | |
tree | f3204e0cf64a7202c42d1f397fd978ccd61f8225 /drivers/power/power_supply_core.c | |
parent | a1e50fd4452b2ed57376ece465a17276b59fad9c (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.c | 48 |
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 @@ | |||
22 | struct class *power_supply_class; | 23 | struct class *power_supply_class; |
23 | EXPORT_SYMBOL_GPL(power_supply_class); | 24 | EXPORT_SYMBOL_GPL(power_supply_class); |
24 | 25 | ||
26 | static struct device_type power_supply_dev_type; | ||
27 | |||
25 | static int __power_supply_changed_work(struct device *dev, void *data) | 28 | static 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 | } |
145 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); | 148 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); |
146 | 149 | ||
150 | static 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 | |||
147 | int power_supply_register(struct device *parent, struct power_supply *psy) | 156 | int 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 | ||
172 | create_triggers_failed: | 192 | create_triggers_failed: |
173 | power_supply_remove_attrs(psy); | ||
174 | create_attrs_failed: | ||
175 | device_unregister(psy->dev); | 193 | device_unregister(psy->dev); |
176 | dev_create_failed: | 194 | kobject_set_name_failed: |
195 | device_add_failed: | ||
196 | kfree(dev); | ||
177 | success: | 197 | success: |
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 | } |
189 | EXPORT_SYMBOL_GPL(power_supply_unregister); | 208 | EXPORT_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 | } |