From: Liu Ping Fan <qemulist@gmail.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>, Avi Kivity <avi@redhat.com>,
Anthony Liguori <anthony@codemonkey.ws>
Subject: [Qemu-devel] [PATCH] qdev: unplug request will propagate and release item bottom-up
Date: Sat, 25 Aug 2012 15:26:47 +0800 [thread overview]
Message-ID: <1345879607-15650-1-git-send-email-qemulist@gmail.com> (raw)
From: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
To achieve uplug a sub tree, we propagate unplug event on the tree.
Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
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
next reply other threads:[~2012-08-25 7:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-25 7:26 Liu Ping Fan [this message]
2012-08-26 14:34 ` [Qemu-devel] [PATCH] qdev: unplug request will propagate and release item bottom-up Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1345879607-15650-1-git-send-email-qemulist@gmail.com \
--to=qemulist@gmail.com \
--cc=anthony@codemonkey.ws \
--cc=avi@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).