diff options
author | mochel@digitalimplant.org <mochel@digitalimplant.org> | 2005-03-21 15:25:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-20 18:15:16 -0400 |
commit | 94e7b1c5ff2055571703e38b059afffe17658432 (patch) | |
tree | 469dbd920087ec62acd88b4985437a78c6786c0e /drivers/base/driver.c | |
parent | 38fdac3cdce276554b4484a41f8ec2daf81cb2ff (diff) |
[PATCH] Add a klist to struct device_driver for the devices bound to it.
- Use it in driver_for_each_device() instead of the regular list_head and stop using
the bus's rwsem for protection.
- Use driver_for_each_device() in driver_detach() so we don't deadlock on the
bus's rwsem.
- Remove ->devices.
- Move klist access and sysfs link access out from under device's semaphore, since
they're synchronized through other means.
Signed-off-by: Patrick Mochel <mochel@digitalimplant.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/driver.c')
-rw-r--r-- | drivers/base/driver.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 484fed1985aa..34bd38aa7eb8 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -19,6 +19,12 @@ | |||
19 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) | 19 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) |
20 | 20 | ||
21 | 21 | ||
22 | static struct device * next_device(struct klist_iter * i) | ||
23 | { | ||
24 | struct klist_node * n = klist_next(i); | ||
25 | return n ? container_of(n, struct device, knode_driver) : NULL; | ||
26 | } | ||
27 | |||
22 | /** | 28 | /** |
23 | * driver_for_each_device - Iterator for devices bound to a driver. | 29 | * driver_for_each_device - Iterator for devices bound to a driver. |
24 | * @drv: Driver we're iterating. | 30 | * @drv: Driver we're iterating. |
@@ -32,21 +38,18 @@ | |||
32 | int driver_for_each_device(struct device_driver * drv, struct device * start, | 38 | int driver_for_each_device(struct device_driver * drv, struct device * start, |
33 | void * data, int (*fn)(struct device *, void *)) | 39 | void * data, int (*fn)(struct device *, void *)) |
34 | { | 40 | { |
35 | struct list_head * head; | 41 | struct klist_iter i; |
36 | struct device * dev; | 42 | struct device * dev; |
37 | int error = 0; | 43 | int error = 0; |
38 | 44 | ||
39 | down_read(&drv->bus->subsys.rwsem); | 45 | if (!drv) |
40 | head = &drv->devices; | 46 | return -EINVAL; |
41 | dev = list_prepare_entry(start, head, driver_list); | 47 | |
42 | list_for_each_entry_continue(dev, head, driver_list) { | 48 | klist_iter_init_node(&drv->klist_devices, &i, |
43 | get_device(dev); | 49 | start ? &start->knode_driver : NULL); |
50 | while ((dev = next_device(&i)) && !error) | ||
44 | error = fn(dev, data); | 51 | error = fn(dev, data); |
45 | put_device(dev); | 52 | klist_iter_exit(&i); |
46 | if (error) | ||
47 | break; | ||
48 | } | ||
49 | up_read(&drv->bus->subsys.rwsem); | ||
50 | return error; | 53 | return error; |
51 | } | 54 | } |
52 | 55 | ||
@@ -120,7 +123,7 @@ void put_driver(struct device_driver * drv) | |||
120 | */ | 123 | */ |
121 | int driver_register(struct device_driver * drv) | 124 | int driver_register(struct device_driver * drv) |
122 | { | 125 | { |
123 | INIT_LIST_HEAD(&drv->devices); | 126 | klist_init(&drv->klist_devices); |
124 | init_completion(&drv->unloaded); | 127 | init_completion(&drv->unloaded); |
125 | return bus_add_driver(drv); | 128 | return bus_add_driver(drv); |
126 | } | 129 | } |