Merge branch 'kvm-updates/3.2' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm
[pandora-kernel.git] / virt / kvm / assigned-dev.c
index 4e9eaeb..3ad0925 100644 (file)
@@ -58,8 +58,6 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel
 static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id)
 {
        struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
-       u32 vector;
-       int index;
 
        if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_INTX) {
                spin_lock(&assigned_dev->intx_lock);
@@ -68,31 +66,35 @@ static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id)
                spin_unlock(&assigned_dev->intx_lock);
        }
 
-       if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
-               index = find_index_from_host_irq(assigned_dev, irq);
-               if (index >= 0) {
-                       vector = assigned_dev->
-                                       guest_msix_entries[index].vector;
-                       kvm_set_irq(assigned_dev->kvm,
-                                   assigned_dev->irq_source_id, vector, 1);
-               }
-       } else
+       kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
+                   assigned_dev->guest_irq, 1);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef __KVM_HAVE_MSIX
+static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
+{
+       struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
+       int index = find_index_from_host_irq(assigned_dev, irq);
+       u32 vector;
+
+       if (index >= 0) {
+               vector = assigned_dev->guest_msix_entries[index].vector;
                kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
-                           assigned_dev->guest_irq, 1);
+                           vector, 1);
+       }
 
        return IRQ_HANDLED;
 }
+#endif
 
 /* Ack the irq line for an assigned device */
 static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
 {
-       struct kvm_assigned_dev_kernel *dev;
-
-       if (kian->gsi == -1)
-               return;
-
-       dev = container_of(kian, struct kvm_assigned_dev_kernel,
-                          ack_notifier);
+       struct kvm_assigned_dev_kernel *dev =
+               container_of(kian, struct kvm_assigned_dev_kernel,
+                            ack_notifier);
 
        kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
 
@@ -110,8 +112,9 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
 static void deassign_guest_irq(struct kvm *kvm,
                               struct kvm_assigned_dev_kernel *assigned_dev)
 {
-       kvm_unregister_irq_ack_notifier(kvm, &assigned_dev->ack_notifier);
-       assigned_dev->ack_notifier.gsi = -1;
+       if (assigned_dev->ack_notifier.gsi != -1)
+               kvm_unregister_irq_ack_notifier(kvm,
+                                               &assigned_dev->ack_notifier);
 
        kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
                    assigned_dev->guest_irq, 0);
@@ -143,7 +146,7 @@ static void deassign_host_irq(struct kvm *kvm,
 
                for (i = 0; i < assigned_dev->entries_nr; i++)
                        free_irq(assigned_dev->host_msix_entries[i].vector,
-                                (void *)assigned_dev);
+                                assigned_dev);
 
                assigned_dev->entries_nr = 0;
                kfree(assigned_dev->host_msix_entries);
@@ -153,7 +156,7 @@ static void deassign_host_irq(struct kvm *kvm,
                /* Deal with MSI and INTx */
                disable_irq(assigned_dev->host_irq);
 
-               free_irq(assigned_dev->host_irq, (void *)assigned_dev);
+               free_irq(assigned_dev->host_irq, assigned_dev);
 
                if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSI)
                        pci_disable_msi(assigned_dev->dev);
@@ -205,6 +208,8 @@ static void kvm_free_assigned_device(struct kvm *kvm,
        else
                pci_restore_state(assigned_dev->dev);
 
+       assigned_dev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
+
        pci_release_regions(assigned_dev->dev);
        pci_disable_device(assigned_dev->dev);
        pci_dev_put(assigned_dev->dev);
@@ -237,7 +242,7 @@ static int assigned_device_enable_host_intx(struct kvm *kvm,
         * are going to be long delays in accepting, acking, etc.
         */
        if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                IRQF_ONESHOT, dev->irq_name, (void *)dev))
+                                IRQF_ONESHOT, dev->irq_name, dev))
                return -EIO;
        return 0;
 }
@@ -256,7 +261,7 @@ static int assigned_device_enable_host_msi(struct kvm *kvm,
 
        dev->host_irq = dev->dev->irq;
        if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
-                                0, dev->irq_name, (void *)dev)) {
+                                0, dev->irq_name, dev)) {
                pci_disable_msi(dev->dev);
                return -EIO;
        }
@@ -282,8 +287,8 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
 
        for (i = 0; i < dev->entries_nr; i++) {
                r = request_threaded_irq(dev->host_msix_entries[i].vector,
-                                        NULL, kvm_assigned_dev_thread,
-                                        0, dev->irq_name, (void *)dev);
+                                        NULL, kvm_assigned_dev_thread_msix,
+                                        0, dev->irq_name, dev);
                if (r)
                        goto err;
        }
@@ -291,7 +296,7 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
        return 0;
 err:
        for (i -= 1; i >= 0; i--)
-               free_irq(dev->host_msix_entries[i].vector, (void *)dev);
+               free_irq(dev->host_msix_entries[i].vector, dev);
        pci_disable_msix(dev->dev);
        return r;
 }
@@ -404,7 +409,8 @@ static int assign_guest_irq(struct kvm *kvm,
 
        if (!r) {
                dev->irq_requested_type |= guest_irq_type;
-               kvm_register_irq_ack_notifier(kvm, &dev->ack_notifier);
+               if (dev->ack_notifier.gsi != -1)
+                       kvm_register_irq_ack_notifier(kvm, &dev->ack_notifier);
        } else
                kvm_free_irq_source_id(kvm, dev->irq_source_id);