Commit 0d1c76a0 authored by Patrick Mochel's avatar Patrick Mochel

[Driver Model] Add default attributes for classes class devices.

- add struct class::class_attrs, which is designed to point to an 
  array of class_attributes that are added when the class is registered
  and removed when the class is unregistered. 
  This allows for more consolidated and cleaner definition of and
  management of attributes.

- Add struct class::class_dev_attrs to do something similarly for 
  class devices. Each class device that is registered with the class
  gets that set of attributes added for them, and subsequently removed
  when the device is unregistered.

Each array depends on a terminating attribute with a NULL name. Hint:
use the new __ATTR_NULL macro to terminate it.
parent e33617a4
...@@ -100,6 +100,37 @@ void class_put(struct class * cls) ...@@ -100,6 +100,37 @@ void class_put(struct class * cls)
subsys_put(&cls->subsys); subsys_put(&cls->subsys);
} }
static int add_class_attrs(struct class * cls)
{
int i;
int error = 0;
if (cls->class_attrs) {
for (i = 0; attr_name(cls->class_attrs[i]); i++) {
error = class_create_file(cls,&cls->class_attrs[i]);
if (error)
goto Err;
}
}
Done:
return error;
Err:
while (--i >= 0)
class_remove_file(cls,&cls->class_attrs[i]);
goto Done;
}
static void remove_class_attrs(struct class * cls)
{
int i;
if (cls->class_attrs) {
for (i = 0; attr_name(cls->class_attrs[i]); i++)
class_remove_file(cls,&cls->class_attrs[i]);
}
}
int class_register(struct class * cls) int class_register(struct class * cls)
{ {
int error; int error;
...@@ -115,18 +146,21 @@ int class_register(struct class * cls) ...@@ -115,18 +146,21 @@ int class_register(struct class * cls)
subsys_set_kset(cls,class_subsys); subsys_set_kset(cls,class_subsys);
error = subsystem_register(&cls->subsys); error = subsystem_register(&cls->subsys);
if (error) if (!error) {
return error; error = add_class_attrs(class_get(cls));
class_put(cls);
return 0; }
return error;
} }
void class_unregister(struct class * cls) void class_unregister(struct class * cls)
{ {
pr_debug("device class '%s': unregistering\n",cls->name); pr_debug("device class '%s': unregistering\n",cls->name);
remove_class_attrs(cls);
subsystem_unregister(&cls->subsys); subsystem_unregister(&cls->subsys);
} }
/* Class Device Stuff */ /* Class Device Stuff */
int class_device_create_file(struct class_device * class_dev, int class_device_create_file(struct class_device * class_dev,
...@@ -272,6 +306,40 @@ static struct kset_hotplug_ops class_hotplug_ops = { ...@@ -272,6 +306,40 @@ static struct kset_hotplug_ops class_hotplug_ops = {
static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops); static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
static int class_device_add_attrs(struct class_device * cd)
{
int i;
int error = 0;
struct class * cls = cd->class;
if (cls->class_dev_attrs) {
for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
error = class_device_create_file(cd,
&cls->class_dev_attrs[i]);
if (error)
goto Err;
}
}
Done:
return error;
Err:
while (--i >= 0)
class_device_remove_file(cd,&cls->class_dev_attrs[i]);
goto Done;
}
static void class_device_remove_attrs(struct class_device * cd)
{
int i;
struct class * cls = cd->class;
if (cls->class_dev_attrs) {
for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
class_device_remove_file(cd,&cls->class_dev_attrs[i]);
}
}
void class_device_initialize(struct class_device *class_dev) void class_device_initialize(struct class_device *class_dev)
{ {
kobj_set_kset_s(class_dev, class_obj_subsys); kobj_set_kset_s(class_dev, class_obj_subsys);
...@@ -311,7 +379,7 @@ int class_device_add(struct class_device *class_dev) ...@@ -311,7 +379,7 @@ int class_device_add(struct class_device *class_dev)
class_intf->add(class_dev); class_intf->add(class_dev);
up_write(&parent->subsys.rwsem); up_write(&parent->subsys.rwsem);
} }
class_device_add_attrs(class_dev);
class_device_dev_link(class_dev); class_device_dev_link(class_dev);
class_device_driver_link(class_dev); class_device_driver_link(class_dev);
...@@ -344,7 +412,8 @@ void class_device_del(struct class_device *class_dev) ...@@ -344,7 +412,8 @@ void class_device_del(struct class_device *class_dev)
class_device_dev_unlink(class_dev); class_device_dev_unlink(class_dev);
class_device_driver_unlink(class_dev); class_device_driver_unlink(class_dev);
class_device_remove_attrs(class_dev);
kobject_del(&class_dev->kobj); kobject_del(&class_dev->kobj);
if (parent) if (parent)
......
...@@ -143,6 +143,9 @@ struct class { ...@@ -143,6 +143,9 @@ struct class {
struct list_head children; struct list_head children;
struct list_head interfaces; struct list_head interfaces;
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
int (*hotplug)(struct class_device *dev, char **envp, int (*hotplug)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size); int num_envp, char *buffer, int buffer_size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment