diff mbox

[v15,10/15] pci: Introduce device hot reset

Message ID 50a3283cf0656ae8df681c54d9e8fb375b207276.1451901804.git.chen.fan.fnst@cn.fujitsu.com
State New
Headers show

Commit Message

Cao jin Jan. 5, 2016, 1:20 a.m. UTC
From: Chen Fan <chen.fan.fnst@cn.fujitsu.com>

The secondary bus reset in bridge control register setting trigger
a hot reset, Specially for vfio device, we usually need to do a hot
reset for the host bus other than the device reset.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/core/qdev.c         | 24 ++++++++++++++++++++++++
 hw/pci/pci_bridge.c    |  2 +-
 include/hw/qdev-core.h |  3 +++
 3 files changed, 28 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b3ad467..9c48bae 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -311,6 +311,13 @@  static int qdev_reset_one(DeviceState *dev, void *opaque)
     return 0;
 }
 
+static int qdev_hot_reset_one(DeviceState *dev, void *opaque)
+{
+    device_hot_reset(dev);
+
+    return 0;
+}
+
 static int qbus_reset_one(BusState *bus, void *opaque)
 {
     BusClass *bc = BUS_GET_CLASS(bus);
@@ -335,6 +342,11 @@  void qbus_reset_all(BusState *bus)
     qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
 }
 
+void qbus_hot_reset_all(BusState *bus)
+{
+    qbus_walk_children(bus, NULL, NULL, qdev_hot_reset_one, qbus_reset_one, NULL);
+}
+
 void qbus_reset_all_fn(void *opaque)
 {
     BusState *bus = opaque;
@@ -1284,6 +1296,18 @@  void device_reset(DeviceState *dev)
     }
 }
 
+void device_hot_reset(DeviceState *dev)
+{
+    DeviceClass *klass = DEVICE_GET_CLASS(dev);
+
+    if (klass->hot_reset) {
+        klass->hot_reset(dev);
+        return;
+    }
+
+    device_reset(dev);
+}
+
 Object *qdev_get_machine(void)
 {
     static Object *dev;
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 40c97b1..f1903db 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -268,7 +268,7 @@  void pci_bridge_write_config(PCIDevice *d,
     newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
     if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
         /* Trigger hot reset on 0->1 transition. */
-        qbus_reset_all(&s->sec_bus.qbus);
+        qbus_hot_reset_all(&s->sec_bus.qbus);
     }
 }
 
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index c537969..e9fe4b3 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -131,6 +131,7 @@  typedef struct DeviceClass {
 
     /* callbacks */
     void (*reset)(DeviceState *dev);
+    void (*hot_reset)(DeviceState *dev);
     DeviceRealize realize;
     DeviceUnrealize unrealize;
 
@@ -351,6 +352,7 @@  void qdev_reset_all_fn(void *opaque);
  */
 void qbus_reset_all(BusState *bus);
 void qbus_reset_all_fn(void *opaque);
+void qbus_hot_reset_all(BusState *bus);
 
 /* This should go away once we get rid of the NULL bus hack */
 BusState *sysbus_get_default(void);
@@ -372,6 +374,7 @@  void qdev_machine_init(void);
  * Reset a single device (by calling the reset method).
  */
 void device_reset(DeviceState *dev);
+void device_hot_reset(DeviceState *dev);
 
 const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);