Commit ec0a28d2 authored by Patrick Mochel's avatar Patrick Mochel

driver model: clean up bus_for_each_{dev,drv}

- make sure we check what we get back from get_bus()
- do down_read() instead of down_write(), so multiple people can do iterations
  concurrently.
- Note that devices and drivers are removed from these while doing a down_write(), 
  so all removals will be stalled until the iterators are done.
 
parent 557aebd2
...@@ -43,26 +43,23 @@ int bus_for_each_dev(struct bus_type * bus, void * data, ...@@ -43,26 +43,23 @@ int bus_for_each_dev(struct bus_type * bus, void * data,
int (*callback)(struct device * dev, void * data)) int (*callback)(struct device * dev, void * data))
{ {
struct list_head * node; struct list_head * node;
struct device * prev = NULL;
int error = 0; int error = 0;
get_bus(bus); bus = get_bus(bus);
down_write(&bus->rwsem); if (bus) {
list_for_each(node,&bus->devices) { down_read(&bus->rwsem);
struct device * dev = get_device(to_dev(node)); list_for_each(node,&bus->devices) {
if (dev) { struct device * dev = get_device(to_dev(node));
error = callback(dev,data); if (dev) {
if (prev) error = callback(dev,data);
put_device(prev); put_device(dev);
prev = dev; if (error)
if (error) break;
break; }
} }
up_read(&bus->rwsem);
put_bus(bus);
} }
if (prev)
put_device(prev);
up_write(&bus->rwsem);
put_bus(bus);
return error; return error;
} }
...@@ -70,27 +67,23 @@ int bus_for_each_drv(struct bus_type * bus, void * data, ...@@ -70,27 +67,23 @@ int bus_for_each_drv(struct bus_type * bus, void * data,
int (*callback)(struct device_driver * drv, void * data)) int (*callback)(struct device_driver * drv, void * data))
{ {
struct list_head * node; struct list_head * node;
struct device_driver * prev = NULL;
int error = 0; int error = 0;
/* pin bus in memory */ bus = get_bus(bus);
get_bus(bus); if (bus) {
down_write(&bus->rwsem); down_read(&bus->rwsem);
list_for_each(node,&bus->drivers) { list_for_each(node,&bus->drivers) {
struct device_driver * drv = get_driver(to_drv(node)); struct device_driver * drv = get_driver(to_drv(node));
if (drv) { if (drv) {
error = callback(drv,data); error = callback(drv,data);
if (prev) put_driver(drv);
put_driver(prev); if (error)
prev = drv; break;
if (error) }
break;
} }
up_read(&bus->rwsem);
put_bus(bus);
} }
if (prev)
put_driver(prev);
up_write(&bus->rwsem);
put_bus(bus);
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment