From fae3cd00255e3e51ffd59fedb1bdb91ec96be395 Mon Sep 17 00:00:00 2001 From: "mochel@digitalimplant.org" Date: Mon, 21 Mar 2005 10:59:56 -0800 Subject: [PATCH] Add driver_for_each_device(). Now there's an iterator for accessing each device bound to a driver. Signed-off-by: Patrick Mochel Signed-off-by: Greg Kroah-Hartman Index: linux-2.6.12-rc2/drivers/base/driver.c =================================================================== --- drivers/base/driver.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers/base/driver.c') diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 3b269f7e5213..484fed1985aa 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -18,6 +18,41 @@ #define to_dev(node) container_of(node, struct device, driver_list) #define to_drv(obj) container_of(obj, struct device_driver, kobj) + +/** + * driver_for_each_device - Iterator for devices bound to a driver. + * @drv: Driver we're iterating. + * @data: Data to pass to the callback. + * @fn: Function to call for each device. + * + * Take the bus's rwsem and iterate over the @drv's list of devices, + * calling @fn for each one. + */ + +int driver_for_each_device(struct device_driver * drv, struct device * start, + void * data, int (*fn)(struct device *, void *)) +{ + struct list_head * head; + struct device * dev; + int error = 0; + + down_read(&drv->bus->subsys.rwsem); + head = &drv->devices; + dev = list_prepare_entry(start, head, driver_list); + list_for_each_entry_continue(dev, head, driver_list) { + get_device(dev); + error = fn(dev, data); + put_device(dev); + if (error) + break; + } + up_read(&drv->bus->subsys.rwsem); + return error; +} + +EXPORT_SYMBOL(driver_for_each_device); + + /** * driver_create_file - create sysfs file for driver. * @drv: driver. -- cgit v1.2.2 From 94e7b1c5ff2055571703e38b059afffe17658432 Mon Sep 17 00:00:00 2001 From: "mochel@digitalimplant.org" Date: Mon, 21 Mar 2005 12:25:36 -0800 Subject: [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 Signed-off-by: Greg Kroah-Hartman --- drivers/base/driver.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/base/driver.c') 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 @@ #define to_drv(obj) container_of(obj, struct device_driver, kobj) +static struct device * next_device(struct klist_iter * i) +{ + struct klist_node * n = klist_next(i); + return n ? container_of(n, struct device, knode_driver) : NULL; +} + /** * driver_for_each_device - Iterator for devices bound to a driver. * @drv: Driver we're iterating. @@ -32,21 +38,18 @@ int driver_for_each_device(struct device_driver * drv, struct device * start, void * data, int (*fn)(struct device *, void *)) { - struct list_head * head; + struct klist_iter i; struct device * dev; int error = 0; - down_read(&drv->bus->subsys.rwsem); - head = &drv->devices; - dev = list_prepare_entry(start, head, driver_list); - list_for_each_entry_continue(dev, head, driver_list) { - get_device(dev); + if (!drv) + return -EINVAL; + + klist_iter_init_node(&drv->klist_devices, &i, + start ? &start->knode_driver : NULL); + while ((dev = next_device(&i)) && !error) error = fn(dev, data); - put_device(dev); - if (error) - break; - } - up_read(&drv->bus->subsys.rwsem); + klist_iter_exit(&i); return error; } @@ -120,7 +123,7 @@ void put_driver(struct device_driver * drv) */ int driver_register(struct device_driver * drv) { - INIT_LIST_HEAD(&drv->devices); + klist_init(&drv->klist_devices); init_completion(&drv->unloaded); return bus_add_driver(drv); } -- cgit v1.2.2 From 4d12d2d953ca5e299de6a653f1d0478f670d7bc6 Mon Sep 17 00:00:00 2001 From: "mochel@digitalimplant.org" Date: Thu, 24 Mar 2005 20:08:04 -0800 Subject: [PATCH] Fix up bogus comment. Signed-off-by: Patrick Mochel Signed-off-by: Greg Kroah-Hartman diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- drivers/base/driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/base/driver.c') diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 34bd38aa7eb8..f789b6cb4b56 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -31,8 +31,7 @@ static struct device * next_device(struct klist_iter * i) * @data: Data to pass to the callback. * @fn: Function to call for each device. * - * Take the bus's rwsem and iterate over the @drv's list of devices, - * calling @fn for each one. + * Iterate over the @drv's list of devices calling @fn for each one. */ int driver_for_each_device(struct device_driver * drv, struct device * start, -- cgit v1.2.2 From 126eddfbf8cae8a20c22708192bffcbd77c8a889 Mon Sep 17 00:00:00 2001 From: "gregkh@suse.de" Date: Tue, 22 Mar 2005 12:17:13 -0800 Subject: [PATCH] driver core: change export symbol for driver_for_each_device() Signed-off-by: Greg Kroah-Hartman Index: linux-2.6.12-rc2/drivers/base/driver.c =================================================================== --- drivers/base/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base/driver.c') diff --git a/drivers/base/driver.c b/drivers/base/driver.c index f789b6cb4b56..1b645886e9eb 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -52,7 +52,7 @@ int driver_for_each_device(struct device_driver * drv, struct device * start, return error; } -EXPORT_SYMBOL(driver_for_each_device); +EXPORT_SYMBOL_GPL(driver_for_each_device); /** -- cgit v1.2.2