]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/core/qdev.c
qdev: Fix latent bug with compat_props and onboard devices
[mirror_qemu.git] / hw / core / qdev.c
index a9647d42ae538ac7f9a0f2d8a9d63fabf7e0b475..4f3200d54bb1ca4134f201d4bbf3467b8c463e0d 100644 (file)
@@ -236,14 +236,20 @@ HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev)
     return NULL;
 }
 
+HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev)
+{
+    if (dev->parent_bus) {
+        return dev->parent_bus->hotplug_handler;
+    }
+    return NULL;
+}
+
 HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
 {
-    HotplugHandler *hotplug_ctrl;
+    HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
 
-    if (dev->parent_bus && dev->parent_bus->hotplug_handler) {
-        hotplug_ctrl = dev->parent_bus->hotplug_handler;
-    } else {
-        hotplug_ctrl = qdev_get_machine_hotplug_handler(dev);
+    if (hotplug_ctrl == NULL && dev->parent_bus) {
+        hotplug_ctrl = qdev_get_bus_hotplug_handler(dev);
     }
     return hotplug_ctrl;
 }
@@ -972,25 +978,51 @@ static void device_initfn(Object *obj)
     QLIST_INIT(&dev->gpios);
 }
 
-void object_apply_compat_props(Object *obj)
+/*
+ * Global property defaults
+ * Slot 0: accelerator's global property defaults
+ * Slot 1: machine's global property defaults
+ * Each is a GPtrArray of of GlobalProperty.
+ * Applied in order, later entries override earlier ones.
+ */
+static GPtrArray *object_compat_props[2];
+
+/*
+ * Set machine's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_machine_compat_props(GPtrArray *compat_props)
 {
-    if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
-        MachineState *m = MACHINE(qdev_get_machine());
-        MachineClass *mc = MACHINE_GET_CLASS(m);
+    assert(!object_compat_props[1]);
+    object_compat_props[1] = compat_props;
+}
 
-        if (m->accelerator) {
-            AccelClass *ac = ACCEL_GET_CLASS(m->accelerator);
+/*
+ * Set accelerator's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_accelerator_compat_props(GPtrArray *compat_props)
+{
+    assert(!object_compat_props[0]);
+    object_compat_props[0] = compat_props;
+}
 
-            if (ac->compat_props) {
-                object_apply_global_props(obj, ac->compat_props, &error_abort);
-            }
-        }
-        object_apply_global_props(obj, mc->compat_props, &error_abort);
+void object_apply_compat_props(Object *obj)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
+        object_apply_global_props(obj, object_compat_props[i],
+                                  &error_abort);
     }
 }
 
 static void device_post_init(Object *obj)
 {
+    /*
+     * Note: ordered so that the user's global properties take
+     * precedence.
+     */
     object_apply_compat_props(obj);
     qdev_prop_set_globals(DEVICE(obj));
 }