Commit 8f560cdc authored by David Hildenbrand's avatar David Hildenbrand Committed by Michael S. Tsirkin
Browse files

pci/shpc: 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: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 62b76563
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -219,6 +219,15 @@ void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
    shpc_device_plug_cb(hotplug_dev, dev, errp);
}

void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                              Error **errp)
{
    PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev);

    g_assert(shpc_present(pci_hotplug_dev));
    shpc_device_unplug_cb(hotplug_dev, dev, errp);
}

void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp)
{
@@ -251,6 +260,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data)
    dc->vmsd = &pci_bridge_dev_vmstate;
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    hc->plug = pci_bridge_dev_plug_cb;
    hc->unplug = pci_bridge_dev_unplug_cb;
    hc->unplug_request = pci_bridge_dev_unplug_request_cb;
}

+1 −0
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ static void pcie_pci_bridge_class_init(ObjectClass *klass, void *data)
    dc->reset = &pcie_pci_bridge_reset;
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    hc->plug = pci_bridge_dev_plug_cb;
    hc->unplug = pci_bridge_dev_unplug_cb;
    hc->unplug_request = pci_bridge_dev_unplug_request_cb;
}

+10 −1
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ static void shpc_invalid_command(SHPCDevice *shpc)

static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
{
    HotplugHandler *hotplug_ctrl;
    int devfn;
    int pci_slot = SHPC_IDX_TO_PCI(slot);
    for (devfn = PCI_DEVFN(pci_slot, 0);
@@ -245,7 +246,9 @@ static void shpc_free_devices_in_slot(SHPCDevice *shpc, int slot)
         ++devfn) {
        PCIDevice *affected_dev = shpc->sec_bus->devices[devfn];
        if (affected_dev) {
            object_unparent(OBJECT(affected_dev));
            hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(affected_dev));
            hotplug_handler_unplug(hotplug_ctrl, DEVICE(affected_dev),
                                   &error_abort);
        }
    }
}
@@ -540,6 +543,12 @@ void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
    shpc_interrupt_update(pci_hotplug_dev);
}

void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                           Error **errp)
{
    object_unparent(OBJECT(dev));
}

void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                   DeviceState *dev, Error **errp)
{
+2 −0
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ void pci_bridge_exitfn(PCIDevice *pci_dev);

void pci_bridge_dev_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                            Error **errp);
void pci_bridge_dev_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                              Error **errp);
void pci_bridge_dev_unplug_request_cb(HotplugHandler *hotplug_dev,
                                      DeviceState *dev, Error **errp);

+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len);

void shpc_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                         Error **errp);
void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                           Error **errp);
void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
                                   DeviceState *dev, Error **errp);