bacd9b0468
Rebase to qemu-1.7 GA New monitor command blockdev-add for full featured block device hotplug. Performance and functionality improvements for USB 3.0. Many VFIO improvements ACPI tables can be generated by QEMU and can be used by firmware directly. Support creating and writing .vhdx images. qemu-img map: dump detailed image file metadata
142 lines
4.6 KiB
Diff
142 lines
4.6 KiB
Diff
From 60ab1ca9f2a40610902b610fa0a06fccea7f0f57 Mon Sep 17 00:00:00 2001
|
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
Date: Thu, 2 May 2013 11:38:38 +0200
|
|
Subject: [PATCH] qdev: allow both pre- and post-order vists in qdev walking
|
|
functions
|
|
|
|
Resetting should be done in post-order, not pre-order. However,
|
|
qdev_walk_children and qbus_walk_children do not allow this. Fix
|
|
it by adding two extra arguments to the functions.
|
|
|
|
Tested-by: Claudio Bley <cbley@av-test.de>
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
---
|
|
hw/core/qdev.c | 45 +++++++++++++++++++++++++++++++++------------
|
|
include/hw/qdev-core.h | 13 +++++++++----
|
|
2 files changed, 42 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
|
|
index e374a93..5ddf1aa 100644
|
|
--- a/hw/core/qdev.c
|
|
+++ b/hw/core/qdev.c
|
|
@@ -240,12 +240,12 @@ static int qbus_reset_one(BusState *bus, void *opaque)
|
|
|
|
void qdev_reset_all(DeviceState *dev)
|
|
{
|
|
- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
|
|
+ qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
|
|
}
|
|
|
|
void qbus_reset_all(BusState *bus)
|
|
{
|
|
- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
|
|
+ qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
|
|
}
|
|
|
|
void qbus_reset_all_fn(void *opaque)
|
|
@@ -337,49 +337,70 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
|
return NULL;
|
|
}
|
|
|
|
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
|
- qbus_walkerfn *busfn, void *opaque)
|
|
+int qbus_walk_children(BusState *bus,
|
|
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
|
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
|
+ void *opaque)
|
|
{
|
|
BusChild *kid;
|
|
int err;
|
|
|
|
- if (busfn) {
|
|
- err = busfn(bus, opaque);
|
|
+ if (pre_busfn) {
|
|
+ err = pre_busfn(bus, opaque);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
QTAILQ_FOREACH(kid, &bus->children, sibling) {
|
|
- err = qdev_walk_children(kid->child, devfn, busfn, opaque);
|
|
+ err = qdev_walk_children(kid->child,
|
|
+ pre_devfn, pre_busfn,
|
|
+ post_devfn, post_busfn, opaque);
|
|
if (err < 0) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
+ if (post_busfn) {
|
|
+ err = post_busfn(bus, opaque);
|
|
+ if (err) {
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
|
|
- qbus_walkerfn *busfn, void *opaque)
|
|
+int qdev_walk_children(DeviceState *dev,
|
|
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
|
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
|
+ void *opaque)
|
|
{
|
|
BusState *bus;
|
|
int err;
|
|
|
|
- if (devfn) {
|
|
- err = devfn(dev, opaque);
|
|
+ if (pre_devfn) {
|
|
+ err = pre_devfn(dev, opaque);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
|
|
- err = qbus_walk_children(bus, devfn, busfn, opaque);
|
|
+ err = qbus_walk_children(bus, pre_devfn, pre_busfn,
|
|
+ post_devfn, post_busfn, opaque);
|
|
if (err < 0) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
+ if (post_devfn) {
|
|
+ err = post_devfn(dev, opaque);
|
|
+ if (err) {
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
|
|
index f2043a6..ecf5cb3 100644
|
|
--- a/include/hw/qdev-core.h
|
|
+++ b/include/hw/qdev-core.h
|
|
@@ -253,10 +253,15 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam
|
|
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
|
|
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
|
|
* 0 otherwise. */
|
|
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
|
|
- qbus_walkerfn *busfn, void *opaque);
|
|
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
|
|
- qbus_walkerfn *busfn, void *opaque);
|
|
+int qbus_walk_children(BusState *bus,
|
|
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
|
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
|
+ void *opaque);
|
|
+int qdev_walk_children(DeviceState *dev,
|
|
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
|
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
|
+ void *opaque);
|
|
+
|
|
void qdev_reset_all(DeviceState *dev);
|
|
|
|
/**
|