diff options
Diffstat (limited to 'drivers/base/bus.c')
-rw-r--r-- | drivers/base/bus.c | 54 |
1 files changed, 24 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); |