qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 04/10] qdev: introduce new interface to remove compo


From: Liu Ping Fan
Subject: [Qemu-devel] [PATCH 04/10] qdev: introduce new interface to remove composite sub-tree
Date: Fri, 24 Aug 2012 17:49:17 +0800

From: Liu Ping Fan <address@hidden>

When a bridge device removed, all the children bebind it should be
removed. Using qdev_delete_subtree(dev) to emulate this event.
And it is achieved by iterated laughed by qdev_walk_children()

Signed-off-by: Liu Ping Fan <address@hidden>
---
 hw/qdev.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 hw/qdev.h |    1 +
 2 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index ad618dd..570f0bf 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -239,6 +239,50 @@ void qbus_reset_all_fn(void *opaque)
     qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, 0);
 }
 
+static int qdev_device_delete(DeviceState *dev, void *opaque)
+{
+    Object *obj = OBJECT(dev);
+    BusState *b = dev->parent_bus;
+
+    dev->parent_bus = NULL;
+    /* removed from list and bus->dev link */
+    bus_remove_child(b, dev);
+    /* remove bus<-dev link */
+    object_property_del(OBJECT(dev), "parent_bus", NULL);
+
+    /* when mmio-dispatch out of big lock, remove it!
+         * refcnt hold by
+         * object_property_add_child(qdev_get_peripheral(), ., OBJECT(qdev),..)
+         * should be released before here.
+         */
+    g_assert(obj->ref == 1);
+    object_unref(OBJECT(dev));
+
+    return 0;
+}
+
+static int qdev_bus_delete(BusState *bus, void *opaque)
+{
+    Object *obj = OBJECT(bus);
+    DeviceState *d = bus->parent;
+
+    bus->parent = NULL;
+    QLIST_REMOVE(bus, sibling);
+    d->num_child_bus--;
+    object_property_del_child(OBJECT(d), OBJECT(bus), NULL);
+    /* when mmio-dispatch out of big lock, remove it!*/
+    g_assert(obj->ref == 1);
+    object_unref(obj);
+
+    return 0;
+}
+
+/* Delete the composite tree which starts from @dev */
+void qdev_delete_subtree(DeviceState *dev)
+{
+    qdev_walk_children(dev, qdev_device_delete, qdev_bus_delete, NULL, 1);
+}
+
 /* can be used as ->unplug() callback for the simple cases */
 int qdev_simple_unplug_cb(DeviceState *dev)
 {
diff --git a/hw/qdev.h b/hw/qdev.h
index 9fc8b46..6f97990 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -162,6 +162,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int 
alias_id,
                                  int required_for_version);
 void qdev_unplug(DeviceState *dev, Error **errp);
 void qdev_free(DeviceState *dev);
+void qdev_delete_subtree(DeviceState *dev);
 int qdev_simple_unplug_cb(DeviceState *dev);
 void qdev_machine_creation_done(void);
 bool qdev_machine_modified(void);
-- 
1.7.4.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]