|
|
45bdef |
From 6e6d80327eb2e249daaa0937468248d54222b125 Mon Sep 17 00:00:00 2001
|
|
|
9e0a86 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9e0a86 |
Date: Thu, 2 May 2013 11:38:39 +0200
|
|
|
9e0a86 |
Subject: [PATCH] qdev: switch reset to post-order
|
|
|
9e0a86 |
|
|
|
9e0a86 |
Post-order is the only sensible direction for the reset signals.
|
|
|
9e0a86 |
For example, suppose pre-order is used and the parent has some data
|
|
|
9e0a86 |
structures that cache children state (for example a list of active
|
|
|
9e0a86 |
requests). When the reset method is invoked on the parent, these caches
|
|
|
9e0a86 |
could be in any state.
|
|
|
9e0a86 |
|
|
|
9e0a86 |
If post-order is used, on the other hand, these will be in a known state
|
|
|
9e0a86 |
when the reset method is invoked on the parent.
|
|
|
9e0a86 |
|
|
|
9e0a86 |
This change means that it is no longer possible to block the visit of
|
|
|
9e0a86 |
the devices, so the callback is changed to return void. This is not
|
|
|
9e0a86 |
a problem, because PCI was returning 1 exactly in order to achieve the
|
|
|
9e0a86 |
same ordering that this patch implements.
|
|
|
9e0a86 |
|
|
|
9e0a86 |
PCI can then rely on the qdev core having sent a "reset signal"
|
|
|
9e0a86 |
(whatever that means) to the device, and only do the PCI-specific
|
|
|
9e0a86 |
initialization with the new function pci_do_device_reset, extracted
|
|
|
9e0a86 |
from pci_device_reset. There is no change in the operation of FLR,
|
|
|
9e0a86 |
which used and still uses pci_device_reset.
|
|
|
9e0a86 |
|
|
|
9e0a86 |
Tested-by: Claudio Bley <cbley@av-test.de>
|
|
|
9e0a86 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9e0a86 |
---
|
|
|
9e0a86 |
hw/core/qdev.c | 6 +++---
|
|
|
9e0a86 |
hw/pci/pci.c | 31 ++++++++++++++++---------------
|
|
|
9e0a86 |
include/hw/qdev-core.h | 2 +-
|
|
|
9e0a86 |
3 files changed, 20 insertions(+), 19 deletions(-)
|
|
|
9e0a86 |
|
|
|
9e0a86 |
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
|
|
|
45bdef |
index 5ddf1aa..d2ffe35 100644
|
|
|
9e0a86 |
--- a/hw/core/qdev.c
|
|
|
9e0a86 |
+++ b/hw/core/qdev.c
|
|
|
9e0a86 |
@@ -233,19 +233,19 @@ static int qbus_reset_one(BusState *bus, void *opaque)
|
|
|
9e0a86 |
{
|
|
|
9e0a86 |
BusClass *bc = BUS_GET_CLASS(bus);
|
|
|
9e0a86 |
if (bc->reset) {
|
|
|
9e0a86 |
- return bc->reset(bus);
|
|
|
9e0a86 |
+ bc->reset(bus);
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
return 0;
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
void qdev_reset_all(DeviceState *dev)
|
|
|
9e0a86 |
{
|
|
|
9e0a86 |
- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
|
|
|
9e0a86 |
+ qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
void qbus_reset_all(BusState *bus)
|
|
|
9e0a86 |
{
|
|
|
9e0a86 |
- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL, NULL, NULL);
|
|
|
9e0a86 |
+ qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
void qbus_reset_all_fn(void *opaque)
|
|
|
9e0a86 |
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
|
|
|
45bdef |
index ab73b4c..b52df14 100644
|
|
|
9e0a86 |
--- a/hw/pci/pci.c
|
|
|
9e0a86 |
+++ b/hw/pci/pci.c
|
|
|
9e0a86 |
@@ -46,7 +46,7 @@
|
|
|
9e0a86 |
static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
|
|
|
9e0a86 |
static char *pcibus_get_dev_path(DeviceState *dev);
|
|
|
9e0a86 |
static char *pcibus_get_fw_dev_path(DeviceState *dev);
|
|
|
9e0a86 |
-static int pcibus_reset(BusState *qbus);
|
|
|
9e0a86 |
+static void pcibus_reset(BusState *qbus);
|
|
|
9e0a86 |
|
|
|
9e0a86 |
static Property pci_props[] = {
|
|
|
9e0a86 |
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
|
|
|
9e0a86 |
@@ -165,16 +165,10 @@ void pci_device_deassert_intx(PCIDevice *dev)
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
-/*
|
|
|
9e0a86 |
- * This function is called on #RST and FLR.
|
|
|
9e0a86 |
- * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
|
|
|
9e0a86 |
- */
|
|
|
9e0a86 |
-void pci_device_reset(PCIDevice *dev)
|
|
|
9e0a86 |
+static void pci_do_device_reset(PCIDevice *dev)
|
|
|
9e0a86 |
{
|
|
|
9e0a86 |
int r;
|
|
|
9e0a86 |
|
|
|
9e0a86 |
- qdev_reset_all(&dev->qdev);
|
|
|
9e0a86 |
-
|
|
|
9e0a86 |
dev->irq_state = 0;
|
|
|
9e0a86 |
pci_update_irq_status(dev);
|
|
|
9e0a86 |
pci_device_deassert_intx(dev);
|
|
|
9e0a86 |
@@ -207,10 +201,21 @@ void pci_device_reset(PCIDevice *dev)
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
/*
|
|
|
9e0a86 |
+ * This function is called on #RST and FLR.
|
|
|
9e0a86 |
+ * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
|
|
|
9e0a86 |
+ */
|
|
|
9e0a86 |
+void pci_device_reset(PCIDevice *dev)
|
|
|
9e0a86 |
+{
|
|
|
9e0a86 |
+ qdev_reset_all(&dev->qdev);
|
|
|
9e0a86 |
+ pci_do_device_reset(dev);
|
|
|
9e0a86 |
+}
|
|
|
9e0a86 |
+
|
|
|
9e0a86 |
+/*
|
|
|
9e0a86 |
* Trigger pci bus reset under a given bus.
|
|
|
9e0a86 |
- * To be called on RST# assert.
|
|
|
9e0a86 |
+ * Called via qbus_reset_all on RST# assert, after the devices
|
|
|
9e0a86 |
+ * have been reset qdev_reset_all-ed already.
|
|
|
9e0a86 |
*/
|
|
|
9e0a86 |
-static int pcibus_reset(BusState *qbus)
|
|
|
9e0a86 |
+static void pcibus_reset(BusState *qbus)
|
|
|
9e0a86 |
{
|
|
|
9e0a86 |
PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus);
|
|
|
9e0a86 |
int i;
|
|
|
9e0a86 |
@@ -220,13 +225,9 @@ static int pcibus_reset(BusState *qbus)
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
|
|
|
9e0a86 |
if (bus->devices[i]) {
|
|
|
9e0a86 |
- pci_device_reset(bus->devices[i]);
|
|
|
9e0a86 |
+ pci_do_device_reset(bus->devices[i]);
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
-
|
|
|
9e0a86 |
- /* topology traverse is done by pci_bus_reset().
|
|
|
9e0a86 |
- Tell qbus/qdev walker not to traverse the tree */
|
|
|
9e0a86 |
- return 1;
|
|
|
9e0a86 |
}
|
|
|
9e0a86 |
|
|
|
9e0a86 |
static void pci_host_bus_register(PCIBus *bus, DeviceState *parent)
|
|
|
9e0a86 |
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
|
|
|
45bdef |
index ecf5cb3..a9ce4a3 100644
|
|
|
9e0a86 |
--- a/include/hw/qdev-core.h
|
|
|
9e0a86 |
+++ b/include/hw/qdev-core.h
|
|
|
45bdef |
@@ -158,7 +158,7 @@ struct BusClass {
|
|
|
9e0a86 |
* bindings can be found at http://playground.sun.com/1275/bindings/.
|
|
|
9e0a86 |
*/
|
|
|
9e0a86 |
char *(*get_fw_dev_path)(DeviceState *dev);
|
|
|
9e0a86 |
- int (*reset)(BusState *bus);
|
|
|
9e0a86 |
+ void (*reset)(BusState *bus);
|
|
|
9e0a86 |
/* maximum devices allowed on the bus, 0: no limit. */
|
|
|
9e0a86 |
int max_dev;
|
|
|
9e0a86 |
};
|