igb_uio: add MSI IRQ mode
authorMarkus Theil <markus.theil@tu-ilmenau.de>
Tue, 5 Sep 2017 12:04:06 +0000 (14:04 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 6 Oct 2017 22:03:03 +0000 (23:03 +0100)
This patch adds MSI IRQ mode in a way, that should
also work on older kernel versions. The base for my patch
was an attempt to do this in cf705bc36c which was later
reverted in d8ee82745a. Compilation was tested on Linux 3.2,
4.10 and 4.12.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
lib/librte_eal/linuxapp/igb_uio/igb_uio.c

index e4ef817..b578c4a 100644 (file)
@@ -119,7 +119,7 @@ igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state)
 
        pci_cfg_access_lock(pdev);
 
-       if (udev->mode == RTE_INTR_MODE_MSIX) {
+       if (udev->mode == RTE_INTR_MODE_MSIX || udev->mode == RTE_INTR_MODE_MSI) {
 #ifdef HAVE_PCI_MSI_MASK_IRQ
                if (irq_state == 1)
                        pci_msi_unmask_irq(irq);
@@ -325,6 +325,25 @@ igbuio_pci_enable_interrupts(struct rte_uio_pci_dev *udev)
                        udev->mode = RTE_INTR_MODE_MSIX;
                        break;
                }
+#endif
+       /* fall back to MSI */
+       case RTE_INTR_MODE_MSI:
+#ifndef HAVE_ALLOC_IRQ_VECTORS
+               if (pci_enable_msi(udev->pdev) == 0) {
+                       dev_dbg(&udev->pdev->dev, "using MSI");
+                       udev->info.irq_flags = IRQF_NO_THREAD;
+                       udev->info.irq = udev->pdev->irq;
+                       udev->mode = RTE_INTR_MODE_MSI;
+                       break;
+               }
+#else
+               if (pci_alloc_irq_vectors(udev->pdev, 1, 1, PCI_IRQ_MSI) == 1) {
+                       dev_dbg(&udev->pdev->dev, "using MSI");
+                       udev->info.irq_flags = IRQF_NO_THREAD;
+                       udev->info.irq = pci_irq_vector(udev->pdev, 0);
+                       udev->mode = RTE_INTR_MODE_MSI;
+                       break;
+               }
 #endif
        /* fall back to INTX */
        case RTE_INTR_MODE_LEGACY:
@@ -336,7 +355,7 @@ igbuio_pci_enable_interrupts(struct rte_uio_pci_dev *udev)
                        break;
                }
                dev_notice(&udev->pdev->dev, "PCI INTX mask not supported\n");
-               /* fall back to no IRQ */
+       /* fall back to no IRQ */
        case RTE_INTR_MODE_NONE:
                udev->mode = RTE_INTR_MODE_NONE;
                udev->info.irq = 0;
@@ -357,8 +376,11 @@ igbuio_pci_disable_interrupts(struct rte_uio_pci_dev *udev)
 #ifndef HAVE_ALLOC_IRQ_VECTORS
        if (udev->mode == RTE_INTR_MODE_MSIX)
                pci_disable_msix(udev->pdev);
+       if (udev->mode == RTE_INTR_MODE_MSI)
+               pci_disable_msi(udev->pdev);
 #else
-       if (udev->mode == RTE_INTR_MODE_MSIX)
+       if (udev->mode == RTE_INTR_MODE_MSIX ||
+           udev->mode == RTE_INTR_MODE_MSI)
                pci_free_irq_vectors(udev->pdev);
 #endif
 }
@@ -544,6 +566,9 @@ igbuio_config_intr_mode(char *intr_str)
        if (!strcmp(intr_str, RTE_INTR_MODE_MSIX_NAME)) {
                igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX;
                pr_info("Use MSIX interrupt\n");
+       } else if (!strcmp(intr_str, RTE_INTR_MODE_MSI_NAME)) {
+               igbuio_intr_mode_preferred = RTE_INTR_MODE_MSI;
+               pr_info("Use MSI interrupt\n");
        } else if (!strcmp(intr_str, RTE_INTR_MODE_LEGACY_NAME)) {
                igbuio_intr_mode_preferred = RTE_INTR_MODE_LEGACY;
                pr_info("Use legacy interrupt\n");
@@ -587,6 +612,7 @@ module_param(intr_mode, charp, S_IRUGO);
 MODULE_PARM_DESC(intr_mode,
 "igb_uio interrupt mode (default=msix):\n"
 "    " RTE_INTR_MODE_MSIX_NAME "       Use MSIX interrupt\n"
+"    " RTE_INTR_MODE_MSI_NAME "        Use MSI interrupt\n"
 "    " RTE_INTR_MODE_LEGACY_NAME "     Use Legacy interrupt\n"
 "\n");