diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2007-11-28 18:59:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-01-24 23:40:35 -0500 |
commit | e5dd12784617f0f1fae5f96a7fac1ec4c49fadbe (patch) | |
tree | c81e2a2f3aa1c60b92951d398774f1391bdc6a1c /drivers/base/bus.c | |
parent | c63469a3985a9771c18a916b8d42845d044ea0b1 (diff) |
Driver core: move the static kobject out of struct driver
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>
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 04d3850ff4b7..aa0c986c323a 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2002-3 Patrick Mochel | 4 | * Copyright (c) 2002-3 Patrick Mochel |
5 | * Copyright (c) 2002-3 Open Source Development Labs | 5 | * Copyright (c) 2002-3 Open Source Development Labs |
6 | * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> | ||
7 | * Copyright (c) 2007 Novell Inc. | ||
6 | * | 8 | * |
7 | * This file is released under the GPLv2 | 9 | * This file is released under the GPLv2 |
8 | * | 10 | * |
@@ -24,7 +26,6 @@ | |||
24 | */ | 26 | */ |
25 | 27 | ||
26 | #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) | 28 | #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr) |
27 | #define to_driver(obj) container_of(obj, struct device_driver, kobj) | ||
28 | 29 | ||
29 | 30 | ||
30 | static int __must_check bus_rescan_devices_helper(struct device *dev, | 31 | static int __must_check bus_rescan_devices_helper(struct device *dev, |
@@ -49,11 +50,11 @@ static ssize_t | |||
49 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 50 | drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
50 | { | 51 | { |
51 | struct driver_attribute * drv_attr = to_drv_attr(attr); | 52 | struct driver_attribute * drv_attr = to_drv_attr(attr); |
52 | struct device_driver * drv = to_driver(kobj); | 53 | struct driver_private *drv_priv = to_driver(kobj); |
53 | ssize_t ret = -EIO; | 54 | ssize_t ret = -EIO; |
54 | 55 | ||
55 | if (drv_attr->show) | 56 | if (drv_attr->show) |
56 | ret = drv_attr->show(drv, buf); | 57 | ret = drv_attr->show(drv_priv->driver, buf); |
57 | return ret; | 58 | return ret; |
58 | } | 59 | } |
59 | 60 | ||
@@ -62,11 +63,11 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr, | |||
62 | const char * buf, size_t count) | 63 | const char * buf, size_t count) |
63 | { | 64 | { |
64 | struct driver_attribute * drv_attr = to_drv_attr(attr); | 65 | struct driver_attribute * drv_attr = to_drv_attr(attr); |
65 | struct device_driver * drv = to_driver(kobj); | 66 | struct driver_private *drv_priv = to_driver(kobj); |
66 | ssize_t ret = -EIO; | 67 | ssize_t ret = -EIO; |
67 | 68 | ||
68 | if (drv_attr->store) | 69 | if (drv_attr->store) |
69 | ret = drv_attr->store(drv, buf, count); | 70 | ret = drv_attr->store(drv_priv->driver, buf, count); |
70 | return ret; | 71 | return ret; |
71 | } | 72 | } |
72 | 73 | ||
@@ -75,22 +76,12 @@ static struct sysfs_ops driver_sysfs_ops = { | |||
75 | .store = drv_attr_store, | 76 | .store = drv_attr_store, |
76 | }; | 77 | }; |
77 | 78 | ||
78 | 79 | static void driver_release(struct kobject *kobj) | |
79 | static void driver_release(struct kobject * kobj) | ||
80 | { | 80 | { |
81 | /* | 81 | struct driver_private *drv_priv = to_driver(kobj); |
82 | * Yes this is an empty release function, it is this way because struct | 82 | |
83 | * device is always a static object, not a dynamic one. Yes, this is | 83 | pr_debug("%s: freeing %s\n", __FUNCTION__, kobject_name(kobj)); |
84 | * not nice and bad, but remember, drivers are code, reference counted | 84 | kfree(drv_priv); |
85 | * by the module count, not a device, which is really data. And yes, | ||
86 | * in the future I do want to have all drivers be created dynamically, | ||
87 | * and am working toward that goal, but it will take a bit longer... | ||
88 | * | ||
89 | * But do not let this example give _anyone_ the idea that they can | ||
90 | * create a release function without any code in it at all, to do that | ||
91 | * is almost always wrong. If you have any questions about this, | ||
92 | * please send an email to <greg@kroah.com> | ||
93 | */ | ||
94 | } | 85 | } |
95 | 86 | ||
96 | static struct kobj_type driver_ktype = { | 87 | static struct kobj_type driver_ktype = { |
@@ -350,7 +341,13 @@ struct device * bus_find_device(struct bus_type *bus, | |||
350 | static struct device_driver * next_driver(struct klist_iter * i) | 341 | static struct device_driver * next_driver(struct klist_iter * i) |
351 | { | 342 | { |
352 | struct klist_node * n = klist_next(i); | 343 | struct klist_node * n = klist_next(i); |
353 | return n ? container_of(n, struct device_driver, knode_bus) : NULL; | 344 | struct driver_private *drv_priv; |
345 | |||
346 | if (n) { | ||
347 | drv_priv = container_of(n, struct driver_private, knode_bus); | ||
348 | return drv_priv->driver; | ||
349 | } | ||
350 | return NULL; | ||
354 | } | 351 | } |
355 | 352 | ||
356 | /** | 353 | /** |
@@ -384,7 +381,7 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | |||
384 | return -EINVAL; | 381 | return -EINVAL; |
385 | 382 | ||
386 | klist_iter_init_node(&bus->p->klist_drivers, &i, | 383 | klist_iter_init_node(&bus->p->klist_drivers, &i, |
387 | start ? &start->knode_bus : NULL); | 384 | start ? &start->p->knode_bus : NULL); |
388 | while ((drv = next_driver(&i)) && !error) | 385 | while ((drv = next_driver(&i)) && !error) |
389 | error = fn(drv, data); | 386 | error = fn(drv, data); |
390 | klist_iter_exit(&i); | 387 | klist_iter_exit(&i); |
@@ -620,7 +617,7 @@ static ssize_t driver_uevent_store(struct device_driver *drv, | |||
620 | enum kobject_action action; | 617 | enum kobject_action action; |
621 | 618 | ||
622 | if (kobject_action_type(buf, count, &action) == 0) | 619 | if (kobject_action_type(buf, count, &action) == 0) |
623 | kobject_uevent(&drv->kobj, action); | 620 | kobject_uevent(&drv->p->kobj, action); |
624 | return count; | 621 | return count; |
625 | } | 622 | } |
626 | static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); | 623 | static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); |
@@ -632,19 +629,29 @@ static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store); | |||
632 | */ | 629 | */ |
633 | int bus_add_driver(struct device_driver *drv) | 630 | int bus_add_driver(struct device_driver *drv) |
634 | { | 631 | { |
635 | struct bus_type * bus = bus_get(drv->bus); | 632 | struct bus_type *bus; |
633 | struct driver_private *priv; | ||
636 | int error = 0; | 634 | int error = 0; |
637 | 635 | ||
636 | bus = bus_get(drv->bus); | ||
638 | if (!bus) | 637 | if (!bus) |
639 | return -EINVAL; | 638 | return -EINVAL; |
640 | 639 | ||
641 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); | 640 | pr_debug("bus %s: add driver %s\n", bus->name, drv->name); |
642 | error = kobject_set_name(&drv->kobj, "%s", drv->name); | 641 | |
642 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
643 | if (!priv) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | error = kobject_set_name(&priv->kobj, "%s", drv->name); | ||
643 | if (error) | 647 | if (error) |
644 | goto out_put_bus; | 648 | goto out_put_bus; |
645 | drv->kobj.kset = bus->p->drivers_kset; | 649 | priv->kobj.kset = bus->p->drivers_kset; |
646 | drv->kobj.ktype = &driver_ktype; | 650 | priv->kobj.ktype = &driver_ktype; |
647 | error = kobject_register(&drv->kobj); | 651 | klist_init(&priv->klist_devices, NULL, NULL); |
652 | priv->driver = drv; | ||
653 | drv->p = priv; | ||
654 | error = kobject_register(&priv->kobj); | ||
648 | if (error) | 655 | if (error) |
649 | goto out_put_bus; | 656 | goto out_put_bus; |
650 | 657 | ||
@@ -653,7 +660,7 @@ int bus_add_driver(struct device_driver *drv) | |||
653 | if (error) | 660 | if (error) |
654 | goto out_unregister; | 661 | goto out_unregister; |
655 | } | 662 | } |
656 | klist_add_tail(&drv->knode_bus, &bus->p->klist_drivers); | 663 | klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); |
657 | module_add_driver(drv->owner, drv); | 664 | module_add_driver(drv->owner, drv); |
658 | 665 | ||
659 | error = driver_create_file(drv, &driver_attr_uevent); | 666 | error = driver_create_file(drv, &driver_attr_uevent); |
@@ -676,7 +683,7 @@ int bus_add_driver(struct device_driver *drv) | |||
676 | 683 | ||
677 | return error; | 684 | return error; |
678 | out_unregister: | 685 | out_unregister: |
679 | kobject_unregister(&drv->kobj); | 686 | kobject_unregister(&priv->kobj); |
680 | out_put_bus: | 687 | out_put_bus: |
681 | bus_put(bus); | 688 | bus_put(bus); |
682 | return error; | 689 | return error; |
@@ -699,11 +706,11 @@ void bus_remove_driver(struct device_driver * drv) | |||
699 | remove_bind_files(drv); | 706 | remove_bind_files(drv); |
700 | driver_remove_attrs(drv->bus, drv); | 707 | driver_remove_attrs(drv->bus, drv); |
701 | driver_remove_file(drv, &driver_attr_uevent); | 708 | driver_remove_file(drv, &driver_attr_uevent); |
702 | klist_remove(&drv->knode_bus); | 709 | klist_remove(&drv->p->knode_bus); |
703 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 710 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
704 | driver_detach(drv); | 711 | driver_detach(drv); |
705 | module_remove_driver(drv); | 712 | module_remove_driver(drv); |
706 | kobject_unregister(&drv->kobj); | 713 | kobject_unregister(&drv->p->kobj); |
707 | bus_put(drv->bus); | 714 | bus_put(drv->bus); |
708 | } | 715 | } |
709 | 716 | ||