[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] qdev: unplug request will propagate and release ite
From: |
Liu Ping Fan |
Subject: |
[Qemu-devel] [PATCH] qdev: unplug request will propagate and release item bottom-up |
Date: |
Sat, 25 Aug 2012 15:26:47 +0800 |
From: Liu Ping Fan <address@hidden>
To achieve uplug a sub tree, we propagate unplug event on the tree.
Signed-off-by: Liu Ping Fan <address@hidden>
---
hw/acpi_piix4.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
hw/qdev.c | 7 ++++-
hw/qdev.h | 2 +
3 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0aace60..49247c5 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -287,6 +287,74 @@ static const VMStateDescription vmstate_acpi = {
}
};
+static void check_release_bus(BusState *bus);
+
+static void check_release_device(DeviceState *dev)
+{
+ Object *obj = OBJECT(dev);
+ BusState *up_b = dev->parent_bus;
+ BusState *child;
+
+ if (dev->unplug_state == 1) {
+ /* a leaf device has no child bus, or empty child bus */
+ QLIST_FOREACH(child, &dev->child_bus, sibling) {
+ if (!QTAILQ_EMPTY(&child->children)) {
+ return;
+ }
+ child->parent = NULL;
+ QLIST_REMOVE(child, sibling);
+ dev->num_child_bus--;
+ object_property_del_child(OBJECT(dev), OBJECT(child), NULL);
+ /* when mmio-dispatch out of big lock, remove it!*/
+ g_assert(OBJECT(child)->ref == 1);
+ object_unref(OBJECT(child));
+ }
+
+ dev->parent_bus = NULL;
+ /* removed from list and bus->dev link */
+ bus_remove_child(up_b, dev);
+ /* remove bus<-dev link */
+ object_property_del(OBJECT(dev), "parent_bus", NULL);
+
+ /* when mmio-dispatch out of big lock, remove it! */
+ g_assert(obj->ref == 1);
+ object_unref(obj);
+ check_release_bus(up_b);
+ }
+}
+
+static void check_release_bus(BusState *bus)
+{
+ Object *obj = OBJECT(bus);
+ DeviceState *d = bus->parent;
+
+ if (bus->unplug_state == 1 && QTAILQ_EMPTY(&bus->children)) {
+ 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);
+ check_release_device(d);
+ }
+}
+
+static void qdev_unplug_complete(DeviceState *qdev)
+{
+ BusState *child;
+
+ /* keep the child<> , until all of the children detached.
+ * Mark dev and its bus going.
+ */
+ qdev->unplug_state = 1;
+ QLIST_FOREACH(child, &qdev->child_bus, sibling) {
+ child->unplug_state = 1;
+ }
+ /* bottom-up through the release chain */
+ check_release_device(qdev);
+}
+
static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots)
{
BusChild *kid, *next;
@@ -305,8 +373,7 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned
slots)
if (pc->no_hotplug) {
slot_free = false;
} else {
- object_unparent(OBJECT(dev));
- qdev_free(qdev);
+ qdev_unplug_complete(qdev);
}
}
}
diff --git a/hw/qdev.c b/hw/qdev.c
index b5b74b9..206e0eb 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -194,7 +194,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int
alias_id,
dev->alias_required_for_version = required_for_version;
}
-void qdev_unplug(DeviceState *dev, Error **errp)
+static void qdev_eject_unplug(DeviceState *dev, Error **errp)
{
DeviceClass *dc = DEVICE_GET_CLASS(dev);
@@ -212,6 +212,11 @@ void qdev_unplug(DeviceState *dev, Error **errp)
}
}
+void qdev_unplug(DeviceState *dev, Error **errp)
+{
+ qdev_walk_children(dev, qdev_eject_unplug, NULL, errp);
+}
+
static int qdev_reset_one(DeviceState *dev, void *opaque)
{
device_reset(dev);
diff --git a/hw/qdev.h b/hw/qdev.h
index d699194..3c09ae7 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -67,6 +67,7 @@ struct DeviceState {
enum DevState state;
QemuOpts *opts;
int hotplugged;
+ int unplug_state;
BusState *parent_bus;
int num_gpio_out;
qemu_irq *gpio_out;
@@ -115,6 +116,7 @@ struct BusState {
DeviceState *parent;
const char *name;
int allow_hotplug;
+ int unplug_state;
bool qom_allocated;
bool glib_allocated;
int max_index;
--
1.7.4.4
- [Qemu-devel] [PATCH] qdev: unplug request will propagate and release item bottom-up,
Liu Ping Fan <=