summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--hw/acpi_piix4.c10
-rw-r--r--hw/i2c.c5
-rw-r--r--hw/intel-hda.c15
-rw-r--r--hw/lsi53c895a.c5
-rw-r--r--hw/qdev-monitor.c26
-rw-r--r--hw/qdev.c64
-rw-r--r--hw/qdev.h10
-rw-r--r--hw/s390-virtio-bus.c25
-rw-r--r--hw/scsi-bus.c13
-rw-r--r--hw/spapr_pci.c7
-rw-r--r--hw/spapr_vio.c25
-rw-r--r--hw/spapr_vty.c6
-rw-r--r--hw/ssi.c14
-rw-r--r--hw/virtio-scsi.c6
-rw-r--r--qom/object.c11
15 files changed, 159 insertions, 83 deletions
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0345490ee0..a11c8e7ae0 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -284,7 +284,7 @@ static const VMStateDescription vmstate_acpi = {
 
 static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
 {
-    DeviceState *qdev, *next;
+    BusChild *kid, *next;
     BusState *bus = qdev_get_parent_bus(&s->dev.qdev);
     int slot = ffs(slots) - 1;
     bool slot_free = true;
@@ -292,7 +292,8 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
     /* Mark request as complete */
     s->pci0_status.down &= ~(1U << slot);
 
-    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+        DeviceState *qdev = kid->child;
         PCIDevice *dev = PCI_DEVICE(qdev);
         PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
         if (PCI_SLOT(dev->devfn) == slot) {
@@ -313,7 +314,7 @@ static void piix4_update_hotplug(PIIX4PMState *s)
 {
     PCIDevice *dev = &s->dev;
     BusState *bus = qdev_get_parent_bus(&dev->qdev);
-    DeviceState *qdev, *next;
+    BusChild *kid, *next;
 
     /* Execute any pending removes during reset */
     while (s->pci0_status.down) {
@@ -323,7 +324,8 @@ static void piix4_update_hotplug(PIIX4PMState *s)
     s->pci0_hotplug_enable = ~0;
     s->pci0_slot_device_present = 0;
 
-    QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+    QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) {
+        DeviceState *qdev = kid->child;
         PCIDevice *pdev = PCI_DEVICE(qdev);
         PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev);
         int slot = PCI_SLOT(pdev->devfn);
diff --git a/hw/i2c.c b/hw/i2c.c
index 319b249da3..296bece119 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -86,11 +86,12 @@ int i2c_bus_busy(i2c_bus *bus)
 /* TODO: Make this handle multiple masters.  */
 int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     I2CSlave *slave = NULL;
     I2CSlaveClass *sc;
 
-    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev);
         if (candidate->address == address) {
             slave = candidate;
diff --git a/hw/intel-hda.c b/hw/intel-hda.c
index e343096534..c11fd30cab 100644
--- a/hw/intel-hda.c
+++ b/hw/intel-hda.c
@@ -78,10 +78,11 @@ static int hda_codec_dev_exit(DeviceState *qdev)
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     HDACodecDevice *cdev;
 
-    QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         if (cdev->cad == cad) {
             return cdev;
@@ -483,10 +484,11 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st)
 
 static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     HDACodecDevice *cdev;
 
-    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         HDACodecDeviceClass *cdc;
 
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
@@ -1105,15 +1107,16 @@ static const MemoryRegionOps intel_hda_mmio_ops = {
 
 static void intel_hda_reset(DeviceState *dev)
 {
+    BusChild *kid;
     IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev);
-    DeviceState *qdev;
     HDACodecDevice *cdev;
 
     intel_hda_regs_reset(d);
     d->wall_base_ns = qemu_get_clock_ns(vm_clock);
 
     /* reset codecs */
-    QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
         device_reset(DEVICE(cdev));
         d->state_sts |= (1 << cdev->cad);
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index f022a02447..2fe141d24e 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1677,9 +1677,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         if (val & LSI_SCNTL1_RST) {
             if (!(s->sstat0 & LSI_SSTAT0_RST)) {
-                DeviceState *dev;
+                BusChild *kid;
 
-                QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) {
+                QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+                    DeviceState *dev = kid->child;
                     device_reset(dev);
                 }
                 s->sstat0 |= LSI_SSTAT0_RST;
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 691b864c54..17452c8c01 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -205,11 +205,12 @@ static void qbus_list_bus(DeviceState *dev)
 
 static void qbus_list_dev(BusState *bus)
 {
-    DeviceState *dev;
+    BusChild *kid;
     const char *sep = " ";
 
     error_printf("devices at \"%s\":", bus->name);
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
         if (dev->id)
             error_printf("/\"%s\"", dev->id);
@@ -232,7 +233,7 @@ static BusState *qbus_find_bus(DeviceState *dev, char *elem)
 
 static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 {
-    DeviceState *dev;
+    BusChild *kid;
 
     /*
      * try to match in order:
@@ -240,17 +241,20 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
      *   (2) driver name
      *   (3) driver alias, if present
      */
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         if (dev->id  &&  strcmp(dev->id, elem) == 0) {
             return dev;
         }
     }
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
             return dev;
         }
     }
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
         if (qdev_class_has_alias(dc) &&
@@ -264,7 +268,7 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
                                      const char *bus_typename)
 {
-    DeviceState *dev;
+    BusChild *kid;
     BusState *child, *ret;
     int match = 1;
 
@@ -279,7 +283,8 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
         return bus;
     }
 
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         QLIST_FOREACH(child, &dev->child_bus, sibling) {
             ret = qbus_find_recursive(child, name, bus_typename);
             if (ret) {
@@ -533,12 +538,13 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
 
 static void qbus_print(Monitor *mon, BusState *bus, int indent)
 {
-    struct DeviceState *dev;
+    BusChild *kid;
 
     qdev_printf("bus: %s\n", bus->name);
     indent += 2;
     qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
-    QTAILQ_FOREACH(dev, &bus->children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
+        DeviceState *dev = kid->child;
         qdev_print(mon, dev, indent);
     }
 }
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)
diff --git a/hw/qdev.h b/hw/qdev.h
index 736271ecef..e39f82e029 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -74,7 +74,6 @@ struct DeviceState {
     qemu_irq *gpio_in;
     QLIST_HEAD(, BusState) child_bus;
     int num_child_bus;
-    QTAILQ_ENTRY(DeviceState) sibling;
     int instance_id_alias;
     int alias_required_for_version;
 };
@@ -100,6 +99,12 @@ struct BusClass {
     int (*reset)(BusState *bus);
 };
 
+typedef struct BusChild {
+    DeviceState *child;
+    int index;
+    QTAILQ_ENTRY(BusChild) sibling;
+} BusChild;
+
 /**
  * BusState:
  * @qom_allocated: Indicates whether the object was allocated by QOM.
@@ -113,7 +118,8 @@ struct BusState {
     int allow_hotplug;
     bool qom_allocated;
     bool glib_allocated;
-    QTAILQ_HEAD(ChildrenHead, DeviceState) children;
+    int max_index;
+    QTAILQ_HEAD(ChildrenHead, BusChild) children;
     QLIST_ENTRY(BusState) sibling;
 };
 
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 2aec756da1..4d49b96f94 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -315,20 +315,20 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
                                              ram_addr_t mem,
                                              int *vq_num)
 {
-    VirtIOS390Device *_dev;
-    DeviceState *dev;
+    BusChild *kid;
     int i;
 
-    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
-        _dev = (VirtIOS390Device *)dev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
+
         for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
-            if (!virtio_queue_get_addr(_dev->vdev, i))
+            if (!virtio_queue_get_addr(dev->vdev, i))
                 break;
-            if (virtio_queue_get_addr(_dev->vdev, i) == mem) {
+            if (virtio_queue_get_addr(dev->vdev, i) == mem) {
                 if (vq_num) {
                     *vq_num = i;
                 }
-                return _dev;
+                return dev;
             }
         }
     }
@@ -339,13 +339,12 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
 /* Find a device by device descriptor location */
 VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
 {
-    VirtIOS390Device *_dev;
-    DeviceState *dev;
+    BusChild *kid;
 
-    QTAILQ_FOREACH(dev, &bus->bus.children, sibling) {
-        _dev = (VirtIOS390Device *)dev;
-        if (_dev->dev_offs == mem) {
-            return _dev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
+        if (dev->dev_offs == mem) {
+            return dev;
         }
     }
 
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 276c794f47..dbfccdc24a 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -315,7 +315,7 @@ static void store_lun(uint8_t *outbuf, int lun)
 
 static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     int i, len, n;
     int channel, id;
     bool found_lun0;
@@ -330,7 +330,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     id = r->req.dev->id;
     found_lun0 = false;
     n = 0;
-    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
@@ -352,7 +353,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r)
     memset(r->buf, 0, len);
     stl_be_p(&r->buf, n);
     i = found_lun0 ? 8 : 16;
-    QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
@@ -1487,10 +1489,11 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
 
 SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     SCSIDevice *target_dev = NULL;
 
-    QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) {
+    QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) {
+        DeviceState *qdev = kid->child;
         SCSIDevice *dev = SCSI_DEVICE(qdev);
 
         if (dev->channel == channel && dev->id == id) {
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 25b400aa47..97d417a997 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -35,17 +35,18 @@
 static PCIDevice *find_dev(sPAPREnvironment *spapr,
                            uint64_t buid, uint32_t config_addr)
 {
-    DeviceState *qdev;
     int devfn = (config_addr >> 8) & 0xFF;
     sPAPRPHBState *phb;
 
     QLIST_FOREACH(phb, &spapr->phbs, list) {
+        BusChild *kid;
+
         if (phb->buid != buid) {
             continue;
         }
 
-        QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) {
-            PCIDevice *dev = (PCIDevice *)qdev;
+        QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
+            PCIDevice *dev = (PCIDevice *)kid->child;
             if (dev->devfn == devfn) {
                 return dev;
             }
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index b7611ff865..c8271c626c 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -62,11 +62,11 @@ static const TypeInfo spapr_vio_bus_info = {
 
 VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
 {
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *dev = NULL;
 
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
         if (dev->reg == reg) {
             return dev;
         }
@@ -606,7 +606,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
                          uint32_t nret, target_ulong rets)
 {
     VIOsPAPRBus *bus = spapr->vio_bus;
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *dev = NULL;
 
     if (nargs != 0) {
@@ -614,8 +614,8 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
         return;
     }
 
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        dev = (VIOsPAPRDevice *)qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        dev = (VIOsPAPRDevice *)kid->child;
         spapr_vio_quiesce_one(dev);
     }
 
@@ -625,7 +625,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token,
 static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
 {
     VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus);
-    DeviceState *qdev;
+    BusChild *kid;
     VIOsPAPRDevice *other;
 
     /*
@@ -633,8 +633,8 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev)
      * using the requested address. We have to open code this because
      * the given dev might already be in the list.
      */
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child);
 
         if (other != dev && other->reg == dev->reg) {
             return other;
@@ -840,19 +840,20 @@ static int compare_reg(const void *p1, const void *p2)
 int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt)
 {
     DeviceState *qdev, **qdevs;
+    BusChild *kid;
     int i, num, ret = 0;
 
     /* Count qdevs on the bus list */
     num = 0;
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
         num++;
     }
 
     /* Copy out into an array of pointers */
     qdevs = g_malloc(sizeof(qdev) * num);
     num = 0;
-    QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
-        qdevs[num++] = qdev;
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        qdevs[num++] = kid->child;
     }
 
     /* Sort the array */
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index c9674f36a6..f340b83237 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -160,7 +160,7 @@ static TypeInfo spapr_vty_info = {
 VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
 {
     VIOsPAPRDevice *sdev, *selected;
-    DeviceState *iter;
+    BusChild *kid;
 
     /*
      * To avoid the console bouncing around we want one VTY to be
@@ -169,7 +169,9 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus)
      */
 
     selected = NULL;
-    QTAILQ_FOREACH(iter, &bus->bus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
+        DeviceState *iter = kid->child;
+
         /* Only look at VTY devices */
         if (!object_dynamic_cast(OBJECT(iter), "spapr-vty")) {
             continue;
diff --git a/hw/ssi.c b/hw/ssi.c
index 8db99c29e4..e5f14a0cef 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -30,10 +30,11 @@ static int ssi_slave_init(DeviceState *dev)
     SSISlave *s = SSI_SLAVE(dev);
     SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s);
     SSIBus *bus;
+    BusChild *kid;
 
     bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev));
-    if (QTAILQ_FIRST(&bus->qbus.children) != dev
-        || QTAILQ_NEXT(dev, sibling) != NULL) {
+    kid = QTAILQ_FIRST(&bus->qbus.children);
+    if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) {
         hw_error("Too many devices on SSI bus");
     }
 
@@ -72,14 +73,15 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name)
 
 uint32_t ssi_transfer(SSIBus *bus, uint32_t val)
 {
-    DeviceState *dev;
+    BusChild *kid;
     SSISlave *slave;
     SSISlaveClass *ssc;
-    dev = QTAILQ_FIRST(&bus->qbus.children);
-    if (!dev) {
+
+    kid = QTAILQ_FIRST(&bus->qbus.children);
+    if (!kid) {
         return 0;
     }
-    slave = SSI_SLAVE(dev);
+    slave = SSI_SLAVE(kid->child);
     ssc = SSI_SLAVE_GET_CLASS(slave);
     return ssc->transfer(slave, val);
 }
diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 5e39ce93c4..e1a767ea78 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -275,7 +275,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
 {
     SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun);
     SCSIRequest *r, *next;
-    DeviceState *qdev;
+    BusChild *kid;
     int target;
 
     /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE".  */
@@ -346,8 +346,8 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
     case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
         target = req->req.tmf->lun[1];
         s->resetting++;
-        QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) {
-             d = DO_UPCAST(SCSIDevice, qdev, qdev);
+        QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+             d = DO_UPCAST(SCSIDevice, qdev, kid->child);
              if (d->channel == 0 && d->id == target) {
                 qdev_reset_all(&d->qdev);
              }
diff --git a/qom/object.c b/qom/object.c
index d5c6ff7471..27cc651a91 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -689,9 +689,16 @@ void object_property_del(Object *obj, const char *name, Error **errp)
 {
     ObjectProperty *prop = object_property_find(obj, name);
 
-    QTAILQ_REMOVE(&obj->properties, prop, node);
+    if (prop == NULL) {
+        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
+        return;
+    }
+
+    if (prop->release) {
+        prop->release(obj, name, prop->opaque);
+    }
 
-    prop->release(obj, prop->name, prop->opaque);
+    QTAILQ_REMOVE(&obj->properties, prop, node);
 
     g_free(prop->name);
     g_free(prop->type);