diff options
-rw-r--r-- | drivers/base/base.h | 8 | ||||
-rw-r--r-- | drivers/base/bus.c | 71 | ||||
-rw-r--r-- | drivers/base/dd.c | 24 | ||||
-rw-r--r-- | drivers/base/driver.c | 40 | ||||
-rw-r--r-- | drivers/base/module.c | 12 | ||||
-rw-r--r-- | drivers/base/platform.c | 2 | ||||
-rw-r--r-- | include/linux/device.h | 16 |
7 files changed, 99 insertions, 74 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index 05472360f6a2..3b0f395552db 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -27,6 +27,14 @@ struct bus_type_private { | |||
27 | struct bus_type *bus; | 27 | struct bus_type *bus; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | struct driver_private { | ||
31 | struct kobject kobj; | ||
32 | struct klist klist_devices; | ||
33 | struct klist_node knode_bus; | ||
34 | struct module_kobject *mkobj; | ||
35 | struct device_driver *driver; | ||
36 | }; | ||
37 | #define to_driver(obj) container_of(obj, struct driver_private, kobj) | ||
30 | 38 | ||
31 | /* initialisation functions */ | 39 | /* initialisation functions */ |
32 | extern int devices_init(void); | 40 | extern int devices_init(void); |
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 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 7bf0e674c975..87a348ce818c 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -11,6 +11,8 @@ | |||
11 | * | 11 | * |
12 | * Copyright (c) 2002-5 Patrick Mochel | 12 | * Copyright (c) 2002-5 Patrick Mochel |
13 | * Copyright (c) 2002-3 Open Source Development Labs | 13 | * Copyright (c) 2002-3 Open Source Development Labs |
14 | * Copyright (c) 2007 Greg Kroah-Hartman <gregkh@suse.de> | ||
15 | * Copyright (c) 2007 Novell Inc. | ||
14 | * | 16 | * |
15 | * This file is released under the GPLv2 | 17 | * This file is released under the GPLv2 |
16 | */ | 18 | */ |
@@ -23,8 +25,6 @@ | |||
23 | #include "base.h" | 25 | #include "base.h" |
24 | #include "power/power.h" | 26 | #include "power/power.h" |
25 | 27 | ||
26 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) | ||
27 | |||
28 | 28 | ||
29 | static void driver_bound(struct device *dev) | 29 | static void driver_bound(struct device *dev) |
30 | { | 30 | { |
@@ -41,20 +41,20 @@ static void driver_bound(struct device *dev) | |||
41 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 41 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
42 | BUS_NOTIFY_BOUND_DRIVER, dev); | 42 | BUS_NOTIFY_BOUND_DRIVER, dev); |
43 | 43 | ||
44 | klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); | 44 | klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices); |
45 | } | 45 | } |
46 | 46 | ||
47 | static int driver_sysfs_add(struct device *dev) | 47 | static int driver_sysfs_add(struct device *dev) |
48 | { | 48 | { |
49 | int ret; | 49 | int ret; |
50 | 50 | ||
51 | ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, | 51 | ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, |
52 | kobject_name(&dev->kobj)); | 52 | kobject_name(&dev->kobj)); |
53 | if (ret == 0) { | 53 | if (ret == 0) { |
54 | ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj, | 54 | ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj, |
55 | "driver"); | 55 | "driver"); |
56 | if (ret) | 56 | if (ret) |
57 | sysfs_remove_link(&dev->driver->kobj, | 57 | sysfs_remove_link(&dev->driver->p->kobj, |
58 | kobject_name(&dev->kobj)); | 58 | kobject_name(&dev->kobj)); |
59 | } | 59 | } |
60 | return ret; | 60 | return ret; |
@@ -65,7 +65,7 @@ static void driver_sysfs_remove(struct device *dev) | |||
65 | struct device_driver *drv = dev->driver; | 65 | struct device_driver *drv = dev->driver; |
66 | 66 | ||
67 | if (drv) { | 67 | if (drv) { |
68 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | 68 | sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj)); |
69 | sysfs_remove_link(&dev->kobj, "driver"); | 69 | sysfs_remove_link(&dev->kobj, "driver"); |
70 | } | 70 | } |
71 | } | 71 | } |
@@ -339,15 +339,15 @@ void driver_detach(struct device_driver * drv) | |||
339 | struct device * dev; | 339 | struct device * dev; |
340 | 340 | ||
341 | for (;;) { | 341 | for (;;) { |
342 | spin_lock(&drv->klist_devices.k_lock); | 342 | spin_lock(&drv->p->klist_devices.k_lock); |
343 | if (list_empty(&drv->klist_devices.k_list)) { | 343 | if (list_empty(&drv->p->klist_devices.k_list)) { |
344 | spin_unlock(&drv->klist_devices.k_lock); | 344 | spin_unlock(&drv->p->klist_devices.k_lock); |
345 | break; | 345 | break; |
346 | } | 346 | } |
347 | dev = list_entry(drv->klist_devices.k_list.prev, | 347 | dev = list_entry(drv->p->klist_devices.k_list.prev, |
348 | struct device, knode_driver.n_node); | 348 | struct device, knode_driver.n_node); |
349 | get_device(dev); | 349 | get_device(dev); |
350 | spin_unlock(&drv->klist_devices.k_lock); | 350 | spin_unlock(&drv->p->klist_devices.k_lock); |
351 | 351 | ||
352 | if (dev->parent) /* Needed for USB */ | 352 | if (dev->parent) /* Needed for USB */ |
353 | down(&dev->parent->sem); | 353 | down(&dev->parent->sem); |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 633ae1d70e14..5aacff208f21 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.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 | * |
@@ -15,7 +17,6 @@ | |||
15 | #include "base.h" | 17 | #include "base.h" |
16 | 18 | ||
17 | #define to_dev(node) container_of(node, struct device, driver_list) | 19 | #define to_dev(node) container_of(node, struct device, driver_list) |
18 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) | ||
19 | 20 | ||
20 | 21 | ||
21 | static struct device * next_device(struct klist_iter * i) | 22 | 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, | |||
44 | if (!drv) | 45 | if (!drv) |
45 | return -EINVAL; | 46 | return -EINVAL; |
46 | 47 | ||
47 | klist_iter_init_node(&drv->klist_devices, &i, | 48 | klist_iter_init_node(&drv->p->klist_devices, &i, |
48 | start ? &start->knode_driver : NULL); | 49 | start ? &start->knode_driver : NULL); |
49 | while ((dev = next_device(&i)) && !error) | 50 | while ((dev = next_device(&i)) && !error) |
50 | error = fn(dev, data); | 51 | error = fn(dev, data); |
@@ -80,7 +81,7 @@ struct device * driver_find_device(struct device_driver *drv, | |||
80 | if (!drv) | 81 | if (!drv) |
81 | return NULL; | 82 | return NULL; |
82 | 83 | ||
83 | klist_iter_init_node(&drv->klist_devices, &i, | 84 | klist_iter_init_node(&drv->p->klist_devices, &i, |
84 | (start ? &start->knode_driver : NULL)); | 85 | (start ? &start->knode_driver : NULL)); |
85 | while ((dev = next_device(&i))) | 86 | while ((dev = next_device(&i))) |
86 | if (match(dev, data) && get_device(dev)) | 87 | if (match(dev, data) && get_device(dev)) |
@@ -100,7 +101,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att | |||
100 | { | 101 | { |
101 | int error; | 102 | int error; |
102 | if (get_driver(drv)) { | 103 | if (get_driver(drv)) { |
103 | error = sysfs_create_file(&drv->kobj, &attr->attr); | 104 | error = sysfs_create_file(&drv->p->kobj, &attr->attr); |
104 | put_driver(drv); | 105 | put_driver(drv); |
105 | } else | 106 | } else |
106 | error = -EINVAL; | 107 | error = -EINVAL; |
@@ -117,7 +118,7 @@ int driver_create_file(struct device_driver * drv, struct driver_attribute * att | |||
117 | void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) | 118 | void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr) |
118 | { | 119 | { |
119 | if (get_driver(drv)) { | 120 | if (get_driver(drv)) { |
120 | sysfs_remove_file(&drv->kobj, &attr->attr); | 121 | sysfs_remove_file(&drv->p->kobj, &attr->attr); |
121 | put_driver(drv); | 122 | put_driver(drv); |
122 | } | 123 | } |
123 | } | 124 | } |
@@ -143,7 +144,7 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj, | |||
143 | if (!name) | 144 | if (!name) |
144 | return -ENOMEM; | 145 | return -ENOMEM; |
145 | 146 | ||
146 | return kobject_add_ng(kobj, &drv->kobj, "%s", name); | 147 | return kobject_add_ng(kobj, &drv->p->kobj, "%s", name); |
147 | } | 148 | } |
148 | EXPORT_SYMBOL_GPL(driver_add_kobj); | 149 | EXPORT_SYMBOL_GPL(driver_add_kobj); |
149 | 150 | ||
@@ -153,7 +154,15 @@ EXPORT_SYMBOL_GPL(driver_add_kobj); | |||
153 | */ | 154 | */ |
154 | struct device_driver * get_driver(struct device_driver * drv) | 155 | struct device_driver * get_driver(struct device_driver * drv) |
155 | { | 156 | { |
156 | return drv ? to_drv(kobject_get(&drv->kobj)) : NULL; | 157 | if (drv) { |
158 | struct driver_private *priv; | ||
159 | struct kobject *kobj; | ||
160 | |||
161 | kobj = kobject_get(&drv->p->kobj); | ||
162 | priv = to_driver(kobj); | ||
163 | return priv->driver; | ||
164 | } | ||
165 | return NULL; | ||
157 | } | 166 | } |
158 | 167 | ||
159 | 168 | ||
@@ -163,7 +172,7 @@ struct device_driver * get_driver(struct device_driver * drv) | |||
163 | */ | 172 | */ |
164 | void put_driver(struct device_driver * drv) | 173 | void put_driver(struct device_driver * drv) |
165 | { | 174 | { |
166 | kobject_put(&drv->kobj); | 175 | kobject_put(&drv->p->kobj); |
167 | } | 176 | } |
168 | 177 | ||
169 | static int driver_add_groups(struct device_driver *drv, | 178 | static int driver_add_groups(struct device_driver *drv, |
@@ -174,10 +183,10 @@ static int driver_add_groups(struct device_driver *drv, | |||
174 | 183 | ||
175 | if (groups) { | 184 | if (groups) { |
176 | for (i = 0; groups[i]; i++) { | 185 | for (i = 0; groups[i]; i++) { |
177 | error = sysfs_create_group(&drv->kobj, groups[i]); | 186 | error = sysfs_create_group(&drv->p->kobj, groups[i]); |
178 | if (error) { | 187 | if (error) { |
179 | while (--i >= 0) | 188 | while (--i >= 0) |
180 | sysfs_remove_group(&drv->kobj, | 189 | sysfs_remove_group(&drv->p->kobj, |
181 | groups[i]); | 190 | groups[i]); |
182 | break; | 191 | break; |
183 | } | 192 | } |
@@ -193,7 +202,7 @@ static void driver_remove_groups(struct device_driver *drv, | |||
193 | 202 | ||
194 | if (groups) | 203 | if (groups) |
195 | for (i = 0; groups[i]; i++) | 204 | for (i = 0; groups[i]; i++) |
196 | sysfs_remove_group(&drv->kobj, groups[i]); | 205 | sysfs_remove_group(&drv->p->kobj, groups[i]); |
197 | } | 206 | } |
198 | 207 | ||
199 | 208 | ||
@@ -214,7 +223,6 @@ int driver_register(struct device_driver * drv) | |||
214 | (drv->bus->shutdown && drv->shutdown)) { | 223 | (drv->bus->shutdown && drv->shutdown)) { |
215 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); | 224 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); |
216 | } | 225 | } |
217 | klist_init(&drv->klist_devices, NULL, NULL); | ||
218 | ret = bus_add_driver(drv); | 226 | ret = bus_add_driver(drv); |
219 | if (ret) | 227 | if (ret) |
220 | return ret; | 228 | return ret; |
@@ -250,8 +258,12 @@ void driver_unregister(struct device_driver * drv) | |||
250 | struct device_driver *driver_find(const char *name, struct bus_type *bus) | 258 | struct device_driver *driver_find(const char *name, struct bus_type *bus) |
251 | { | 259 | { |
252 | struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); | 260 | struct kobject *k = kset_find_obj(bus->p->drivers_kset, name); |
253 | if (k) | 261 | struct driver_private *priv; |
254 | return to_drv(k); | 262 | |
263 | if (k) { | ||
264 | priv = to_driver(k); | ||
265 | return priv->driver; | ||
266 | } | ||
255 | return NULL; | 267 | return NULL; |
256 | } | 268 | } |
257 | 269 | ||
diff --git a/drivers/base/module.c b/drivers/base/module.c index cad07be5de1a..103be9cacb05 100644 --- a/drivers/base/module.c +++ b/drivers/base/module.c | |||
@@ -50,7 +50,7 @@ void module_add_driver(struct module *mod, struct device_driver *drv) | |||
50 | if (mkobj) { | 50 | if (mkobj) { |
51 | mk = container_of(mkobj, struct module_kobject, kobj); | 51 | mk = container_of(mkobj, struct module_kobject, kobj); |
52 | /* remember our module structure */ | 52 | /* remember our module structure */ |
53 | drv->mkobj = mk; | 53 | drv->p->mkobj = mk; |
54 | /* kset_find_obj took a reference */ | 54 | /* kset_find_obj took a reference */ |
55 | kobject_put(mkobj); | 55 | kobject_put(mkobj); |
56 | } | 56 | } |
@@ -60,11 +60,11 @@ void module_add_driver(struct module *mod, struct device_driver *drv) | |||
60 | return; | 60 | return; |
61 | 61 | ||
62 | /* Don't check return codes; these calls are idempotent */ | 62 | /* Don't check return codes; these calls are idempotent */ |
63 | no_warn = sysfs_create_link(&drv->kobj, &mk->kobj, "module"); | 63 | no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module"); |
64 | driver_name = make_driver_name(drv); | 64 | driver_name = make_driver_name(drv); |
65 | if (driver_name) { | 65 | if (driver_name) { |
66 | module_create_drivers_dir(mk); | 66 | module_create_drivers_dir(mk); |
67 | no_warn = sysfs_create_link(mk->drivers_dir, &drv->kobj, | 67 | no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj, |
68 | driver_name); | 68 | driver_name); |
69 | kfree(driver_name); | 69 | kfree(driver_name); |
70 | } | 70 | } |
@@ -78,12 +78,12 @@ void module_remove_driver(struct device_driver *drv) | |||
78 | if (!drv) | 78 | if (!drv) |
79 | return; | 79 | return; |
80 | 80 | ||
81 | sysfs_remove_link(&drv->kobj, "module"); | 81 | sysfs_remove_link(&drv->p->kobj, "module"); |
82 | 82 | ||
83 | if (drv->owner) | 83 | if (drv->owner) |
84 | mk = &drv->owner->mkobj; | 84 | mk = &drv->owner->mkobj; |
85 | else if (drv->mkobj) | 85 | else if (drv->p->mkobj) |
86 | mk = drv->mkobj; | 86 | mk = drv->p->mkobj; |
87 | if (mk && mk->drivers_dir) { | 87 | if (mk && mk->drivers_dir) { |
88 | driver_name = make_driver_name(drv); | 88 | driver_name = make_driver_name(drv); |
89 | if (driver_name) { | 89 | if (driver_name) { |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d56a05f94f67..bdd59e8358f0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -499,7 +499,7 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, | |||
499 | */ | 499 | */ |
500 | spin_lock(&platform_bus_type.p->klist_drivers.k_lock); | 500 | spin_lock(&platform_bus_type.p->klist_drivers.k_lock); |
501 | drv->probe = NULL; | 501 | drv->probe = NULL; |
502 | if (code == 0 && list_empty(&drv->driver.klist_devices.k_list)) | 502 | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) |
503 | retval = -ENODEV; | 503 | retval = -ENODEV; |
504 | drv->driver.probe = platform_drv_probe_fail; | 504 | drv->driver.probe = platform_drv_probe_fail; |
505 | spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); | 505 | spin_unlock(&platform_bus_type.p->klist_drivers.k_lock); |
diff --git a/include/linux/device.h b/include/linux/device.h index 721ee318d57b..92ba3a874627 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | struct device; | 33 | struct device; |
34 | struct device_driver; | 34 | struct device_driver; |
35 | struct driver_private; | ||
35 | struct class; | 36 | struct class; |
36 | struct class_device; | 37 | struct class_device; |
37 | struct bus_type; | 38 | struct bus_type; |
@@ -113,16 +114,11 @@ extern struct kset *bus_get_kset(struct bus_type *bus); | |||
113 | extern struct klist *bus_get_device_klist(struct bus_type *bus); | 114 | extern struct klist *bus_get_device_klist(struct bus_type *bus); |
114 | 115 | ||
115 | struct device_driver { | 116 | struct device_driver { |
116 | const char * name; | 117 | const char *name; |
117 | struct bus_type * bus; | 118 | struct bus_type *bus; |
118 | |||
119 | struct kobject kobj; | ||
120 | struct klist klist_devices; | ||
121 | struct klist_node knode_bus; | ||
122 | 119 | ||
123 | struct module * owner; | 120 | struct module *owner; |
124 | const char * mod_name; /* used for built-in modules */ | 121 | const char *mod_name; /* used for built-in modules */ |
125 | struct module_kobject * mkobj; | ||
126 | 122 | ||
127 | int (*probe) (struct device * dev); | 123 | int (*probe) (struct device * dev); |
128 | int (*remove) (struct device * dev); | 124 | int (*remove) (struct device * dev); |
@@ -130,6 +126,8 @@ struct device_driver { | |||
130 | int (*suspend) (struct device * dev, pm_message_t state); | 126 | int (*suspend) (struct device * dev, pm_message_t state); |
131 | int (*resume) (struct device * dev); | 127 | int (*resume) (struct device * dev); |
132 | struct attribute_group **groups; | 128 | struct attribute_group **groups; |
129 | |||
130 | struct driver_private *p; | ||
133 | }; | 131 | }; |
134 | 132 | ||
135 | 133 | ||