pci/pcie: perform unplug via the hotplug handler
authorDavid Hildenbrand <david@redhat.com>
Wed, 12 Dec 2018 09:16:20 +0000 (10:16 +0100)
committerMichael S. Tsirkin <mst@redhat.com>
Thu, 20 Dec 2018 16:19:12 +0000 (11:19 -0500)
Introduce and use the "unplug" callback.

This is a preparation for multi-stage hotplug handlers, whereby the bus
hotplug handler is overwritten by the machine hotplug handler. This handler
will then pass control to the bus hotplug handler. So to get this running
cleanly, we also have to make sure to go via the hotplug handler chain when
actually unplugging a device after an unplug request. Lookup the hotplug
handler and call "unplug".

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
hw/pci/pcie.c
hw/pci/pcie_port.c
include/hw/pci/pcie.h

index ec3b1145f335be55f9367b47aa4447cb182217e9..2d3d8a047b837887d538519e933169e4b68a66d2 100644 (file)
@@ -442,11 +442,19 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
     }
 }
 
-static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
+void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+                             Error **errp)
 {
     object_unparent(OBJECT(dev));
 }
 
+static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
+{
+    HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(dev));
+
+    hotplug_handler_unplug(hotplug_ctrl, DEVICE(dev), &error_abort);
+}
+
 void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
 {
index 73e81e58473f6b9093a46f3157572bdf246d1919..bc07abc31b47a4842cd6954e5e0f261608baa7ce 100644 (file)
@@ -155,6 +155,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void *data)
 
     dc->props = pcie_slot_props;
     hc->plug = pcie_cap_slot_plug_cb;
+    hc->unplug = pcie_cap_slot_unplug_cb;
     hc->unplug_request = pcie_cap_slot_unplug_request_cb;
 }
 
index d51ca23f07a1483179ebd72712401f570f64e50e..cd318646a2b514a819d9ddbb581648382870c21b 100644 (file)
@@ -134,6 +134,8 @@ void pcie_ats_init(PCIDevice *dev, uint16_t offset);
 
 void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                            Error **errp);
+void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+                             Error **errp);
 void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp);
 #endif /* QEMU_PCIE_H */