diff options
author | Cao jin <caoj.fnst@cn.fujitsu.com> | 2015-10-28 14:20:30 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2015-10-29 11:17:52 +0200 |
commit | 0d1c7d88ad909c5b2bd86211a9fe8abf5c74993b (patch) | |
tree | 1ff174b0b230dd25cb3f36c813e2d8776bd44a3f /hw/pci | |
parent | 3595e2eb0a233a881789fcc71f5b1072e5aaf669 (diff) | |
download | qemu-0d1c7d88ad909c5b2bd86211a9fe8abf5c74993b.zip |
remove function during multi-function hot-add
In case user want to cancel the hot-add operation, should roll back,
device_del the added function that still don`t work.
Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/pci')
-rw-r--r-- | hw/pci/pcie.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 6e28985bd1..a72d516e4f 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -261,13 +261,31 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); } +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; pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp); + /* In case user cancel the operation of multi-function hot-add, + * remove the function that is unexposed to guest individually, + * without interaction with guest. + */ + if (pci_dev->devfn && + !bus->devices[0]) { + pcie_unplug_device(bus, pci_dev, NULL); + + return; + } + pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); } @@ -378,11 +396,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) { |