From mboxrd@z Thu Jan 1 00:00:00 1970 From: Markus Theil Subject: [PATCH v5 3/5] igb_uio: MSI IRQ mode Date: Thu, 31 Aug 2017 23:46:58 +0200 Message-ID: <1504216020-16067-3-git-send-email-markus.theil@tu-ilmenau.de> References: <1504174949-25656-3-git-send-email-markus.theil@tu-ilmenau.de> <1504216020-16067-1-git-send-email-markus.theil@tu-ilmenau.de> Cc: ferruh.yigit@intel.com, stephen@networkplumber.org, Markus Theil To: dev@dpdk.org Return-path: Received: from smail.rz.tu-ilmenau.de (smail.rz.tu-ilmenau.de [141.24.186.67]) by dpdk.org (Postfix) with ESMTP id CD7682BF3 for ; Thu, 31 Aug 2017 23:47:23 +0200 (CEST) In-Reply-To: <1504216020-16067-1-git-send-email-markus.theil@tu-ilmenau.de> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds MSI IRQ mode and 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 --- lib/librte_eal/linuxapp/igb_uio/igb_uio.c | 60 ++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c index 93bb71d..99a085a 100644 --- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c +++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c @@ -91,6 +91,7 @@ static struct attribute *dev_attrs[] = { static const struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; + /* * It masks the msix on/off of generating MSI-X messages. */ @@ -113,6 +114,29 @@ igbuio_msix_mask_irq(struct msi_desc *desc, int32_t state) } } +/* + * It masks the msi on/off of generating MSI messages. + */ +static void +igbuio_msi_mask_irq(struct pci_dev *pdev, struct msi_desc *desc, int32_t state) +{ + u32 mask_bits = desc->masked; + u32 offset = desc->irq - pdev->irq; + u32 mask = 1 << offset; + u32 flag = !!state << offset; + + if (!desc->msi_attrib.maskbit) + return; + + mask_bits &= ~mask; + mask_bits |= flag; + + if (mask_bits != desc->masked) { + pci_write_config_dword(pdev, desc->mask_pos, mask_bits); + desc->masked = mask_bits; + } +} + /** * This is the irqcontrol callback to be registered to uio_info. * It can be used to disable/enable interrupt from user space processes. @@ -146,6 +170,16 @@ igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state) list_for_each_entry(desc, &pdev->dev.msi_list, list) igbuio_msix_mask_irq(desc, irq_state); #endif + } else if (udev->mode == RTE_INTR_MODE_MSI) { + struct msi_desc *desc; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)) + list_for_each_entry(desc, &pdev->msi_list, list) + igbuio_msi_mask_irq(pdev, desc, irq_state); +#else + list_for_each_entry(desc, &pdev->dev.msi_list, list) + igbuio_msi_mask_irq(pdev, desc, irq_state); +#endif } pci_cfg_access_unlock(pdev); @@ -336,6 +370,23 @@ igbuio_pci_enable_interrupts(struct rte_uio_pci_dev *udev) break; } #endif + 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 = pci_irq_vector(udev->pdev, 0); + udev->mode = RTE_INTR_MODE_MSI; + break; + } +#endif /* fall back to INTX */ case RTE_INTR_MODE_LEGACY: if (pci_intx_mask_supported(udev->pdev)) { @@ -367,8 +418,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 } @@ -553,6 +607,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"); @@ -596,6 +653,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"); -- 2.7.4