]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/vfio/pci/vfio_pci_intrs.c
Merge remote-tracking branch 'asoc/topic/component' into asoc-next
[karo-tx-linux.git] / drivers / vfio / pci / vfio_pci_intrs.c
index 152b43822ef1912c980292f7927286e6df76656c..1c46045b0e7fc6b2e8ef421853742851aa880d7e 100644 (file)
@@ -250,44 +250,23 @@ static irqreturn_t vfio_msihandler(int irq, void *arg)
 static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
 {
        struct pci_dev *pdev = vdev->pdev;
+       unsigned int flag = msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;
        int ret;
 
        if (!is_irq_none(vdev))
                return -EINVAL;
 
-       vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
+       vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);
        if (!vdev->ctx)
                return -ENOMEM;
 
-       if (msix) {
-               int i;
-
-               vdev->msix = kzalloc(nvec * sizeof(struct msix_entry),
-                                    GFP_KERNEL);
-               if (!vdev->msix) {
-                       kfree(vdev->ctx);
-                       return -ENOMEM;
-               }
-
-               for (i = 0; i < nvec; i++)
-                       vdev->msix[i].entry = i;
-
-               ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec);
-               if (ret < nvec) {
-                       if (ret > 0)
-                               pci_disable_msix(pdev);
-                       kfree(vdev->msix);
-                       kfree(vdev->ctx);
-                       return ret;
-               }
-       } else {
-               ret = pci_enable_msi_range(pdev, 1, nvec);
-               if (ret < nvec) {
-                       if (ret > 0)
-                               pci_disable_msi(pdev);
-                       kfree(vdev->ctx);
-                       return ret;
-               }
+       /* return the number of supported vectors if we can't get all: */
+       ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag);
+       if (ret < nvec) {
+               if (ret > 0)
+                       pci_free_irq_vectors(pdev);
+               kfree(vdev->ctx);
+               return ret;
        }
 
        vdev->num_ctx = nvec;
@@ -315,7 +294,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev,
        if (vector < 0 || vector >= vdev->num_ctx)
                return -EINVAL;
 
-       irq = msix ? vdev->msix[vector].vector : pdev->irq + vector;
+       irq = pci_irq_vector(pdev, vector);
 
        if (vdev->ctx[vector].trigger) {
                free_irq(irq, vdev->ctx[vector].trigger);
@@ -408,11 +387,14 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
 
        vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
-       if (msix) {
-               pci_disable_msix(vdev->pdev);
-               kfree(vdev->msix);
-       } else
-               pci_disable_msi(pdev);
+       pci_free_irq_vectors(pdev);
+
+       /*
+        * Both disable paths above use pci_intx_for_msi() to clear DisINTx
+        * via their shutdown paths.  Restore for NoINTx devices.
+        */
+       if (vdev->nointx)
+               pci_intx(pdev, 0);
 
        vdev->irq_type = VFIO_PCI_NUM_IRQS;
        vdev->num_ctx = 0;