diff options
author | mochel@digitalimplant.org <mochel@digitalimplant.org> | 2005-03-21 14:49:14 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-20 18:15:14 -0400 |
commit | 465c7a3a3a5aabcedd2e43612cac5a12f23da19a (patch) | |
tree | 392dabbfe84d1de3e84b1eb238bfd09d0ade6c4c | |
parent | 9a19fea43616066561e221359596ce532e631395 (diff) |
[PATCH] Add a klist to struct bus_type for its devices.
- Use it for bus_for_each_dev().
- Use the klist spinlock instead of the bus rwsem.
Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/bus.c | 54 | ||||
-rw-r--r-- | include/linux/device.h | 3 |
2 files changed, 27 insertions, 30 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 1b05c1399e37..c8da37230b3e 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -134,28 +134,6 @@ static struct kobj_type ktype_bus = { | |||
134 | 134 | ||
135 | decl_subsys(bus, &ktype_bus, NULL); | 135 | decl_subsys(bus, &ktype_bus, NULL); |
136 | 136 | ||
137 | static int __bus_for_each_dev(struct bus_type *bus, struct device *start, | ||
138 | void *data, int (*fn)(struct device *, void *)) | ||
139 | { | ||
140 | struct list_head *head; | ||
141 | struct device *dev; | ||
142 | int error = 0; | ||
143 | |||
144 | if (!(bus = get_bus(bus))) | ||
145 | return -EINVAL; | ||
146 | |||
147 | head = &bus->devices.list; | ||
148 | dev = list_prepare_entry(start, head, bus_list); | ||
149 | list_for_each_entry_continue(dev, head, bus_list) { | ||
150 | get_device(dev); | ||
151 | error = fn(dev, data); | ||
152 | put_device(dev); | ||
153 | if (error) | ||
154 | break; | ||
155 | } | ||
156 | put_bus(bus); | ||
157 | return error; | ||
158 | } | ||
159 | 137 | ||
160 | static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | 138 | static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, |
161 | void * data, int (*fn)(struct device_driver *, void *)) | 139 | void * data, int (*fn)(struct device_driver *, void *)) |
@@ -180,6 +158,13 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | |||
180 | return error; | 158 | return error; |
181 | } | 159 | } |
182 | 160 | ||
161 | |||
162 | static struct device * next_device(struct klist_iter * i) | ||
163 | { | ||
164 | struct klist_node * n = klist_next(i); | ||
165 | return n ? container_of(n, struct device, knode_bus) : NULL; | ||
166 | } | ||
167 | |||
183 | /** | 168 | /** |
184 | * bus_for_each_dev - device iterator. | 169 | * bus_for_each_dev - device iterator. |
185 | * @bus: bus type. | 170 | * @bus: bus type. |
@@ -203,12 +188,19 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | |||
203 | int bus_for_each_dev(struct bus_type * bus, struct device * start, | 188 | int bus_for_each_dev(struct bus_type * bus, struct device * start, |
204 | void * data, int (*fn)(struct device *, void *)) | 189 | void * data, int (*fn)(struct device *, void *)) |
205 | { | 190 | { |
206 | int ret; | 191 | struct klist_iter i; |
192 | struct device * dev; | ||
193 | int error = 0; | ||
207 | 194 | ||
208 | down_read(&bus->subsys.rwsem); | 195 | if (!bus) |
209 | ret = __bus_for_each_dev(bus, start, data, fn); | 196 | return -EINVAL; |
210 | up_read(&bus->subsys.rwsem); | 197 | |
211 | return ret; | 198 | klist_iter_init_node(&bus->klist_devices, &i, |
199 | (start ? &start->knode_bus : NULL)); | ||
200 | while ((dev = next_device(&i)) && !error) | ||
201 | error = fn(dev, data); | ||
202 | klist_iter_exit(&i); | ||
203 | return error; | ||
212 | } | 204 | } |
213 | 205 | ||
214 | /** | 206 | /** |
@@ -293,6 +285,7 @@ int bus_add_device(struct device * dev) | |||
293 | list_add_tail(&dev->bus_list, &dev->bus->devices.list); | 285 | list_add_tail(&dev->bus_list, &dev->bus->devices.list); |
294 | device_attach(dev); | 286 | device_attach(dev); |
295 | up_write(&dev->bus->subsys.rwsem); | 287 | up_write(&dev->bus->subsys.rwsem); |
288 | klist_add_tail(&bus->klist_devices, &dev->knode_bus); | ||
296 | device_add_attrs(bus, dev); | 289 | device_add_attrs(bus, dev); |
297 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); | 290 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); |
298 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); | 291 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); |
@@ -315,6 +308,7 @@ void bus_remove_device(struct device * dev) | |||
315 | sysfs_remove_link(&dev->kobj, "bus"); | 308 | sysfs_remove_link(&dev->kobj, "bus"); |
316 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | 309 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); |
317 | device_remove_attrs(dev->bus, dev); | 310 | device_remove_attrs(dev->bus, dev); |
311 | klist_remove(&dev->knode_bus); | ||
318 | down_write(&dev->bus->subsys.rwsem); | 312 | down_write(&dev->bus->subsys.rwsem); |
319 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 313 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
320 | device_release_driver(dev); | 314 | device_release_driver(dev); |
@@ -439,9 +433,7 @@ int bus_rescan_devices(struct bus_type * bus) | |||
439 | { | 433 | { |
440 | int count = 0; | 434 | int count = 0; |
441 | 435 | ||
442 | down_write(&bus->subsys.rwsem); | 436 | bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); |
443 | __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); | ||
444 | up_write(&bus->subsys.rwsem); | ||
445 | 437 | ||
446 | return count; | 438 | return count; |
447 | } | 439 | } |
@@ -542,6 +534,8 @@ int bus_register(struct bus_type * bus) | |||
542 | retval = kset_register(&bus->drivers); | 534 | retval = kset_register(&bus->drivers); |
543 | if (retval) | 535 | if (retval) |
544 | goto bus_drivers_fail; | 536 | goto bus_drivers_fail; |
537 | |||
538 | klist_init(&bus->klist_devices); | ||
545 | bus_add_attrs(bus); | 539 | bus_add_attrs(bus); |
546 | 540 | ||
547 | pr_debug("bus type '%s' registered\n", bus->name); | 541 | pr_debug("bus type '%s' registered\n", bus->name); |
diff --git a/include/linux/device.h b/include/linux/device.h index 10f5aa20e041..e36953cf7f14 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
15 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
16 | #include <linux/kobject.h> | 16 | #include <linux/kobject.h> |
17 | #include <linux/klist.h> | ||
17 | #include <linux/list.h> | 18 | #include <linux/list.h> |
18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -51,6 +52,7 @@ struct bus_type { | |||
51 | struct subsystem subsys; | 52 | struct subsystem subsys; |
52 | struct kset drivers; | 53 | struct kset drivers; |
53 | struct kset devices; | 54 | struct kset devices; |
55 | struct klist klist_devices; | ||
54 | 56 | ||
55 | struct bus_attribute * bus_attrs; | 57 | struct bus_attribute * bus_attrs; |
56 | struct device_attribute * dev_attrs; | 58 | struct device_attribute * dev_attrs; |
@@ -262,6 +264,7 @@ struct device { | |||
262 | struct list_head bus_list; /* node in bus's list */ | 264 | struct list_head bus_list; /* node in bus's list */ |
263 | struct list_head driver_list; | 265 | struct list_head driver_list; |
264 | struct list_head children; | 266 | struct list_head children; |
267 | struct klist_node knode_bus; | ||
265 | struct device * parent; | 268 | struct device * parent; |
266 | 269 | ||
267 | struct kobject kobj; | 270 | struct kobject kobj; |