summaryrefslogtreecommitdiff
path: root/hw/qdev.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2011-12-23 15:34:39 -0600
committerAndreas Färber <afaerber@suse.de>2012-06-18 15:14:38 +0200
commit0866aca1de15a12547f52ff8563cf7c163e1898e (patch)
tree511c043eb3de19d479f708209e588d828b751903 /hw/qdev.c
parentf968fc6892daf02865cce8af277cc755be690eda (diff)
qbus: Make child devices links
Make qbus children show up as link<> properties. There is no stable addressing for qbus children so we use an unstable naming convention. This is okay in QOM though because the composition name is expected to be what's stable. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Andreas Färber <afaerber@suse.de>
Diffstat (limited to 'hw/qdev.c')
-rw-r--r--hw/qdev.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index dc46e7bd10..fc79b24103 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -60,14 +60,48 @@ bool qdev_exists(const char *name)
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
Error **errp);
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+static void bus_remove_child(BusState *bus, DeviceState *child)
{
+ BusChild *kid;
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ if (kid->child == child) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "child[%d]", kid->index);
+ QTAILQ_REMOVE(&bus->children, kid, sibling);
+ object_property_del(OBJECT(bus), name, NULL);
+ g_free(kid);
+ return;
+ }
+ }
+}
+
+static void bus_add_child(BusState *bus, DeviceState *child)
+{
+ char name[32];
+ BusChild *kid = g_malloc0(sizeof(*kid));
+
if (qdev_hotplug) {
assert(bus->allow_hotplug);
}
+ kid->index = bus->max_index++;
+ kid->child = child;
+
+ QTAILQ_INSERT_HEAD(&bus->children, kid, sibling);
+
+ snprintf(name, sizeof(name), "child[%d]", kid->index);
+ object_property_add_link(OBJECT(bus), name,
+ object_get_typename(OBJECT(child)),
+ (Object **)&kid->child,
+ NULL);
+}
+
+void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+{
dev->parent_bus = bus;
- QTAILQ_INSERT_HEAD(&bus->children, dev, sibling);
+ bus_add_child(bus, dev);
}
/* Create a new device. This only initializes the device state structure
@@ -310,7 +344,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
qbus_walkerfn *busfn, void *opaque)
{
- DeviceState *dev;
+ BusChild *kid;
int err;
if (busfn) {
@@ -320,8 +354,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
}
}
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- err = qdev_walk_children(dev, devfn, busfn, opaque);
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ err = qdev_walk_children(kid->child, devfn, busfn, opaque);
if (err < 0) {
return err;
}
@@ -355,12 +389,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
DeviceState *qdev_find_recursive(BusState *bus, const char *id)
{
- DeviceState *dev, *ret;
+ BusChild *kid;
+ DeviceState *ret;
BusState *child;
- QTAILQ_FOREACH(dev, &bus->children, sibling) {
- if (dev->id && strcmp(dev->id, id) == 0)
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ DeviceState *dev = kid->child;
+
+ if (dev->id && strcmp(dev->id, id) == 0) {
return dev;
+ }
+
QLIST_FOREACH(child, &dev->child_bus, sibling) {
ret = qdev_find_recursive(child, id);
if (ret) {
@@ -431,9 +470,10 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
void qbus_free(BusState *bus)
{
- DeviceState *dev;
+ BusChild *kid;
- while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) {
+ while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
+ DeviceState *dev = kid->child;
qdev_free(dev);
}
if (bus->parent) {
@@ -684,7 +724,9 @@ static void device_finalize(Object *obj)
qemu_opts_del(dev->opts);
}
}
- QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling);
+ if (dev->parent_bus) {
+ bus_remove_child(dev->parent_bus, dev);
+ }
}
static void device_class_base_init(ObjectClass *class, void *data)