]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/base/bus.c
kset: convert struct bus_device->devices to use kset_create
[linux-2.6-omap-h63xx.git] / drivers / base / bus.c
index dca734819e50cc670439f22806eac6198e8c29eb..b23eeb2d4ead0ae8c6226cba940f69bc656d080a 100644 (file)
 static int __must_check bus_rescan_devices_helper(struct device *dev,
                                                void *data);
 
+static struct bus_type *bus_get(struct bus_type *bus)
+{
+       return bus ? container_of(kset_get(&bus->subsys),
+                               struct bus_type, subsys) : NULL;
+}
+
+static void bus_put(struct bus_type *bus)
+{
+       kset_put(&bus->subsys);
+}
+
 static ssize_t
 drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
@@ -78,7 +89,7 @@ static void driver_release(struct kobject * kobj)
         */
 }
 
-static struct kobj_type ktype_driver = {
+static struct kobj_type driver_ktype = {
        .sysfs_ops      = &driver_sysfs_ops,
        .release        = driver_release,
 };
@@ -122,9 +133,9 @@ static struct sysfs_ops bus_sysfs_ops = {
 int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
 {
        int error;
-       if (get_bus(bus)) {
+       if (bus_get(bus)) {
                error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
-               put_bus(bus);
+               bus_put(bus);
        } else
                error = -EINVAL;
        return error;
@@ -132,18 +143,30 @@ int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
 
 void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
 {
-       if (get_bus(bus)) {
+       if (bus_get(bus)) {
                sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
-               put_bus(bus);
+               bus_put(bus);
        }
 }
 
-static struct kobj_type ktype_bus = {
+static struct kobj_type bus_ktype = {
        .sysfs_ops      = &bus_sysfs_ops,
+};
+
+static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+       struct kobj_type *ktype = get_ktype(kobj);
+
+       if (ktype == &bus_ktype)
+               return 1;
+       return 0;
+}
 
+static struct kset_uevent_ops bus_uevent_ops = {
+       .filter = bus_uevent_filter,
 };
 
-static decl_subsys(bus, &ktype_bus, NULL);
+static struct kset *bus_kset;
 
 
 #ifdef CONFIG_HOTPLUG
@@ -160,7 +183,7 @@ static int driver_helper(struct device *dev, void *data)
 static ssize_t driver_unbind(struct device_driver *drv,
                             const char *buf, size_t count)
 {
-       struct bus_type *bus = get_bus(drv->bus);
+       struct bus_type *bus = bus_get(drv->bus);
        struct device *dev;
        int err = -ENODEV;
 
@@ -174,7 +197,7 @@ static ssize_t driver_unbind(struct device_driver *drv,
                err = count;
        }
        put_device(dev);
-       put_bus(bus);
+       bus_put(bus);
        return err;
 }
 static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
@@ -187,7 +210,7 @@ static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
 static ssize_t driver_bind(struct device_driver *drv,
                           const char *buf, size_t count)
 {
-       struct bus_type *bus = get_bus(drv->bus);
+       struct bus_type *bus = bus_get(drv->bus);
        struct device *dev;
        int err = -ENODEV;
 
@@ -207,7 +230,7 @@ static ssize_t driver_bind(struct device_driver *drv,
                        err = -ENODEV;
        }
        put_device(dev);
-       put_bus(bus);
+       bus_put(bus);
        return err;
 }
 static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
@@ -418,7 +441,7 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
  */
 int bus_add_device(struct device * dev)
 {
-       struct bus_type * bus = get_bus(dev->bus);
+       struct bus_type * bus = bus_get(dev->bus);
        int error = 0;
 
        if (bus) {
@@ -426,7 +449,7 @@ int bus_add_device(struct device * dev)
                error = device_add_attrs(bus, dev);
                if (error)
                        goto out_put;
-               error = sysfs_create_link(&bus->devices.kobj,
+               error = sysfs_create_link(&bus->devices_kset->kobj,
                                                &dev->kobj, dev->bus_id);
                if (error)
                        goto out_id;
@@ -443,11 +466,11 @@ int bus_add_device(struct device * dev)
 out_deprecated:
        sysfs_remove_link(&dev->kobj, "subsystem");
 out_subsys:
-       sysfs_remove_link(&bus->devices.kobj, dev->bus_id);
+       sysfs_remove_link(&bus->devices_kset->kobj, dev->bus_id);
 out_id:
        device_remove_attrs(bus, dev);
 out_put:
-       put_bus(dev->bus);
+       bus_put(dev->bus);
        return error;
 }
 
@@ -489,7 +512,7 @@ void bus_remove_device(struct device * dev)
        if (dev->bus) {
                sysfs_remove_link(&dev->kobj, "subsystem");
                remove_deprecated_bus_links(dev);
-               sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
+               sysfs_remove_link(&dev->bus->devices_kset->kobj, dev->bus_id);
                device_remove_attrs(dev->bus, dev);
                if (dev->is_registered) {
                        dev->is_registered = 0;
@@ -497,7 +520,7 @@ void bus_remove_device(struct device * dev)
                }
                pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
                device_release_driver(dev);
-               put_bus(dev->bus);
+               bus_put(dev->bus);
        }
 }
 
@@ -556,34 +579,29 @@ static void remove_bind_files(struct device_driver *drv)
        driver_remove_file(drv, &driver_attr_unbind);
 }
 
+static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);
+static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,
+               show_drivers_autoprobe, store_drivers_autoprobe);
+
 static int add_probe_files(struct bus_type *bus)
 {
        int retval;
 
-       bus->drivers_probe_attr.attr.name = "drivers_probe";
-       bus->drivers_probe_attr.attr.mode = S_IWUSR;
-       bus->drivers_probe_attr.attr.owner = bus->owner;
-       bus->drivers_probe_attr.store = store_drivers_probe;
-       retval = bus_create_file(bus, &bus->drivers_probe_attr);
+       retval = bus_create_file(bus, &bus_attr_drivers_probe);
        if (retval)
                goto out;
 
-       bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
-       bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
-       bus->drivers_autoprobe_attr.attr.owner = bus->owner;
-       bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
-       bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
-       retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
+       retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);
        if (retval)
-               bus_remove_file(bus, &bus->drivers_probe_attr);
+               bus_remove_file(bus, &bus_attr_drivers_probe);
 out:
        return retval;
 }
 
 static void remove_probe_files(struct bus_type *bus)
 {
-       bus_remove_file(bus, &bus->drivers_autoprobe_attr);
-       bus_remove_file(bus, &bus->drivers_probe_attr);
+       bus_remove_file(bus, &bus_attr_drivers_autoprobe);
+       bus_remove_file(bus, &bus_attr_drivers_probe);
 }
 #else
 static inline int add_bind_files(struct device_driver *drv) { return 0; }
@@ -592,6 +610,17 @@ static inline int add_probe_files(struct bus_type *bus) { return 0; }
 static inline void remove_probe_files(struct bus_type *bus) {}
 #endif
 
+static ssize_t driver_uevent_store(struct device_driver *drv,
+                                  const char *buf, size_t count)
+{
+       enum kobject_action action;
+
+       if (kobject_action_type(buf, count, &action) == 0)
+               kobject_uevent(&drv->kobj, action);
+       return count;
+}
+static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
+
 /**
  *     bus_add_driver - Add a driver to the bus.
  *     @drv:   driver.
@@ -599,7 +628,7 @@ static inline void remove_probe_files(struct bus_type *bus) {}
  */
 int bus_add_driver(struct device_driver *drv)
 {
-       struct bus_type * bus = get_bus(drv->bus);
+       struct bus_type * bus = bus_get(drv->bus);
        int error = 0;
 
        if (!bus)
@@ -610,7 +639,9 @@ int bus_add_driver(struct device_driver *drv)
        if (error)
                goto out_put_bus;
        drv->kobj.kset = &bus->drivers;
-       if ((error = kobject_register(&drv->kobj)))
+       drv->kobj.ktype = &driver_ktype;
+       error = kobject_register(&drv->kobj);
+       if (error)
                goto out_put_bus;
 
        if (drv->bus->drivers_autoprobe) {
@@ -621,6 +652,11 @@ int bus_add_driver(struct device_driver *drv)
        klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
        module_add_driver(drv->owner, drv);
 
+       error = driver_create_file(drv, &driver_attr_uevent);
+       if (error) {
+               printk(KERN_ERR "%s: uevent attr (%s) failed\n",
+                       __FUNCTION__, drv->name);
+       }
        error = driver_add_attrs(bus, drv);
        if (error) {
                /* How the hell do we get out of this pickle? Give up */
@@ -638,7 +674,7 @@ int bus_add_driver(struct device_driver *drv)
 out_unregister:
        kobject_unregister(&drv->kobj);
 out_put_bus:
-       put_bus(bus);
+       bus_put(bus);
        return error;
 }
 
@@ -658,12 +694,13 @@ void bus_remove_driver(struct device_driver * drv)
 
        remove_bind_files(drv);
        driver_remove_attrs(drv->bus, drv);
+       driver_remove_file(drv, &driver_attr_uevent);
        klist_remove(&drv->knode_bus);
        pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
        driver_detach(drv);
        module_remove_driver(drv);
        kobject_unregister(&drv->kobj);
-       put_bus(drv->bus);
+       bus_put(drv->bus);
 }
 
 
@@ -718,18 +755,6 @@ int device_reprobe(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(device_reprobe);
 
-struct bus_type *get_bus(struct bus_type *bus)
-{
-       return bus ? container_of(subsys_get(&bus->subsys),
-                               struct bus_type, subsys) : NULL;
-}
-
-void put_bus(struct bus_type * bus)
-{
-       subsys_put(&bus->subsys);
-}
-
-
 /**
  *     find_bus - locate bus by name.
  *     @name:  name of bus.
@@ -742,7 +767,7 @@ void put_bus(struct bus_type * bus)
 #if 0
 struct bus_type * find_bus(char * name)
 {
-       struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
+       struct kobject * k = kset_find_obj(bus_kset, name);
        return k ? to_bus(k) : NULL;
 }
 #endif  /*  0  */
@@ -760,7 +785,8 @@ static int bus_add_attrs(struct bus_type * bus)
 
        if (bus->bus_attrs) {
                for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
-                       if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
+                       error = bus_create_file(bus,&bus->bus_attrs[i]);
+                       if (error)
                                goto Err;
                }
        }
@@ -796,6 +822,17 @@ static void klist_devices_put(struct klist_node *n)
        put_device(dev);
 }
 
+static ssize_t bus_uevent_store(struct bus_type *bus,
+                               const char *buf, size_t count)
+{
+       enum kobject_action action;
+
+       if (kobject_action_type(buf, count, &action) == 0)
+               kobject_uevent(&bus->subsys.kobj, action);
+       return count;
+}
+static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
+
 /**
  *     bus_register - register a bus with the system.
  *     @bus:   bus.
@@ -814,20 +851,26 @@ int bus_register(struct bus_type * bus)
        if (retval)
                goto out;
 
-       subsys_set_kset(bus, bus_subsys);
+       bus->subsys.kobj.kset = bus_kset;
+       bus->subsys.kobj.ktype = &bus_ktype;
+
        retval = subsystem_register(&bus->subsys);
        if (retval)
                goto out;
 
-       kobject_set_name(&bus->devices.kobj, "devices");
-       bus->devices.kobj.parent = &bus->subsys.kobj;
-       retval = kset_register(&bus->devices);
+       retval = bus_create_file(bus, &bus_attr_uevent);
        if (retval)
+               goto bus_uevent_fail;
+
+       bus->devices_kset = kset_create_and_add("devices", NULL,
+                                               &bus->subsys.kobj);
+       if (!bus->devices_kset) {
+               retval = -ENOMEM;
                goto bus_devices_fail;
+       }
 
        kobject_set_name(&bus->drivers.kobj, "drivers");
        bus->drivers.kobj.parent = &bus->subsys.kobj;
-       bus->drivers.ktype = &ktype_driver;
        retval = kset_register(&bus->drivers);
        if (retval)
                goto bus_drivers_fail;
@@ -852,8 +895,10 @@ bus_attrs_fail:
 bus_probe_files_fail:
        kset_unregister(&bus->drivers);
 bus_drivers_fail:
-       kset_unregister(&bus->devices);
+       kset_unregister(bus->devices_kset);
 bus_devices_fail:
+       bus_remove_file(bus, &bus_attr_uevent);
+bus_uevent_fail:
        subsystem_unregister(&bus->subsys);
 out:
        return retval;
@@ -864,7 +909,7 @@ out:
  *     @bus:   bus.
  *
  *     Unregister the child subsystems and the bus itself.
- *     Finally, we call put_bus() to release the refcount
+ *     Finally, we call bus_put() to release the refcount
  */
 void bus_unregister(struct bus_type * bus)
 {
@@ -872,7 +917,8 @@ void bus_unregister(struct bus_type * bus)
        bus_remove_attrs(bus);
        remove_probe_files(bus);
        kset_unregister(&bus->drivers);
-       kset_unregister(&bus->devices);
+       kset_unregister(bus->devices_kset);
+       bus_remove_file(bus, &bus_attr_uevent);
        subsystem_unregister(&bus->subsys);
 }
 
@@ -890,7 +936,10 @@ EXPORT_SYMBOL_GPL(bus_unregister_notifier);
 
 int __init buses_init(void)
 {
-       return subsystem_register(&bus_subsys);
+       bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
+       if (!bus_kset)
+               return -ENOMEM;
+       return 0;
 }