Commit 3e815107 authored by Patrick Mochel's avatar Patrick Mochel

Introduce struct kset.

struct kset is what struct subsystem should have originally been called. It
is a set of kobjects, and nothing more, with a much less confusing name than
'subsystem.'

struct kset contains an embedded kobject, making it possible to represent it
in the object hierarchy, and sysfs. This also provides a means for objects
to easily express a list of subordinate objects. 

struct subsystem still exists, and contains an rwsem, which its subordinate
ksets use to protect their lists. 

An arbitrary number of ksets may belong to a subsystem. A ksets specifies
the subsystem it belongs to via its ->subsys field. 

struct subsystem also contains a default kset, which may be used without
having to define a separate kset. 

The objects that defined subordinate subsystems (bus and class drivers) have
been converted to use subordinate ksets instead.


Note that the usage of ksets is flexible. 
- ksets may contain a list of objects of any type, not just kobjects.
- The objects registered with a kset do not have to be registered.
- ksets themselves do not have to be registered. One can be used by
  simply calling kset_init(). 
- ksets do not need a name if they are not registered. 
- Note however that locking must be done manually in these cases.
parent 2e1c4037
......@@ -35,11 +35,12 @@ static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release,
};
static struct subsystem acpi_namespace_subsys = {
static struct kset acpi_namespace_kset = {
.kobj = {
.name = "namespace",
.parent = &acpi_subsys.kobj,
},
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
};
......@@ -67,7 +68,7 @@ static void acpi_device_register(struct acpi_device * device, struct acpi_device
if (parent)
device->kobj.parent = &parent->kobj;
device->kobj.ktype = &ktype_acpi_ns;
device->kobj.subsys = &acpi_namespace_subsys;
device->kobj.kset = &acpi_namespace_kset;
kobject_register(&device->kobj);
}
......@@ -926,7 +927,7 @@ static int __init acpi_scan_init(void)
if (acpi_disabled)
return_VALUE(0);
subsystem_register(&acpi_namespace_subsys);
kset_register(&acpi_namespace_kset);
/*
* Create the root device in the bus's device tree
......
......@@ -435,7 +435,6 @@ int bus_add_driver(struct device_driver * drv)
{
struct bus_type * bus = get_bus(drv->bus);
if (bus) {
down_write(&bus->subsys.rwsem);
pr_debug("bus %s: add driver %s\n",bus->name,drv->name);
strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
......@@ -443,6 +442,7 @@ int bus_add_driver(struct device_driver * drv)
drv->kobj.subsys = &bus->drivers;
kobject_register(&drv->kobj);
down_write(&bus->subsys.rwsem);
devclass_add_driver(drv);
driver_attach(drv);
up_write(&bus->subsys.rwsem);
......@@ -467,8 +467,8 @@ void bus_remove_driver(struct device_driver * drv)
pr_debug("bus %s: remove driver %s\n",drv->bus->name,drv->name);
driver_detach(drv);
devclass_remove_driver(drv);
kobject_unregister(&drv->kobj);
up_write(&drv->bus->subsys.rwsem);
kobject_unregister(&drv->kobj);
put_bus(drv->bus);
}
}
......@@ -499,12 +499,12 @@ int bus_register(struct bus_type * bus)
subsystem_register(&bus->subsys);
snprintf(bus->devices.kobj.name,KOBJ_NAME_LEN,"devices");
bus->devices.parent = &bus->subsys;
subsystem_register(&bus->devices);
bus->devices.subsys = &bus->subsys;
kset_register(&bus->devices);
snprintf(bus->drivers.kobj.name,KOBJ_NAME_LEN,"drivers");
bus->drivers.parent = &bus->subsys;
subsystem_register(&bus->drivers);
bus->drivers.subsys = &bus->subsys;
kset_register(&bus->drivers);
pr_debug("bus type '%s' registered\n",bus->name);
return 0;
......@@ -521,8 +521,8 @@ int bus_register(struct bus_type * bus)
void bus_unregister(struct bus_type * bus)
{
pr_debug("bus %s: unregistering\n",bus->name);
subsystem_unregister(&bus->drivers);
subsystem_unregister(&bus->devices);
kset_unregister(&bus->drivers);
kset_unregister(&bus->devices);
subsystem_unregister(&bus->subsys);
}
......
......@@ -86,7 +86,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute *
{
int error;
if (cls) {
error = sysfs_create_file(&cls->subsys.kobj,&attr->attr);
error = sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr);
} else
error = -EINVAL;
return error;
......@@ -95,7 +95,7 @@ int devclass_create_file(struct device_class * cls, struct devclass_attribute *
void devclass_remove_file(struct device_class * cls, struct devclass_attribute * attr)
{
if (cls)
sysfs_remove_file(&cls->subsys.kobj,&attr->attr);
sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr);
}
......@@ -234,12 +234,12 @@ int devclass_register(struct device_class * cls)
subsystem_register(&cls->subsys);
snprintf(cls->devices.kobj.name,KOBJ_NAME_LEN,"devices");
cls->devices.parent = &cls->subsys;
subsystem_register(&cls->devices);
cls->devices.subsys = &cls->subsys;
kset_register(&cls->devices);
snprintf(cls->drivers.kobj.name,KOBJ_NAME_LEN,"drivers");
cls->drivers.parent = &cls->subsys;
subsystem_register(&cls->drivers);
cls->drivers.subsys = &cls->subsys;
kset_register(&cls->drivers);
return 0;
}
......@@ -247,8 +247,8 @@ int devclass_register(struct device_class * cls)
void devclass_unregister(struct device_class * cls)
{
pr_debug("device class '%s': unregistering\n",cls->name);
subsystem_unregister(&cls->drivers);
subsystem_unregister(&cls->devices);
kset_unregister(&cls->drivers);
kset_unregister(&cls->devices);
subsystem_unregister(&cls->subsys);
}
......
......@@ -12,7 +12,7 @@ static struct subsystem firmware_subsys = {
int firmware_register(struct subsystem * s)
{
s->parent = &firmware_subsys;
s->kobj.kset = &firmware_subsys.kset;
return subsystem_register(s);
}
......
......@@ -25,7 +25,7 @@ static int intf_dev_link(struct intf_data * data)
{
char name[16];
snprintf(name,16,"%d",data->intf_num);
return sysfs_create_link(&data->intf->subsys.kobj,&data->dev->kobj,name);
return sysfs_create_link(&data->intf->subsys.kset.kobj,&data->dev->kobj,name);
}
/**
......@@ -38,7 +38,7 @@ static void intf_dev_unlink(struct intf_data * data)
{
char name[16];
snprintf(name,16,"%d",data->intf_num);
sysfs_remove_link(&data->intf->subsys.kobj,name);
sysfs_remove_link(&data->intf->subsys.kset.kobj,name);
}
......@@ -192,7 +192,7 @@ static void del_intf(struct device_interface * intf)
struct list_head * entry;
down_write(&intf->devclass->subsys.rwsem);
list_for_each(entry,&intf->subsys.list) {
list_for_each(entry,&intf->subsys.kset.list) {
struct intf_data * data = to_data(entry);
del(data);
}
......@@ -241,7 +241,7 @@ int interface_add_dev(struct device * dev)
pr_debug("interfaces: adding device %s\n",dev->name);
list_for_each(node,&cls->subsys.list) {
list_for_each(node,&cls->subsys.kset.list) {
struct device_interface * intf = to_intf(node);
add(intf,dev);
}
......
......@@ -38,7 +38,7 @@ int device_suspend(u32 state, u32 level)
printk(KERN_EMERG "Suspending devices\n");
down_write(&device_subsys.rwsem);
list_for_each(node,&device_subsys.list) {
list_for_each(node,&device_subsys.kset.list) {
struct device * dev = to_dev(node);
if (dev->driver && dev->driver->suspend) {
pr_debug("suspending device %s\n",dev->name);
......@@ -64,7 +64,7 @@ void device_resume(u32 level)
struct list_head * node;
down_write(&device_subsys.rwsem);
list_for_each_prev(node,&device_subsys.list) {
list_for_each_prev(node,&device_subsys.kset.list) {
struct device * dev = to_dev(node);
if (dev->driver && dev->driver->resume) {
pr_debug("resuming device %s\n",dev->name);
......@@ -86,7 +86,7 @@ void device_shutdown(void)
printk(KERN_EMERG "Shutting down devices\n");
down_write(&device_subsys.rwsem);
list_for_each(entry,&device_subsys.list) {
list_for_each(entry,&device_subsys.kset.list) {
struct device * dev = to_dev(entry);
if (dev->driver && dev->driver->shutdown) {
pr_debug("shutting down %s\n",dev->name);
......
......@@ -66,8 +66,8 @@ struct bus_type {
char * name;
struct subsystem subsys;
struct subsystem drivers;
struct subsystem devices;
struct kset drivers;
struct kset devices;
int (*match)(struct device * dev, struct device_driver * drv);
struct device * (*add) (struct device * parent, char * bus_id);
......@@ -162,8 +162,8 @@ struct device_class {
u32 devnum;
struct subsystem subsys;
struct subsystem devices;
struct subsystem drivers;
struct kset devices;
struct kset drivers;
int (*add_device)(struct device *);
void (*remove_device)(struct device *);
......
......@@ -20,6 +20,7 @@ struct kobject {
struct list_head entry;
struct kobject * parent;
struct subsystem * subsys;
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
};
......@@ -43,25 +44,70 @@ struct kobj_type {
struct attribute ** default_attrs;
};
/**
* kset - a set of kobjects of a specific type, belonging
* to a specific subsystem.
*
* All kobjects of a kset should be embedded in an identical
* type. This type may have a descriptor, which the kset points
* to. This allows there to exist sets of objects of the same
* type in different subsystems.
*
* A subsystem does not have to be a list of only one type
* of object; multiple ksets can belong to one subsystem. All
* ksets of a subsystem share the subsystem's lock.
*
*/
struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list;
struct kobject kobj;
};
extern void kset_init(struct kset * k);
extern int kset_add(struct kset * k);
extern int kset_register(struct kset * k);
extern void kset_unregister(struct kset * k);
static inline struct kset * to_kset(struct kobject * kobj)
{
return container_of(kobj,struct kset,kobj);
}
static inline struct kset * kset_get(struct kset * k)
{
return k ? to_kset(kobject_get(&k->kobj)) : NULL;
}
static inline void kset_put(struct kset * k)
{
kobject_put(&k->kobj);
}
struct subsystem {
struct kset kset;
struct kobject kobj;
struct list_head list;
struct rw_semaphore rwsem;
struct subsystem * parent;
};
extern void subsystem_init(struct subsystem *);
extern int subsystem_register(struct subsystem *);
extern void subsystem_unregister(struct subsystem *);
static inline struct subsystem * subsys_get(struct subsystem * s)
{
return s ? container_of(kobject_get(&s->kobj),struct subsystem,kobj) : NULL;
return s ? container_of(kset_get(&s->kset),struct subsystem,kset) : NULL;
}
static inline void subsys_put(struct subsystem * s)
{
kobject_put(&s->kobj);
kset_put(&s->kset);
}
struct subsys_attribute {
......@@ -73,4 +119,5 @@ struct subsys_attribute {
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
#endif /* _KOBJECT_H_ */
......@@ -62,7 +62,7 @@ void kobject_init(struct kobject * kobj)
{
atomic_set(&kobj->refcount,1);
INIT_LIST_HEAD(&kobj->entry);
kobj->subsys = subsys_get(kobj->subsys);
kobj->kset = kset_get(kobj->kset);
}
/**
......@@ -73,7 +73,6 @@ void kobject_init(struct kobject * kobj)
int kobject_add(struct kobject * kobj)
{
int error = 0;
struct subsystem * s = kobj->subsys;
struct kobject * parent;
if (!(kobj = kobject_get(kobj)))
......@@ -81,19 +80,24 @@ int kobject_add(struct kobject * kobj)
parent = kobject_get(kobj->parent);
pr_debug("kobject %s: registering. parent: %s, subsys: %s\n",
pr_debug("kobject %s: registering. parent: %s, set: %s\n",
kobj->name, parent ? parent->name : "<NULL>",
kobj->subsys ? kobj->subsys->kobj.name : "<NULL>" );
kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
if (s) {
down_write(&s->rwsem);
if (kobj->subsys) {
if (!kobj->kset)
kobj->kset = &kobj->subsys->kset;
}
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
if (parent)
list_add_tail(&kobj->entry,&parent->entry);
else {
list_add_tail(&kobj->entry,&s->list);
kobj->parent = kobject_get(&s->kobj);
list_add_tail(&kobj->entry,&kobj->kset->list);
kobj->parent = kobject_get(&kobj->kset->kobj);
}
up_write(&s->rwsem);
up_write(&kobj->kset->subsys->rwsem);
}
error = create_dir(kobj);
if (error && parent)
......@@ -127,10 +131,10 @@ int kobject_register(struct kobject * kobj)
void kobject_del(struct kobject * kobj)
{
sysfs_remove_dir(kobj);
if (kobj->subsys) {
down_write(&kobj->subsys->rwsem);
if (kobj->kset) {
down_write(&kobj->kset->subsys->rwsem);
list_del_init(&kobj->entry);
up_write(&kobj->subsys->rwsem);
up_write(&kobj->kset->subsys->rwsem);
}
if (kobj->parent)
kobject_put(kobj->parent);
......@@ -174,17 +178,13 @@ struct kobject * kobject_get(struct kobject * kobj)
void kobject_cleanup(struct kobject * kobj)
{
struct kobj_type * t = kobj->ktype;
struct subsystem * s = kobj->subsys;
struct kset * s = kobj->kset;
pr_debug("kobject %s: cleaning up\n",kobj->name);
if (s) {
down_write(&s->rwsem);
list_del_init(&kobj->entry);
up_write(&s->rwsem);
subsys_put(s);
}
if (t && t->release)
t->release(kobj);
if (s)
kset_put(s);
}
/**
......@@ -203,32 +203,98 @@ void kobject_put(struct kobject * kobj)
}
/**
* kset_init - initialize a kset for use
* @k: kset
*/
void kset_init(struct kset * k)
{
kobject_init(&k->kobj);
INIT_LIST_HEAD(&k->list);
}
/**
* kset_add - add a kset object to the hierarchy.
* @k: kset.
*
* Simply, this adds the kset's embedded kobject to the
* hierarchy.
* We also try to make sure that the kset's embedded kobject
* has a parent before it is added. We only care if the embedded
* kobject is not part of a kset itself, since kobject_add()
* assigns a parent in that case.
* If that is the case, and the kset has a controlling subsystem,
* then we set the kset's parent to be said subsystem.
*/
int kset_add(struct kset * k)
{
if (!k->kobj.parent && !k->kobj.kset && k->subsys)
k->kobj.parent = &k->subsys->kset.kobj;
return kobject_add(&k->kobj);
}
/**
* kset_register - initialize and add a kset.
* @k: kset.
*/
int kset_register(struct kset * k)
{
kset_init(k);
return kset_add(k);
}
/**
* kset_unregister - remove a kset.
* @k: kset.
*/
void kset_unregister(struct kset * k)
{
kobject_unregister(&k->kobj);
}
void subsystem_init(struct subsystem * s)
{
kobject_init(&s->kobj);
memcpy(&s->kset.kobj,&s->kobj,sizeof(struct kobject));
init_rwsem(&s->rwsem);
INIT_LIST_HEAD(&s->list);
kset_init(&s->kset);
}
/**
* subsystem_register - register a subsystem.
* @s: the subsystem we're registering.
*
* Once we register the subsystem, we want to make sure that
* the kset points back to this subsystem for correct usage of
* the rwsem.
*/
int subsystem_register(struct subsystem * s)
{
int error;
subsystem_init(s);
if (s->parent)
s->kobj.parent = &s->parent->kobj;
pr_debug("subsystem %s: registering, parent: %s\n",
s->kobj.name,s->parent ? s->parent->kobj.name : "<none>");
return kobject_add(&s->kobj);
pr_debug("subsystem %s: registering\n",s->kobj.name);
if (!(error = kset_add(&s->kset))) {
if (!s->kset.subsys)
s->kset.subsys = s;
}
return error;
}
void subsystem_unregister(struct subsystem * s)
{
pr_debug("subsystem %s: unregistering\n",s->kobj.name);
kobject_unregister(&s->kobj);
kset_unregister(&s->kset);
}
......
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