qbus: add functions to walk both devices and busses
There are some cases where you want to walk the busses, in particular, when searching for a bus either by name or DeviceInfo. Paolo suggested that we model the return values on how GCC's walkers work which allows an actor to skip child transversal, or terminate walking with a positive value that's returned as the qbus_walk_children's result. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
0389ced419
commit
81699d8a90
46
hw/qdev.c
46
hw/qdev.c
@ -449,6 +449,52 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
||||
qbus_walkerfn *busfn, void *opaque)
|
||||
{
|
||||
DeviceState *dev;
|
||||
int err;
|
||||
|
||||
if (busfn) {
|
||||
err = busfn(bus, opaque);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
QLIST_FOREACH(dev, &bus->children, sibling) {
|
||||
err = qdev_walk_children(dev, devfn, busfn, opaque);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
|
||||
qbus_walkerfn *busfn, void *opaque)
|
||||
{
|
||||
BusState *bus;
|
||||
int err;
|
||||
|
||||
if (devfn) {
|
||||
err = devfn(dev, opaque);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
||||
err = qbus_walk_children(bus, devfn, busfn, opaque);
|
||||
if (err < 0) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BusState *qbus_find_recursive(BusState *bus, const char *name,
|
||||
const BusInfo *info)
|
||||
{
|
||||
|
11
hw/qdev.h
11
hw/qdev.h
@ -173,9 +173,20 @@ BusState *qdev_get_parent_bus(DeviceState *dev);
|
||||
|
||||
/*** BUS API. ***/
|
||||
|
||||
/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
|
||||
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
|
||||
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
|
||||
|
||||
void qbus_create_inplace(BusState *bus, BusInfo *info,
|
||||
DeviceState *parent, const char *name);
|
||||
BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name);
|
||||
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
|
||||
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
|
||||
* 0 otherwise. */
|
||||
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
||||
qbus_walkerfn *busfn, void *opaque);
|
||||
int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
|
||||
qbus_walkerfn *busfn, void *opaque);
|
||||
void qbus_free(BusState *bus);
|
||||
|
||||
#define FROM_QBUS(type, dev) DO_UPCAST(type, qbus, dev)
|
||||
|
Loading…
Reference in New Issue
Block a user