Driver core: move the static kobject out of struct driver
Greg Kroah-Hartman [Wed, 28 Nov 2007 23:59:15 +0000 (15:59 -0800)]
This patch removes the kobject, and a few other driver-core-only fields
out of struct driver and into the driver core only.  Now drivers can be
safely create on the stack or statically (like they currently are.)

Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/base/base.h
drivers/base/bus.c
drivers/base/dd.c
drivers/base/driver.c
drivers/base/module.c
drivers/base/platform.c
include/linux/device.h

index 0547236..3b0f395 100644 (file)
@@ -27,6 +27,14 @@ struct bus_type_private {
        struct bus_type *bus;
 };
 
+struct driver_private {
+       struct kobject kobj;
+       struct klist klist_devices;
+       struct klist_node knode_bus;
+       struct module_kobject *mkobj;
+       struct device_driver *driver;
+};
+#define to_driver(obj) container_of(obj, struct driver_private, kobj)
 
 /* initialisation functions */
 extern int devices_init(void);
index 04d3850..aa0c986 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (c) 2007 Novell Inc.
  *
  * This file is released under the GPLv2
  *
@@ -24,7 +26,6 @@
  */
 
 #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
-#define to_driver(obj) container_of(obj, struct device_driver, kobj)
 
 
 static int __must_check bus_rescan_devices_helper(struct device *dev,
@@ -49,11 +50,11 @@ static ssize_t
 drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
        struct driver_attribute * drv_attr = to_drv_attr(attr);
-       struct device_driver * drv = to_driver(kobj);
+       struct driver_private *drv_priv = to_driver(kobj);
        ssize_t ret = -EIO;
 
        if (drv_attr->show)
-               ret = drv_attr->show(drv, buf);
+               ret = drv_attr->show(drv_priv->driver, buf);
        return ret;
 }
 
@@ -62,11 +63,11 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr,
               const char * buf, size_t count)
 {
        struct driver_attribute * drv_attr = to_drv_attr(attr);
-       struct device_driver * drv = to_driver(kobj);
+       struct driver_private *drv_priv = to_driver(kobj);
        ssize_t ret = -EIO;
 
        if (drv_attr->store)
-               ret = drv_attr->store(drv, buf, count);
+               ret = drv_attr->store(drv_priv->driver, buf, count);
        return ret;
 }
 
@@ -75,22 +76,12 @@ static struct sysfs_ops driver_sysfs_ops = {
        .store  = drv_attr_store,
 };
 
-
-static void driver_release(struct kobject * kobj)
+static void driver_release(struct kobject *kobj)
 {
-       /*
-        * Yes this is an empty release function, it is this way because struct
-        * device is always a static object, not a dynamic one.  Yes, this is
-        * not nice and bad, but remember, drivers are code, reference counted
-        * by the module count, not a device, which is really data.  And yes,
-        * in the future I do want to have all drivers be created dynamically,
-        * and am working toward that goal, but it will take a bit longer...
-        *
-        * But do not let this example give _anyone_ the idea that they can
-        * create a release function without any code in it at all, to do that
-        * is almost always wrong.  If you have any questions about this,
-        * please send an email to <greg@kroah.com>
-        */
+       struct driver_private *drv_priv = to_driver(kobj);
+
+       pr_debug("%s: freeing %s\n", __FUNCTION__, kobject_name(kobj));
+       kfree(drv_priv);
 }
 
 static struct kobj_type driver_ktype = {
@@ -350,7 +341,13 @@ struct device * bus_find_device(struct bus_type *bus,
 static struct device_driver * next_driver(struct klist_iter * i)
 {
        struct klist_node * n = klist_next(i);
-       return n ? container_of(n, struct device_driver, knode_bus) : NULL;
+       struct driver_private *drv_priv;
+
+       if (n) {
+               drv_priv = container_of(n, struct driver_private, knode_bus);
+               return drv_priv->driver;
+       }
+       return NULL;
 }
 
 /**
@@ -384,7 +381,7 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
                return -EINVAL;
 
        klist_iter_init_node(&bus->p->klist_drivers, &i,
-                            start ? &start->knode_bus : NULL);
+                            start ? &start->p->knode_bus : NULL);
        while ((drv = next_driver(&i)) && !error)
                error = fn(drv, data);
        klist_iter_exit(&i);
@@ -620,7 +617,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv,
        enum kobject_action action;
 
        if (kobject_action_type(buf, count, &action) == 0)
-               kobject_uevent(&drv->kobj, action);
+               kobject_uevent(&drv->p->kobj, action);
        return count;
 }
 static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
@@ -632,19 +629,29 @@ static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
  */
 int bus_add_driver(struct device_driver *drv)
 {
-       struct bus_type * bus = bus_get(drv->bus);
+       struct bus_type *bus;
+       struct driver_private *priv;
        int error = 0;
 
+       bus = bus_get(drv->bus);
        if (!bus)
                return -EINVAL;
 
        pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
-       error = kobject_set_name(&drv->kobj, "%s", drv->name);
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       error = kobject_set_name(&priv->kobj, "%s", drv->name);
        if (error)
                goto out_put_bus;
-       drv->kobj.kset = bus->p->drivers_kset;
-       drv->kobj.ktype = &driver_ktype;
-       error = kobject_register(&drv->kobj);
+       priv->kobj.kset = bus->p->drivers_kset;
+       priv->kobj.ktype = &driver_ktype;
+       klist_init(&priv->klist_devices, NULL, NULL);
+       priv->driver = drv;
+       drv->p = priv;
+       error = kobject_register(&priv->kobj);
        if (error)
                goto out_put_bus;
 
@@ -653,7 +660,7 @@ int bus_add_driver(struct device_driver *drv)
                if (error)
                        goto out_unregister;
        }
-       klist_add_tail(&drv->knode_bus, &bus->p->klist_drivers);
+       klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
        module_add_driver(drv->owner, drv);
 
        error = driver_create_file(drv, &driver_attr_uevent);
@@ -676,7 +683,7 @@ int bus_add_driver(struct device_driver *drv)
 
        return error;
 out_unregister:
-       kobject_unregister(&drv->kobj);
+       kobject_unregister(&priv->kobj);
 out_put_bus:
        bus_put(bus);
        return error;
@@ -699,11 +706,11 @@ 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);
+       klist_remove(&drv->p->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);
+       kobject_unregister(&drv->p->kobj);
        bus_put(drv->bus);
 }
 
index 7bf0e67..87a348c 100644 (file)
@@ -11,6 +11,8 @@
  *
  *     Copyright (c) 2002-5 Patrick Mochel
  *     Copyright (c) 2002-3 Open Source Development Labs
+ *     Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ *     Copyright (c) 2007 Novell Inc.
  *
  *     This file is released under the GPLv2
  */
@@ -23,8 +25,6 @@
 #include "base.h"
 #include "power/power.h"
 
-#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-
 
 static void driver_bound(struct device *dev)
 {
@@ -41,20 +41,20 @@ static void driver_bound(struct device *dev)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_BOUND_DRIVER, dev);
 
-       klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
+       klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices);
 }
 
 static int driver_sysfs_add(struct device *dev)
 {
        int ret;
 
-       ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+       ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
                          kobject_name(&dev->kobj));
        if (ret == 0) {
-               ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
+               ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
                                        "driver");
                if (ret)
-                       sysfs_remove_link(&dev->driver->kobj,
+                       sysfs_remove_link(&dev->driver->p->kobj,
                                        kobject_name(&dev->kobj));
        }
        return ret;
@@ -65,7 +65,7 @@ static void driver_sysfs_remove(struct device *dev)
        struct device_driver *drv = dev->driver;
 
        if (drv) {
-               sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+               sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
                sysfs_remove_link(&dev->kobj, "driver");
        }
 }
@@ -339,15 +339,15 @@ void driver_detach(struct device_driver * drv)
        struct device * dev;
 
        for (;;) {
-               spin_lock(&drv->klist_devices.k_lock);
-               if (list_empty(&drv->klist_devices.k_list)) {
-                       spin_unlock(&drv->klist_devices.k_lock);
+               spin_lock(&drv->p->klist_devices.k_lock);
+               if (list_empty(&drv->p->klist_devices.k_list)) {
+                       spin_unlock(&drv->p->klist_devices.k_lock);
                        break;
                }
-               dev = list_entry(drv->klist_devices.k_list.prev,
+               dev = list_entry(drv->p->klist_devices.k_list.prev,
                                struct device, knode_driver.n_node);
                get_device(dev);
-               spin_unlock(&drv->klist_devices.k_lock);
+               spin_unlock(&drv->p->klist_devices.k_lock);
 
                if (dev->parent)        /* Needed for USB */
                        down(&dev->parent->sem);
index 633ae1d..5aacff2 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (c) 2007 Novell Inc.
  *
  * This file is released under the GPLv2
  *
@@ -15,7 +17,6 @@
 #include "base.h"
 
 #define to_dev(node) container_of(node, struct device, driver_list)
-#define to_drv(obj) container_of(obj, struct device_driver, kobj)
 
 
 static struct device * next_device(struct klist_iter * i)
@@ -44,7 +45,7 @@ int driver_for_each_device(struct device_driver * drv, struct device * start,
        if (!drv)
                return -EINVAL;
 
-       klist_iter_init_node(&drv->klist_devices, &i,
+       klist_iter_init_node(&drv->p->klist_devices, &i,
                             start ? &start->knode_driver : NULL);
        while ((dev = next_device(&i)) && !error)
                error = fn(dev, data);
@@ -80,7 +81,7 @@ struct device * driver_find_device(struct device_driver *drv,
        if (!drv)
                return NULL;
 
-       klist_iter_init_node(&drv->klist_devices, &i,
+       klist_iter_init_node(&drv->p->klist_devices, &i,
                             (start ? &start->knode_driver : NULL));
        while ((dev = next_device(&i)))
                if (match(dev, data) && get_device(dev))
@@ -100,7 +101,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att
 {
        int error;
        if (get_driver(drv)) {
-               error = sysfs_create_file(&drv->kobj, &attr->attr);
+               error = sysfs_create_file(&drv->p->kobj, &attr->attr);
                put_driver(drv);
        } else
                error = -EINVAL;
@@ -117,7 +118,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att
 void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
 {
        if (get_driver(drv)) {
-               sysfs_remove_file(&drv->kobj, &attr->attr);
+               sysfs_remove_file(&drv->p->kobj, &attr->attr);
                put_driver(drv);
        }
 }
@@ -143,7 +144,7 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
        if (!name)
                return -ENOMEM;
 
-       return kobject_add_ng(kobj, &drv->kobj, "%s", name);
+       return kobject_add_ng(kobj, &drv->p->kobj, "%s", name);
 }
 EXPORT_SYMBOL_GPL(driver_add_kobj);
 
@@ -153,7 +154,15 @@ EXPORT_SYMBOL_GPL(driver_add_kobj);
  */
 struct device_driver * get_driver(struct device_driver * drv)
 {
-       return drv ? to_drv(kobject_get(&drv->kobj)) : NULL;
+       if (drv) {
+               struct driver_private *priv;
+               struct kobject *kobj;
+
+               kobj = kobject_get(&drv->p->kobj);
+               priv = to_driver(kobj);
+               return priv->driver;
+       }
+       return NULL;
 }
 
 
@@ -163,7 +172,7 @@ struct device_driver * get_driver(struct device_driver * drv)
  */
 void put_driver(struct device_driver * drv)
 {
-       kobject_put(&drv->kobj);
+       kobject_put(&drv->p->kobj);
 }
 
 static int driver_add_groups(struct device_driver *drv,
@@ -174,10 +183,10 @@ static int driver_add_groups(struct device_driver *drv,
 
        if (groups) {
                for (i = 0; groups[i]; i++) {
-                       error = sysfs_create_group(&drv->kobj, groups[i]);
+                       error = sysfs_create_group(&drv->p->kobj, groups[i]);
                        if (error) {
                                while (--i >= 0)
-                                       sysfs_remove_group(&drv->kobj,
+                                       sysfs_remove_group(&drv->p->kobj,
                                                           groups[i]);
                                break;
                        }
@@ -193,7 +202,7 @@ static void driver_remove_groups(struct device_driver *drv,
 
        if (groups)
                for (i = 0; groups[i]; i++)
-                       sysfs_remove_group(&drv->kobj, groups[i]);
+                       sysfs_remove_group(&drv->p->kobj, groups[i]);
 }
 
 
@@ -214,7 +223,6 @@ int driver_register(struct device_driver * drv)
            (drv->bus->shutdown && drv->shutdown)) {
                printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
        }
-       klist_init(&drv->klist_devices, NULL, NULL);
        ret = bus_add_driver(drv);
        if (ret)
                return ret;
@@ -250,8 +258,12 @@ void driver_unregister(struct device_driver * drv)
 struct device_driver *driver_find(const char *name, struct bus_type *bus)
 {
        struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
-       if (k)
-               return to_drv(k);
+       struct driver_private *priv;
+
+       if (k) {
+               priv = to_driver(k);
+               return priv->driver;
+       }
        return NULL;
 }
 
index cad07be..103be9c 100644 (file)
@@ -50,7 +50,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
                if (mkobj) {
                        mk = container_of(mkobj, struct module_kobject, kobj);
                        /* remember our module structure */
-                       drv->mkobj = mk;
+                       drv->p->mkobj = mk;
                        /* kset_find_obj took a reference */
                        kobject_put(mkobj);
                }
@@ -60,11 +60,11 @@ void module_add_driver(struct module *mod, struct device_driver *drv)
                return;
 
        /* Don't check return codes; these calls are idempotent */
-       no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module");
+       no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
        driver_name = make_driver_name(drv);
        if (driver_name) {
                module_create_drivers_dir(mk);
-               no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj,
+               no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
                                            driver_name);
                kfree(driver_name);
        }
@@ -78,12 +78,12 @@ void module_remove_driver(struct device_driver *drv)
        if (!drv)
                return;
 
-       sysfs_remove_link(&drv->kobj, "module");
+       sysfs_remove_link(&drv->p->kobj, "module");
 
        if (drv->owner)
                mk = &drv->owner->mkobj;
-       else if (drv->mkobj)
-               mk = drv->mkobj;
+       else if (drv->p->mkobj)
+               mk = drv->p->mkobj;
        if (mk && mk->drivers_dir) {
                driver_name = make_driver_name(drv);
                if (driver_name) {
index d56a05f..bdd59e8 100644 (file)
@@ -499,7 +499,7 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
         */
        spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
        drv->probe = NULL;
-       if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
+       if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
                retval = -ENODEV;
        drv->driver.probe = platform_drv_probe_fail;
        spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
index 721ee31..92ba3a8 100644 (file)
@@ -32,6 +32,7 @@
 
 struct device;
 struct device_driver;
+struct driver_private;
 struct class;
 struct class_device;
 struct bus_type;
@@ -113,16 +114,11 @@ extern struct kset *bus_get_kset(struct bus_type *bus);
 extern struct klist *bus_get_device_klist(struct bus_type *bus);
 
 struct device_driver {
-       const char              * name;
-       struct bus_type         * bus;
-
-       struct kobject          kobj;
-       struct klist            klist_devices;
-       struct klist_node       knode_bus;
+       const char              *name;
+       struct bus_type         *bus;
 
-       struct module           * owner;
-       const char              * mod_name;     /* used for built-in modules */
-       struct module_kobject   * mkobj;
+       struct module           *owner;
+       const char              *mod_name;      /* used for built-in modules */
 
        int     (*probe)        (struct device * dev);
        int     (*remove)       (struct device * dev);
@@ -130,6 +126,8 @@ struct device_driver {
        int     (*suspend)      (struct device * dev, pm_message_t state);
        int     (*resume)       (struct device * dev);
        struct attribute_group **groups;
+
+       struct driver_private *p;
 };