Commit a3500b9e authored by Linus Torvalds's avatar Linus Torvalds

Fix "bus_for_each_dev()" and "bus_for_each_drv()", which did not

correctly handle the "restart from this device/driver" case, and
caused oopses with ieee1394.

This just uses "list_for_each_entry_continue()" instead.

Add helper macro to make usage of "list_for_each_entry_continue()"
a bit more readable.
parent 282f037f
...@@ -158,17 +158,19 @@ decl_subsys(bus,&ktype_bus,NULL); ...@@ -158,17 +158,19 @@ decl_subsys(bus,&ktype_bus,NULL);
int bus_for_each_dev(struct bus_type * bus, struct device * start, int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *)) void * data, int (*fn)(struct device *, void *))
{ {
struct list_head * head, * entry; struct device *dev;
struct list_head * head;
int error = 0; int error = 0;
if (!(bus = get_bus(bus))) if (!(bus = get_bus(bus)))
return -EINVAL; return -EINVAL;
head = start ? &start->bus_list : &bus->devices.list; head = &bus->devices.list;
dev = list_prepare_entry(start, head, bus_list);
down_read(&bus->subsys.rwsem); down_read(&bus->subsys.rwsem);
list_for_each(entry,head) { list_for_each_entry_continue(dev, head, bus_list) {
struct device * dev = get_device(to_dev(entry)); get_device(dev);
error = fn(dev,data); error = fn(dev,data);
put_device(dev); put_device(dev);
if (error) if (error)
...@@ -202,17 +204,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, ...@@ -202,17 +204,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *)) void * data, int (*fn)(struct device_driver *, void *))
{ {
struct list_head * head, * entry; struct list_head * head;
struct device_driver *drv;
int error = 0; int error = 0;
if(!(bus = get_bus(bus))) if(!(bus = get_bus(bus)))
return -EINVAL; return -EINVAL;
head = start ? &start->kobj.entry : &bus->drivers.list; head = &bus->drivers.list;
drv = list_prepare_entry(start, head, kobj.entry);
down_read(&bus->subsys.rwsem); down_read(&bus->subsys.rwsem);
list_for_each(entry,head) { list_for_each_entry_continue(drv, head, kobj.entry) {
struct device_driver * drv = get_driver(to_drv(entry)); get_driver(drv);
error = fn(drv,data); error = fn(drv,data);
put_driver(drv); put_driver(drv);
if(error) if(error)
......
...@@ -343,6 +343,16 @@ static inline void list_splice_init(struct list_head *list, ...@@ -343,6 +343,16 @@ static inline void list_splice_init(struct list_head *list,
pos = list_entry(pos->member.prev, typeof(*pos), member), \ pos = list_entry(pos->member.prev, typeof(*pos), member), \
prefetch(pos->member.prev)) prefetch(pos->member.prev))
/**
* list_prepare_entry - prepare a pos entry for use as a start point in
* list_for_each_entry_continue
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/** /**
* list_for_each_entry_continue - iterate over list of given type * list_for_each_entry_continue - iterate over list of given type
* continuing after existing point * continuing after existing point
......
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