diff mbox

[8/8] kvm: qemu: fix hot remove assigned device

Message ID 715D42877B251141A38726ABF5CABF2C0195A1F9B8@pdsmsx503.ccr.corp.intel.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Han, Weidong Feb. 18, 2009, 7:13 a.m. UTC
When hot remove assigned device, should deassign it
from guest and free it from qemu.

assign_dev_update_irqs may not be invoked when hot add a
device, so need to assign irq after device assignment in
init_assigned_device.

Acked-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Weidong Han <weidong.han@intel.com>
---
 qemu/hw/device-assignment.c |   20 ++++++++++++++++++++
 qemu/hw/device-assignment.h |    1 +
 qemu/hw/pci-hotplug.c       |   17 +++++++++++++++++
 3 files changed, 38 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/qemu/hw/device-assignment.c b/qemu/hw/device-assignment.c
index fc89c6f..d6acc67 100644
--- a/qemu/hw/device-assignment.c
+++ b/qemu/hw/device-assignment.c
@@ -571,6 +571,21 @@  void remove_assigned_device(AssignedDevInfo *adev)
     free_assigned_device(adev);
 }
 
+AssignedDevInfo *get_assigned_device(int pcibus, int slot)
+{
+    AssignedDevice *assigned_dev = NULL;
+    AssignedDevInfo *adev = NULL;
+
+    LIST_FOREACH(adev, &adev_head, next) {
+        assigned_dev = adev->assigned_dev;
+        if (pci_bus_num(assigned_dev->dev.bus) == pcibus &&
+            PCI_SLOT(assigned_dev->dev.devfn) == slot)
+            return adev;
+    }
+
+    return NULL;
+}
+
 /* The pci config space got updated. Check if irq numbers have changed
  * for our devices
  */
@@ -639,6 +654,11 @@  struct PCIDevice *init_assigned_device(AssignedDevInfo *adev, PCIBus *bus)
     if (r < 0)
         goto assigned_out;
 
+    /* assign irq for the device */
+    r = assign_irq(adev);
+    if (r < 0)
+        goto assigned_out;
+ 
     return &dev->dev;
 
 assigned_out:
diff --git a/qemu/hw/device-assignment.h b/qemu/hw/device-assignment.h
index 84f3f32..da775d7 100644
--- a/qemu/hw/device-assignment.h
+++ b/qemu/hw/device-assignment.h
@@ -98,6 +98,7 @@  PCIDevice *init_assigned_device(AssignedDevInfo *adev, PCIBus *bus);
 AssignedDevInfo *add_assigned_device(const char *arg);
 void add_assigned_devices(PCIBus *bus, const char **devices, int n_devices);
 void remove_assigned_device(AssignedDevInfo *adev);
+AssignedDevInfo *get_assigned_device(int pcibus, int slot);
 ram_addr_t assigned_dev_load_option_roms(ram_addr_t rom_base_offset);
 void assigned_dev_update_irqs(void);
 
diff --git a/qemu/hw/pci-hotplug.c b/qemu/hw/pci-hotplug.c
index 65fafd1..d2ee2c5 100644
--- a/qemu/hw/pci-hotplug.c
+++ b/qemu/hw/pci-hotplug.c
@@ -155,6 +155,14 @@  static PCIDevice *qemu_pci_hot_assign_device(PCIBus *pci_bus, const char *opts)
     return ret;
 }
 
+static void qemu_pci_hot_deassign_device(AssignedDevInfo *adev)
+{
+    remove_assigned_device(adev);
+
+    term_printf("Unregister host PCI device %02x:%02x.%1x "
+		"(\"%s\") from guest\n", 
+		adev->bus, adev->dev, adev->func, adev->name);
+}
 #endif /* USE_KVM_DEVICE_ASSIGNMENT */
 
 void pci_device_hot_add(const char *pci_addr, const char *type, const char *opts)
@@ -231,12 +239,21 @@  void pci_device_hot_remove_success(int pcibus, int slot)
 {
     PCIDevice *d = pci_find_device(pcibus, slot, 0);
     int class_code;
+    AssignedDevInfo *adev;
 
     if (!d) {
         term_printf("invalid slot %d\n", slot);
         return;
     }
 
+#ifdef USE_KVM_DEVICE_ASSIGNMENT
+    adev = get_assigned_device(pcibus, slot);
+    if (adev) {
+        qemu_pci_hot_deassign_device(adev);
+        return;
+    }
+#endif /* USE_KVM_DEVICE_ASSIGNMENT */
+
     class_code = d->config_read(d, PCI_CLASS_DEVICE+1, 1);
 
     switch(class_code) {