aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-03-10 01:37:34 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-04-27 13:57:28 -0400
commit621a1672f7377e08a942f205d6742d8af1292aab (patch)
tree9249308b3df0675f713058e3f5ac0442ce2a5e1e
parentb8c5cec23d5c33b767a1cddebd4f8813a9563e3c (diff)
driver core: Use attribute groups in struct device_type
Driver core: use attribute groups in struct device_type Attribute groups are more flexible than attribute lists (an attribute list can be represented by anonymous group) so switch struct device_type to use them. Also rework attribute creation for devices so that they all cleaned up properly in case of errors. Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Cc: Kay Sievers <kay.sievers@novell.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/base/core.c115
-rw-r--r--include/linux/device.h2
2 files changed, 70 insertions, 47 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 9ea12d9b48a6..bb2cc37a4d43 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -246,64 +246,95 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
246 return count; 246 return count;
247} 247}
248 248
249static int device_add_groups(struct device *dev) 249static int device_add_attributes(struct device *dev,
250 struct device_attribute *attrs)
251{
252 int error = 0;
253 int i;
254
255 if (attrs) {
256 for (i = 0; attr_name(attrs[i]); i++) {
257 error = device_create_file(dev, &attrs[i]);
258 if (error)
259 break;
260 }
261 if (error)
262 while (--i >= 0)
263 device_remove_file(dev, &attrs[i]);
264 }
265 return error;
266}
267
268static void device_remove_attributes(struct device *dev,
269 struct device_attribute *attrs)
250{ 270{
251 int i; 271 int i;
272
273 if (attrs)
274 for (i = 0; attr_name(attrs[i]); i++)
275 device_remove_file(dev, &attrs[i]);
276}
277
278static int device_add_groups(struct device *dev,
279 struct attribute_group **groups)
280{
252 int error = 0; 281 int error = 0;
282 int i;
253 283
254 if (dev->groups) { 284 if (groups) {
255 for (i = 0; dev->groups[i]; i++) { 285 for (i = 0; groups[i]; i++) {
256 error = sysfs_create_group(&dev->kobj, dev->groups[i]); 286 error = sysfs_create_group(&dev->kobj, groups[i]);
257 if (error) { 287 if (error) {
258 while (--i >= 0) 288 while (--i >= 0)
259 sysfs_remove_group(&dev->kobj, dev->groups[i]); 289 sysfs_remove_group(&dev->kobj, groups[i]);
260 goto out; 290 break;
261 } 291 }
262 } 292 }
263 } 293 }
264out:
265 return error; 294 return error;
266} 295}
267 296
268static void device_remove_groups(struct device *dev) 297static void device_remove_groups(struct device *dev,
298 struct attribute_group **groups)
269{ 299{
270 int i; 300 int i;
271 if (dev->groups) { 301
272 for (i = 0; dev->groups[i]; i++) { 302 if (groups)
273 sysfs_remove_group(&dev->kobj, dev->groups[i]); 303 for (i = 0; groups[i]; i++)
274 } 304 sysfs_remove_group(&dev->kobj, groups[i]);
275 }
276} 305}
277 306
278static int device_add_attrs(struct device *dev) 307static int device_add_attrs(struct device *dev)
279{ 308{
280 struct class *class = dev->class; 309 struct class *class = dev->class;
281 struct device_type *type = dev->type; 310 struct device_type *type = dev->type;
282 int error = 0; 311 int error;
283 int i;
284 312
285 if (class && class->dev_attrs) { 313 if (class) {
286 for (i = 0; attr_name(class->dev_attrs[i]); i++) { 314 error = device_add_attributes(dev, class->dev_attrs);
287 error = device_create_file(dev, &class->dev_attrs[i]);
288 if (error)
289 break;
290 }
291 if (error) 315 if (error)
292 while (--i >= 0) 316 return error;
293 device_remove_file(dev, &class->dev_attrs[i]);
294 } 317 }
295 318
296 if (type && type->attrs) { 319 if (type) {
297 for (i = 0; attr_name(type->attrs[i]); i++) { 320 error = device_add_groups(dev, type->groups);
298 error = device_create_file(dev, &type->attrs[i]);
299 if (error)
300 break;
301 }
302 if (error) 321 if (error)
303 while (--i >= 0) 322 goto err_remove_class_attrs;
304 device_remove_file(dev, &type->attrs[i]);
305 } 323 }
306 324
325 error = device_add_groups(dev, dev->groups);
326 if (error)
327 goto err_remove_type_groups;
328
329 return 0;
330
331 err_remove_type_groups:
332 if (type)
333 device_remove_groups(dev, type->groups);
334 err_remove_class_attrs:
335 if (class)
336 device_remove_attributes(dev, class->dev_attrs);
337
307 return error; 338 return error;
308} 339}
309 340
@@ -311,17 +342,14 @@ static void device_remove_attrs(struct device *dev)
311{ 342{
312 struct class *class = dev->class; 343 struct class *class = dev->class;
313 struct device_type *type = dev->type; 344 struct device_type *type = dev->type;
314 int i;
315 345
316 if (class && class->dev_attrs) { 346 device_remove_groups(dev, dev->groups);
317 for (i = 0; attr_name(class->dev_attrs[i]); i++)
318 device_remove_file(dev, &class->dev_attrs[i]);
319 }
320 347
321 if (type && type->attrs) { 348 if (type)
322 for (i = 0; attr_name(type->attrs[i]); i++) 349 device_remove_groups(dev, type->groups);
323 device_remove_file(dev, &type->attrs[i]); 350
324 } 351 if (class)
352 device_remove_attributes(dev, class->dev_attrs);
325} 353}
326 354
327 355
@@ -638,8 +666,6 @@ int device_add(struct device *dev)
638 666
639 if ((error = device_add_attrs(dev))) 667 if ((error = device_add_attrs(dev)))
640 goto AttrsError; 668 goto AttrsError;
641 if ((error = device_add_groups(dev)))
642 goto GroupError;
643 if ((error = device_pm_add(dev))) 669 if ((error = device_pm_add(dev)))
644 goto PMError; 670 goto PMError;
645 if ((error = bus_add_device(dev))) 671 if ((error = bus_add_device(dev)))
@@ -663,7 +689,7 @@ int device_add(struct device *dev)
663 up(&dev->class->sem); 689 up(&dev->class->sem);
664 } 690 }
665 Done: 691 Done:
666 kfree(class_name); 692 kfree(class_name);
667 put_device(dev); 693 put_device(dev);
668 return error; 694 return error;
669 AttachError: 695 AttachError:
@@ -674,8 +700,6 @@ int device_add(struct device *dev)
674 if (dev->bus) 700 if (dev->bus)
675 blocking_notifier_call_chain(&dev->bus->bus_notifier, 701 blocking_notifier_call_chain(&dev->bus->bus_notifier,
676 BUS_NOTIFY_DEL_DEVICE, dev); 702 BUS_NOTIFY_DEL_DEVICE, dev);
677 device_remove_groups(dev);
678 GroupError:
679 device_remove_attrs(dev); 703 device_remove_attrs(dev);
680 AttrsError: 704 AttrsError:
681 if (dev->devt_attr) { 705 if (dev->devt_attr) {
@@ -838,7 +862,6 @@ void device_del(struct device * dev)
838 } 862 }
839 } 863 }
840 device_remove_file(dev, &dev->uevent_attr); 864 device_remove_file(dev, &dev->uevent_attr);
841 device_remove_groups(dev);
842 device_remove_attrs(dev); 865 device_remove_attrs(dev);
843 bus_remove_device(dev); 866 bus_remove_device(dev);
844 867
diff --git a/include/linux/device.h b/include/linux/device.h
index 9d54fe13eb2e..3b64fdecd041 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -332,7 +332,7 @@ extern struct class_device *class_device_create(struct class *cls,
332extern void class_device_destroy(struct class *cls, dev_t devt); 332extern void class_device_destroy(struct class *cls, dev_t devt);
333 333
334struct device_type { 334struct device_type {
335 struct device_attribute *attrs; 335 struct attribute_group **groups;
336 int (*uevent)(struct device *dev, char **envp, int num_envp, 336 int (*uevent)(struct device *dev, char **envp, int num_envp,
337 char *buffer, int buffer_size); 337 char *buffer, int buffer_size);
338 void (*release)(struct device *dev); 338 void (*release)(struct device *dev);