spapr_pci: perform unplug via the hotplug handler
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: Greg Kurz <groug@kaod.org> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Acked-by: David Gibson <david@gibson.dropbear.id.au> 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>
This commit is contained in:
parent
8f560cdce4
commit
27c1da5129
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user