NULL);
}
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
+static bool bus_check_address(BusState *bus, DeviceState *child, Error **errp)
+{
+ BusClass *bc = BUS_GET_CLASS(bus);
+ return !bc->check_address || bc->check_address(bus, child, errp);
+}
+
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp)
{
bool replugging = dev->parent_bus != NULL;
+ if (!bus_check_address(bus, dev, errp)) {
+ return false;
+ }
+
if (replugging) {
/* Keep a reference to the device while it's not plugged into
* any bus, to avoid it potentially evaporating when it is
if (replugging) {
object_unref(OBJECT(dev));
}
+ return true;
}
/* Create a new device. This only initializes the device state
bus = sysbus_get_default();
}
- qdev_set_parent_bus(dev, bus);
+ qdev_set_parent_bus(dev, bus, &error_abort);
object_unref(OBJECT(dev));
return dev;
}
{
object_initialize_child(parent, childname, child, childsize, childtype,
&error_abort, NULL);
- qdev_set_parent_bus(DEVICE(child), sysbus_get_default());
+ qdev_set_parent_bus(DEVICE(child), sysbus_get_default(), &error_abort);
}
static void sysbus_register_types(void)
int i;
Error *local_error = NULL;
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
virtio_pci_force_virtio_1(vpci_dev);
object_property_set_bool(OBJECT(vdev), true, "realized", &local_error);
vpci_dev->common.offset = offset;
/* init virtio bits */
- qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus), &error_abort);
virtio_pci_force_virtio_1(vpci_dev);
object_property_set_bool(OBJECT(g), true, "realized", &err);
if (err) {
/* This device should take care of IOMMU PCI properties */
x86_iommu->type = TYPE_AMD;
- qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus);
+ qdev_set_parent_bus(DEVICE(&s->pci), &bus->qbus, &error_abort);
object_property_set_bool(OBJECT(&s->pci), true, "realized", err);
ret = pci_add_capability(&s->pci.dev, AMDVI_CAPAB_ID_SEC, 0,
AMDVI_CAPAB_SIZE, err);
i8257_dma_init(isa_bus, 0);
/* RTC */
- qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus));
+ qdev_set_parent_bus(DEVICE(&s->rtc), BUS(isa_bus), &error_abort);
qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000);
object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
if (err) {
bus = AUX_BUS(qbus_create(TYPE_AUX_BUS, parent, name));
auxtoi2c = object_new_with_props(TYPE_AUXTOI2C, OBJECT(bus), "i2c",
&error_abort, NULL);
- qdev_set_parent_bus(DEVICE(auxtoi2c), BUS(bus));
+ qdev_set_parent_bus(DEVICE(auxtoi2c), BUS(bus), &error_abort);
bus->bridge = AUXTOI2C(auxtoi2c);
dev = DEVICE(object_new(type));
assert(dev);
- qdev_set_parent_bus(dev, &bus->qbus);
+ qdev_set_parent_bus(dev, &bus->qbus, &error_abort);
return dev;
}
{
object_initialize_child(OBJECT(s), childname, child, childsize, childtype,
&error_abort, NULL);
- qdev_set_parent_bus(DEVICE(child), BUS(&s->macio_bus));
+ qdev_set_parent_bus(DEVICE(child), BUS(&s->macio_bus), &error_abort);
}
static void macio_common_realize(PCIDevice *d, Error **errp)
object_property_set_link(OBJECT(&s->pmu), OBJECT(sysbus_dev), "gpio",
&error_abort);
qdev_prop_set_bit(DEVICE(&s->pmu), "has-adb", ns->has_adb);
- qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus));
+ qdev_set_parent_bus(DEVICE(&s->pmu), BUS(&s->macio_bus), &error_abort);
object_property_set_bool(OBJECT(&s->pmu), true, "realized", &err);
if (err) {
/* CUDA */
object_initialize_child(OBJECT(s), "cuda", &s->cuda, sizeof(s->cuda),
TYPE_CUDA, &error_abort, NULL);
- qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus));
+ qdev_set_parent_bus(DEVICE(&s->cuda), BUS(&s->macio_bus), &error_abort);
qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency",
s->frequency);
error_setg(errp, "virtio_net: couldn't find primary bus");
return false;
}
- qdev_set_parent_bus(n->primary_dev, n->primary_bus);
+ qdev_set_parent_bus(n->primary_dev, n->primary_bus, &error_abort);
n->primary_should_be_hidden = false;
qemu_opt_set_bool(n->primary_device_opts,
"partially_hotplugged", true, &err);
"pcie-bus-address-space");
pci_setup_iommu(pci->bus, designware_pcie_host_set_iommu, s);
- qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
+ qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus), &error_abort);
qdev_init_nofail(DEVICE(&s->root));
}
pci_swizzle_map_irq_fn, s, &s->io_mmio,
&s->io_ioport, 0, 4, TYPE_PCIE_BUS);
- qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus));
+ qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus), &error_abort);
pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq);
qdev_init_nofail(DEVICE(&s->gpex_root));
}
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE);
pci_dev = DEVICE(&s->pci_dev);
- qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus));
+ qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus), &error_abort);
object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr",
NULL);
qdev_prop_set_bit(pci_dev, "multifunction", false);
s->mch.address_space_io,
0, TYPE_PCIE_BUS);
PC_MACHINE(qdev_get_machine())->bus = pci->bus;
- qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
+ qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus), &error_abort);
qdev_init_nofail(DEVICE(&s->mch));
}
#include "hw/qdev-properties.h"
#include "qemu/log.h"
#include "qemu/module.h"
+#include "qapi/error.h"
/* Old and buggy versions of QEMU used the wrong mapping from
* PCI IRQs to system interrupt lines. Unfortunately the Linux
h->bus = &s->pci_bus;
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST);
- qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus));
+ qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus), &error_abort);
for (i = 0; i < 4; i++) {
sysbus_init_irq(sbd, &s->irq[i]);
pci_swizzle_map_irq_fn, s, &s->mmio,
&s->io, 0, 4, TYPE_PCIE_BUS);
- qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
+ qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus), &error_abort);
qdev_init_nofail(DEVICE(&s->root));
}
new = object_new(TYPE_SCLP_QUIESCE);
object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL);
object_unref(new);
- qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
+ qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus), &error_abort);
new = object_new(TYPE_SCLP_CPU_HOTPLUG);
object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL);
object_unref(new);
- qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
+ qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus), &error_abort);
/* the facility will automatically realize the devices via the bus */
}
* as we can't find a fitting bus via the qom tree, we have to add the
* event facility to the sysbus, so e.g. a sclp console can be created.
*/
- qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
+ qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default(), &error_abort);
ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
if (ret == -E2BIG) {
VHostVSockCCWState *dev = VHOST_VSOCK_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
V9fsCCWState *dev = VIRTIO_9P_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
DeviceState *vdev = DEVICE(&dev->vdev);
Error *err = NULL;
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", &err);
if (err) {
error_propagate(errp, err);
VirtIOGPUCcw *dev = VIRTIO_GPU_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
VirtIOInputCcw *dev = VIRTIO_INPUT_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
DeviceState *vdev = DEVICE(&dev->vdev);
Error *err = NULL;
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", &err);
if (err) {
error_propagate(errp, err);
g_free(bus_name);
}
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-serial.h"
#include "virtio-ccw.h"
+#include "qapi/error.h"
static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
{
g_free(bus_name);
}
- qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/qdev-core.h"
#include "hw/sd/sd.h"
#include "qemu/module.h"
+#include "qapi/error.h"
#include "trace.h"
static inline const char *sdbus_name(SDBus *sdbus)
readonly = sc->get_readonly(card);
sdbus_set_inserted(from, false);
- qdev_set_parent_bus(DEVICE(card), &to->qbus);
+ qdev_set_parent_bus(DEVICE(card), &to->qbus, &error_abort);
sdbus_set_inserted(to, true);
sdbus_set_readonly(to, readonly);
}
#include "hw/ssi/ssi.h"
#include "migration/vmstate.h"
#include "qemu/module.h"
+#include "qapi/error.h"
struct SSIBus {
BusState parent_obj;
}
cs_line = qdev_get_gpio_in_named(DEVICE(dev), SSI_GPIO_CS, 0);
- qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus));
+ qdev_set_parent_bus(DEVICE(dev), BUS(arg->bus), &error_abort);
**arg->cs_linep = cs_line;
(*arg->cs_linep)++;
return 0;
vpci_dev->nvectors = vs->conf.num_queues + 3;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
vpci_dev->nvectors = dev->vdev.num_queues + 1;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-user-fs.h"
#include "virtio-pci.h"
+#include "qapi/error.h"
struct VHostUserFSPCI {
VirtIOPCIProxy parent_obj;
vpci_dev->nvectors = dev->vdev.conf.num_request_queues + 1;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
vpci_dev->nvectors = vs->conf.num_queues + 3;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-vsock.h"
#include "qemu/module.h"
+#include "qapi/error.h"
typedef struct VHostVSockPCI VHostVSockPCI;
VHostVSockPCI *dev = VHOST_VSOCK_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/9pfs/virtio-9p.h"
#include "hw/qdev-properties.h"
#include "qemu/module.h"
+#include "qapi/error.h"
/*
* virtio-9p-pci: This extends VirtioPCIProxy.
V9fsPCIState *dev = VIRTIO_9P_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
vpci_dev->class_code = PCI_CLASS_OTHERS;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
vpci_dev->nvectors = dev->vdev.conf.num_queues + 1;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
return;
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
virtio_pci_force_virtio_1(vpci_dev);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
object_property_set_link(OBJECT(vcrypto),
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio-input.h"
#include "qemu/module.h"
+#include "qapi/error.h"
typedef struct VirtIOInputPCI VirtIOInputPCI;
typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&vinput->vdev);
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
virtio_pci_force_virtio_1(vpci_dev);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
VirtIOPMEMPCI *pmem_pci = VIRTIO_PMEM_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&pmem_pci->vdev);
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
DeviceState *vdev = DEVICE(&vrng->vdev);
Error *err = NULL;
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", &err);
if (err) {
error_propagate(errp, err);
#include "hw/virtio/virtio-scsi.h"
#include "qemu/module.h"
#include "virtio-pci.h"
+#include "qapi/error.h"
typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
g_free(bus_name);
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
#include "hw/virtio/virtio-serial.h"
#include "qemu/module.h"
#include "virtio-pci.h"
+#include "qapi/error.h"
typedef struct VirtIOSerialPCI VirtIOSerialPCI;
g_free(bus_name);
}
- qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+ qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus), &error_abort);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
}
xendev = g_malloc0(ops->size);
object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
OBJECT(xendev)->free = g_free;
- qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
+ qdev_set_parent_bus(DEVICE(xendev), xen_sysbus, &error_abort);
qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
qdev_init_nofail(DEVICE(xendev));
object_unref(OBJECT(xendev));
/* FIXME first arg should be BusState */
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
char *(*get_dev_path)(DeviceState *dev);
+
/*
* This callback is used to create Open Firmware device path in accordance
* with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
* bindings can be found at http://playground.sun.com/1275/bindings/.
*/
char *(*get_fw_dev_path)(DeviceState *dev);
+
void (*reset)(BusState *bus);
+
+ /*
+ * Return whether the device can be added to @bus,
+ * based on the address that was set (via device properties)
+ * before realize. If not, on return @errp contains the
+ * human-readable error message.
+ */
+ bool (*check_address)(BusState *bus, DeviceState *dev, Error **errp);
+
BusRealize realize;
BusUnrealize unrealize;
Object *qdev_get_machine(void);
/* FIXME: make this a link<> */
-void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
+bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
extern bool qdev_hotplug;
extern bool qdev_hot_removed;
}
if (bus) {
- qdev_set_parent_bus(dev, bus);
+ qdev_set_parent_bus(dev, bus, &error_abort);
} else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
/* No bus, no machine hotplug handler --> device is not hotpluggable */
error_setg(&err, "Device '%s' can not be hotplugged on this machine",