diff options
author | mochel@digitalimplant.org <mochel@digitalimplant.org> | 2005-03-21 15:00:18 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-20 18:15:14 -0400 |
commit | 38fdac3cdce276554b4484a41f8ec2daf81cb2ff (patch) | |
tree | 1bdd0b8b69bd8e13de53036c8ef8b968a0dacc1d /drivers | |
parent | 465c7a3a3a5aabcedd2e43612cac5a12f23da19a (diff) |
[PATCH] Add a klist to struct bus_type for its drivers.
- Use it in bus_for_each_drv().
- 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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/base/bus.c | 52 |
1 files changed, 23 insertions, 29 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c8da37230b3e..736dc1f5a316 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -135,30 +135,6 @@ static struct kobj_type ktype_bus = { | |||
135 | decl_subsys(bus, &ktype_bus, NULL); | 135 | decl_subsys(bus, &ktype_bus, NULL); |
136 | 136 | ||
137 | 137 | ||
138 | static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | ||
139 | void * data, int (*fn)(struct device_driver *, void *)) | ||
140 | { | ||
141 | struct list_head *head; | ||
142 | struct device_driver *drv; | ||
143 | int error = 0; | ||
144 | |||
145 | if (!(bus = get_bus(bus))) | ||
146 | return -EINVAL; | ||
147 | |||
148 | head = &bus->drivers.list; | ||
149 | drv = list_prepare_entry(start, head, kobj.entry); | ||
150 | list_for_each_entry_continue(drv, head, kobj.entry) { | ||
151 | get_driver(drv); | ||
152 | error = fn(drv, data); | ||
153 | put_driver(drv); | ||
154 | if (error) | ||
155 | break; | ||
156 | } | ||
157 | put_bus(bus); | ||
158 | return error; | ||
159 | } | ||
160 | |||
161 | |||
162 | static struct device * next_device(struct klist_iter * i) | 138 | static struct device * next_device(struct klist_iter * i) |
163 | { | 139 | { |
164 | struct klist_node * n = klist_next(i); | 140 | struct klist_node * n = klist_next(i); |
@@ -203,6 +179,14 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, | |||
203 | return error; | 179 | return error; |
204 | } | 180 | } |
205 | 181 | ||
182 | |||
183 | |||
184 | static struct device_driver * next_driver(struct klist_iter * i) | ||
185 | { | ||
186 | struct klist_node * n = klist_next(i); | ||
187 | return n ? container_of(n, struct device_driver, knode_bus) : NULL; | ||
188 | } | ||
189 | |||
206 | /** | 190 | /** |
207 | * bus_for_each_drv - driver iterator | 191 | * bus_for_each_drv - driver iterator |
208 | * @bus: bus we're dealing with. | 192 | * @bus: bus we're dealing with. |
@@ -226,12 +210,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, | |||
226 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | 210 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, |
227 | void * data, int (*fn)(struct device_driver *, void *)) | 211 | void * data, int (*fn)(struct device_driver *, void *)) |
228 | { | 212 | { |
229 | int ret; | 213 | struct klist_iter i; |
214 | struct device_driver * drv; | ||
215 | int error = 0; | ||
230 | 216 | ||
231 | down_read(&bus->subsys.rwsem); | 217 | if (!bus) |
232 | ret = __bus_for_each_drv(bus, start, data, fn); | 218 | return -EINVAL; |
233 | up_read(&bus->subsys.rwsem); | 219 | |
234 | return ret; | 220 | klist_iter_init_node(&bus->klist_drivers, &i, |
221 | start ? &start->knode_bus : NULL); | ||
222 | while ((drv = next_driver(&i)) && !error) | ||
223 | error = fn(drv, data); | ||
224 | klist_iter_exit(&i); | ||
225 | return error; | ||
235 | } | 226 | } |
236 | 227 | ||
237 | static int device_add_attrs(struct bus_type * bus, struct device * dev) | 228 | static int device_add_attrs(struct bus_type * bus, struct device * dev) |
@@ -376,6 +367,7 @@ int bus_add_driver(struct device_driver * drv) | |||
376 | down_write(&bus->subsys.rwsem); | 367 | down_write(&bus->subsys.rwsem); |
377 | driver_attach(drv); | 368 | driver_attach(drv); |
378 | up_write(&bus->subsys.rwsem); | 369 | up_write(&bus->subsys.rwsem); |
370 | klist_add_tail(&bus->klist_drivers, &drv->knode_bus); | ||
379 | module_add_driver(drv->owner, drv); | 371 | module_add_driver(drv->owner, drv); |
380 | 372 | ||
381 | driver_add_attrs(bus, drv); | 373 | driver_add_attrs(bus, drv); |
@@ -397,6 +389,7 @@ void bus_remove_driver(struct device_driver * drv) | |||
397 | { | 389 | { |
398 | if (drv->bus) { | 390 | if (drv->bus) { |
399 | driver_remove_attrs(drv->bus, drv); | 391 | driver_remove_attrs(drv->bus, drv); |
392 | klist_remove(&drv->knode_bus); | ||
400 | down_write(&drv->bus->subsys.rwsem); | 393 | down_write(&drv->bus->subsys.rwsem); |
401 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 394 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
402 | driver_detach(drv); | 395 | driver_detach(drv); |
@@ -536,6 +529,7 @@ int bus_register(struct bus_type * bus) | |||
536 | goto bus_drivers_fail; | 529 | goto bus_drivers_fail; |
537 | 530 | ||
538 | klist_init(&bus->klist_devices); | 531 | klist_init(&bus->klist_devices); |
532 | klist_init(&bus->klist_drivers); | ||
539 | bus_add_attrs(bus); | 533 | bus_add_attrs(bus); |
540 | 534 | ||
541 | pr_debug("bus type '%s' registered\n", bus->name); | 535 | pr_debug("bus type '%s' registered\n", bus->name); |