In case user regret when hot-add multi-function, we should roll back, device_del the function added but still not worked.
Signed-off-by: Cao jin <caoj.f...@cn.fujitsu.com> --- hw/pci/pcie.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 61ebefd..b83a244 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -265,10 +265,33 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, } } +static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque) +{ + object_unparent(OBJECT(dev)); +} + void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { uint8_t *exp_cap; + PCIDevice *pci_dev = PCI_DEVICE(dev); + PCIBus *bus = pci_dev->bus; + + /* handle the condition: user want to hot-add multi function, but regret + * before finish it, and want to delete the added but not worked function. + */ + if (PCI_FUNC(pci_dev->devfn) > 0 && + bus->devices[PCI_DEVFN(0,0)] == NULL) { + pci_for_each_device(bus, pci_bus_num(bus), + pcie_unplug_device, NULL); + + pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDC); + + return; + } pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); @@ -382,11 +405,6 @@ void pcie_cap_slot_reset(PCIDevice *dev) hotplug_event_update_event_status(dev); } -static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque) -{ - object_unparent(OBJECT(dev)); -} - void pcie_cap_slot_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) { -- 2.1.0