diff options
-rw-r--r-- | hw/ppc/spapr_pci.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 2374d55fc1..bfb02ee96b 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1370,18 +1370,9 @@ static int spapr_create_pci_child_dt(sPAPRPHBState *phb, PCIDevice *dev, /* Callback to be called during DRC release. */ void spapr_phb_remove_pci_device_cb(DeviceState *dev) { - /* some version guests do not wait for completion of a device - * cleanup (generally done asynchronously by the kernel) before - * signaling to QEMU that the device is safe, but instead sleep - * for some 'safe' period of time. unfortunately on a busy host - * this sleep isn't guaranteed to be long enough, resulting in - * bad things like IRQ lines being left asserted during final - * device removal. to deal with this we call reset just prior - * to finalizing the device, which will put the device back into - * an 'idle' state, as the device cleanup code expects. - */ - pci_device_reset(PCI_DEVICE(dev)); - object_unparent(OBJECT(dev)); + HotplugHandler *hotplug_ctrl = qdev_get_hotplug_handler(dev); + + hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); } static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb, @@ -1490,6 +1481,23 @@ out: } } +static void spapr_pci_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) +{ + /* some version guests do not wait for completion of a device + * cleanup (generally done asynchronously by the kernel) before + * signaling to QEMU that the device is safe, but instead sleep + * for some 'safe' period of time. unfortunately on a busy host + * this sleep isn't guaranteed to be long enough, resulting in + * bad things like IRQ lines being left asserted during final + * device removal. to deal with this we call reset just prior + * to finalizing the device, which will put the device back into + * an 'idle' state, as the device cleanup code expects. + */ + pci_device_reset(PCI_DEVICE(plugged_dev)); + object_unparent(OBJECT(plugged_dev)); +} + static void spapr_pci_unplug_request(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp) { @@ -1965,6 +1973,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); hp->plug = spapr_pci_plug; + hp->unplug = spapr_pci_unplug; hp->unplug_request = spapr_pci_unplug_request; } |