From 56bb5841fd0608989101d933f091852a3126b4fe Mon Sep 17 00:00:00 2001 From: Thomas Monjalon Date: Tue, 8 Sep 2020 00:39:03 +0200 Subject: [PATCH] kernel/linux: remove igb_uio As decided in the Technical Board in November 2019, the kernel module igb_uio is moved to the dpdk-kmods repository in the /linux/igb_uio/ directory. Minutes of Technical Board meeting: https://mails.dpdk.org/archives/dev/2019-November/151763.html Signed-off-by: Thomas Monjalon Acked-by: Stephen Hemminger Acked-by: Andrew Rybchenko Acked-by: Jerin Jacob Reviewed-by: Ferruh Yigit --- MAINTAINERS | 1 - doc/guides/bbdevs/fpga_5gnr_fec.rst | 3 +- doc/guides/bbdevs/fpga_lte_fec.rst | 3 +- doc/guides/cryptodevs/ccp.rst | 3 +- doc/guides/cryptodevs/qat.rst | 3 +- doc/guides/howto/lm_bond_virtio_sriov.rst | 2 +- doc/guides/howto/lm_virtio_vhost_user.rst | 2 +- doc/guides/howto/openwrt.rst | 5 - doc/guides/linux_gsg/enable_func.rst | 3 +- doc/guides/linux_gsg/linux_drivers.rst | 23 +- doc/guides/nics/build_and_test.rst | 2 +- doc/guides/nics/ena.rst | 4 +- doc/guides/rel_notes/deprecation.rst | 7 - doc/guides/rel_notes/release_20_11.rst | 4 +- doc/guides/sample_app_ug/multi_process.rst | 2 - drivers/bus/pci/bsd/pci.c | 2 +- kernel/linux/igb_uio/Kbuild | 2 - kernel/linux/igb_uio/compat.h | 154 ----- kernel/linux/igb_uio/igb_uio.c | 660 --------------------- kernel/linux/igb_uio/meson.build | 20 - kernel/linux/meson.build | 2 +- 21 files changed, 21 insertions(+), 886 deletions(-) delete mode 100644 kernel/linux/igb_uio/Kbuild delete mode 100644 kernel/linux/igb_uio/compat.h delete mode 100644 kernel/linux/igb_uio/igb_uio.c delete mode 100644 kernel/linux/igb_uio/meson.build diff --git a/MAINTAINERS b/MAINTAINERS index 5dfcca759d..75a17d51c0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -290,7 +290,6 @@ F: doc/guides/linux_gsg/ Linux UIO M: Ferruh Yigit -F: kernel/linux/igb_uio/ F: drivers/bus/pci/linux/*uio* Linux VFIO diff --git a/doc/guides/bbdevs/fpga_5gnr_fec.rst b/doc/guides/bbdevs/fpga_5gnr_fec.rst index 6760391e8c..709e7baed9 100644 --- a/doc/guides/bbdevs/fpga_5gnr_fec.rst +++ b/doc/guides/bbdevs/fpga_5gnr_fec.rst @@ -93,8 +93,7 @@ the UIO driver by repeating this command for every function. .. code-block:: console - cd - insmod ./build/kmod/igb_uio.ko + insmod igb_uio.ko echo "8086 0d8f" > /sys/bus/pci/drivers/igb_uio/new_id lspci -vd8086:0d8f diff --git a/doc/guides/bbdevs/fpga_lte_fec.rst b/doc/guides/bbdevs/fpga_lte_fec.rst index fdc8a76981..344a2cc06a 100644 --- a/doc/guides/bbdevs/fpga_lte_fec.rst +++ b/doc/guides/bbdevs/fpga_lte_fec.rst @@ -92,8 +92,7 @@ the UIO driver by repeating this command for every function. .. code-block:: console - cd - insmod ./build/kmod/igb_uio.ko + insmod igb_uio.ko echo "1172 5052" > /sys/bus/pci/drivers/igb_uio/new_id lspci -vd1172: diff --git a/doc/guides/cryptodevs/ccp.rst b/doc/guides/cryptodevs/ccp.rst index a43fe92de9..9c1997768a 100644 --- a/doc/guides/cryptodevs/ccp.rst +++ b/doc/guides/cryptodevs/ccp.rst @@ -75,9 +75,8 @@ Initialization Bind the CCP devices to DPDK UIO driver module before running the CCP PMD stack. e.g. for the 0x1456 device:: - cd to the top-level DPDK directory modprobe uio - insmod ./build/kmod/igb_uio.ko + insmod igb_uio.ko echo "1022 1456" > /sys/bus/pci/drivers/igb_uio/new_id Another way to bind the CCP devices to DPDK UIO driver is by using the ``dpdk-devbind.py`` script. diff --git a/doc/guides/cryptodevs/qat.rst b/doc/guides/cryptodevs/qat.rst index e5d2cf4997..7c56293192 100644 --- a/doc/guides/cryptodevs/qat.rst +++ b/doc/guides/cryptodevs/qat.rst @@ -642,9 +642,8 @@ Install the DPDK igb_uio driver, bind the VF PCI Device id to it and use lspci to confirm the VF devices are now in use by igb_uio kernel driver, e.g. for the C62x device:: - cd to the top-level DPDK directory modprobe uio - insmod ./build/kmod/igb_uio.ko + insmod igb_uio.ko echo "8086 37c9" > /sys/bus/pci/drivers/igb_uio/new_id lspci -vvd:37c9 diff --git a/doc/guides/howto/lm_bond_virtio_sriov.rst b/doc/guides/howto/lm_bond_virtio_sriov.rst index 02ba1cdf5d..16d86d122c 100644 --- a/doc/guides/howto/lm_bond_virtio_sriov.rst +++ b/doc/guides/howto/lm_bond_virtio_sriov.rst @@ -591,7 +591,7 @@ Set up DPDK in the Virtual Machine rmmod virtio-pci ixgbevf modprobe uio - insmod /root/dpdk//kernel/linux/igb_uio/igb_uio.ko + insmod igb_uio.ko /root/dpdk/usertools/dpdk-devbind.py -b igb_uio 0000:00:03.0 /root/dpdk/usertools/dpdk-devbind.py -b igb_uio 0000:00:04.0 diff --git a/doc/guides/howto/lm_virtio_vhost_user.rst b/doc/guides/howto/lm_virtio_vhost_user.rst index 330ff5a9c8..e495ac976e 100644 --- a/doc/guides/howto/lm_virtio_vhost_user.rst +++ b/doc/guides/howto/lm_virtio_vhost_user.rst @@ -421,7 +421,7 @@ setup_dpdk_virtio_in_vm.sh rmmod virtio-pci modprobe uio - insmod /root/dpdk//kernel/linux/igb_uio/igb_uio.ko + insmod igb_uio.ko /root/dpdk/usertools/dpdk-devbind.py -b igb_uio 0000:00:03.0 /root/dpdk/usertools/dpdk-devbind.py -b igb_uio 0000:00:04.0 diff --git a/doc/guides/howto/openwrt.rst b/doc/guides/howto/openwrt.rst index 6081f057be..e1d7db2a90 100644 --- a/doc/guides/howto/openwrt.rst +++ b/doc/guides/howto/openwrt.rst @@ -103,11 +103,6 @@ first. meson builddir --cross-file openwrt-cross ninja -C builddir -.. note:: - - For compiling the igb_uio with the kernel version used in target machine, - you need to explicitly specify kernel_dir in meson_options.txt. - Running DPDK application on OpenWrt ----------------------------------- diff --git a/doc/guides/linux_gsg/enable_func.rst b/doc/guides/linux_gsg/enable_func.rst index 06c17e4058..aab32252ea 100644 --- a/doc/guides/linux_gsg/enable_func.rst +++ b/doc/guides/linux_gsg/enable_func.rst @@ -155,4 +155,5 @@ This results in pass-through of the DMAR (DMA Remapping) lookup in the host. Also, if ``INTEL_IOMMU_DEFAULT_ON`` is not set in the kernel, the ``intel_iommu=on`` kernel parameter must be used too. This ensures that the Intel IOMMU is being initialized as expected. -Please note that while using ``iommu=pt`` is compulsory for ``igb_uio driver``, the ``vfio-pci`` driver can actually work with both ``iommu=pt`` and ``iommu=on``. +Please note that while using ``iommu=pt`` is compulsory for ``igb_uio`` driver, +the ``vfio-pci`` driver can actually work with both ``iommu=pt`` and ``iommu=on``. diff --git a/doc/guides/linux_gsg/linux_drivers.rst b/doc/guides/linux_gsg/linux_drivers.rst index 7789c572bb..080b44955a 100644 --- a/doc/guides/linux_gsg/linux_drivers.rst +++ b/doc/guides/linux_gsg/linux_drivers.rst @@ -27,33 +27,20 @@ can provide the uio capability. This module can be loaded using the command: ``uio_pci_generic`` module doesn't support the creation of virtual functions. -As an alternative to the ``uio_pci_generic``, the DPDK also includes the igb_uio -module which can be found in the kernel/linux subdirectory referred to above. It can -be loaded as shown below: +As an alternative to the ``uio_pci_generic``, there is the ``igb_uio`` module +which can be found in the repository `dpdk-kmods `_. +It can be loaded as shown below: .. code-block:: console sudo modprobe uio - sudo insmod /kernel/linux/igb_uio/igb_uio.ko - -.. note:: - - Building DPDK Linux kernel modules is disabled by default starting from DPDK 20.02. - To enable them again, the config option "enable_kmods" needs to be set - in the meson build configuration. - See :ref:`adjusting_build_options` for details on how to set/clear build options. - It is planned to move ``igb_uio`` module to a different git repository. - -.. note:: - - For some devices which lack support for legacy interrupts, e.g. virtual function - (VF) devices, the ``igb_uio`` module may be needed in place of ``uio_pci_generic``. + sudo insmod igb_uio.ko .. note:: If UEFI secure boot is enabled, the Linux kernel may disallow the use of UIO on the system. Therefore, devices for use by DPDK should be bound to the - ``vfio-pci`` kernel module rather than ``igb_uio`` or ``uio_pci_generic``. + ``vfio-pci`` kernel module rather than any UIO-based module. For more details see :ref:`linux_gsg_binding_kernel` below. .. note:: diff --git a/doc/guides/nics/build_and_test.rst b/doc/guides/nics/build_and_test.rst index 3138c0f880..ba196382a9 100644 --- a/doc/guides/nics/build_and_test.rst +++ b/doc/guides/nics/build_and_test.rst @@ -69,7 +69,7 @@ This section demonstrates how to setup and run ``testpmd`` in Linux. .. code-block:: console modprobe uio - insmod ./x86_64-native-linux-gcc/kmod/igb_uio.ko + insmod igb_uio.ko or diff --git a/doc/guides/nics/ena.rst b/doc/guides/nics/ena.rst index bec97c3326..3a6074cdf6 100644 --- a/doc/guides/nics/ena.rst +++ b/doc/guides/nics/ena.rst @@ -169,8 +169,8 @@ Prerequisites (*) ENAv2 hardware supports Low Latency Queue v2 (LLQv2). This feature reduces the latency of the packets by pushing the header directly through the PCI to the device, before the DMA is even triggered. For proper work - kernel PCI driver must support write combining (WC). In mainline version of - ``igb_uio`` (in DPDK repo) it must be enabled by loading module with + kernel PCI driver must support write combining (WC). + In DPDK ``igb_uio`` it must be enabled by loading module with ``wc_activate=1`` flag (example below). However, mainline's vfio-pci driver in kernel doesn't have WC support yet (planed to be added). If vfio-pci used user should be either turn off ENAv2 (to avoid performance diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 8080a28896..584e720879 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -78,13 +78,6 @@ Deprecation Notices These wrappers must be used for patches that need to be merged in 20.08 onwards. This change will not introduce any performance degradation. -* igb_uio: In the view of reducing the kernel dependency from the main tree, - as a first step, the Technical Board decided to move ``igb_uio`` - kernel module to the dpdk-kmods repository in the /linux/igb_uio/ directory - in 20.11. - Minutes of Technical Board Meeting of `2019-11-06 - `_. - * lib: will fix extending some enum/define breaking the ABI. There are multiple samples in DPDK that enum/define terminated with a ``.*MAX.*`` value which is used by iterators, and arrays holding these values are sized with this diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst index da6e902eb2..ca5ec73914 100644 --- a/doc/guides/rel_notes/release_20_11.rst +++ b/doc/guides/rel_notes/release_20_11.rst @@ -126,8 +126,10 @@ Removed Items * vhost: Dequeue zero-copy support has been removed. -* Removed Python 2 support since it was EOL'd in January 2020. +* kernel: The module ``igb_uio`` has been moved to the git repository + ``dpdk-kmods`` in a new directory ``linux/igb_uio``. +* Removed Python 2 support since it was EOL'd in January 2020. API Changes ----------- diff --git a/doc/guides/sample_app_ug/multi_process.rst b/doc/guides/sample_app_ug/multi_process.rst index f2a79a6397..bd329c2db2 100644 --- a/doc/guides/sample_app_ug/multi_process.rst +++ b/doc/guides/sample_app_ug/multi_process.rst @@ -64,8 +64,6 @@ The process should start successfully and display a command prompt as follows: EAL: Virtual area found at 0x7ff200000000 (size = 0x40000000) ... - EAL: check igb_uio module - EAL: check module finished EAL: Master core 0 is ready (tid=54e41820) EAL: Core 1 is ready (tid=53b32700) diff --git a/drivers/bus/pci/bsd/pci.c b/drivers/bus/pci/bsd/pci.c index 2ed8261349..97c611737a 100644 --- a/drivers/bus/pci/bsd/pci.c +++ b/drivers/bus/pci/bsd/pci.c @@ -50,7 +50,7 @@ * This code is used to simulate a PCI probe by parsing information in * sysfs. Moreover, when a registered driver matches a device, the * kernel driver currently using it is unloaded and replaced by - * igb_uio module, which is a very minimal userland driver for Intel + * nic_uio module, which is a very minimal userland driver for Intel * network card, only providing access to PCI BAR to applications, and * enabling bus master. */ diff --git a/kernel/linux/igb_uio/Kbuild b/kernel/linux/igb_uio/Kbuild deleted file mode 100644 index 3ab85c4116..0000000000 --- a/kernel/linux/igb_uio/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -ccflags-y := $(MODULE_CFLAGS) -obj-m := igb_uio.o diff --git a/kernel/linux/igb_uio/compat.h b/kernel/linux/igb_uio/compat.h deleted file mode 100644 index 8dbb896ae1..0000000000 --- a/kernel/linux/igb_uio/compat.h +++ /dev/null @@ -1,154 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Minimal wrappers to allow compiling igb_uio on older kernels. - */ - -#ifndef RHEL_RELEASE_VERSION -#define RHEL_RELEASE_VERSION(a, b) (((a) << 8) + (b)) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) -#define pci_cfg_access_lock pci_block_user_cfg_access -#define pci_cfg_access_unlock pci_unblock_user_cfg_access -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) -#define HAVE_PTE_MASK_PAGE_IOMAP -#endif - -#ifndef PCI_MSIX_ENTRY_SIZE -#define PCI_MSIX_ENTRY_SIZE 16 -#define PCI_MSIX_ENTRY_VECTOR_CTRL 12 -#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 -#endif - -/* - * for kernels < 2.6.38 and backported patch that moves MSI-X entry definition - * to pci_regs.h Those kernels has PCI_MSIX_ENTRY_SIZE defined but not - * PCI_MSIX_ENTRY_CTRL_MASKBIT - */ -#ifndef PCI_MSIX_ENTRY_CTRL_MASKBIT -#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) && \ - (!(defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5, 9))) - -static int pci_num_vf(struct pci_dev *dev) -{ - struct iov { - int pos; - int nres; - u32 cap; - u16 ctrl; - u16 total; - u16 initial; - u16 nr_virtfn; - } *iov = (struct iov *)dev->sriov; - - if (!dev->is_physfn) - return 0; - - return iov->nr_virtfn; -} - -#endif /* < 2.6.34 */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && \ - (!(defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 4))) - -#define kstrtoul strict_strtoul - -#endif /* < 2.6.39 */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) && \ - (!(defined(RHEL_RELEASE_CODE) && \ - RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(6, 3))) - -/* Check if INTX works to control irq's. - * Set's INTX_DISABLE flag and reads it back - */ -static bool pci_intx_mask_supported(struct pci_dev *pdev) -{ - bool mask_supported = false; - uint16_t orig, new; - - pci_block_user_cfg_access(pdev); - pci_read_config_word(pdev, PCI_COMMAND, &orig); - pci_write_config_word(pdev, PCI_COMMAND, - orig ^ PCI_COMMAND_INTX_DISABLE); - pci_read_config_word(pdev, PCI_COMMAND, &new); - - if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) { - dev_err(&pdev->dev, "Command register changed from " - "0x%x to 0x%x: driver or hardware bug?\n", orig, new); - } else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) { - mask_supported = true; - pci_write_config_word(pdev, PCI_COMMAND, orig); - } - pci_unblock_user_cfg_access(pdev); - - return mask_supported; -} - -static bool pci_check_and_mask_intx(struct pci_dev *pdev) -{ - bool pending; - uint32_t status; - - pci_block_user_cfg_access(pdev); - pci_read_config_dword(pdev, PCI_COMMAND, &status); - - /* interrupt is not ours, goes to out */ - pending = (((status >> 16) & PCI_STATUS_INTERRUPT) != 0); - if (pending) { - uint16_t old, new; - - old = status; - if (status != 0) - new = old & (~PCI_COMMAND_INTX_DISABLE); - else - new = old | PCI_COMMAND_INTX_DISABLE; - - if (old != new) - pci_write_config_word(pdev, PCI_COMMAND, new); - } - pci_unblock_user_cfg_access(pdev); - - return pending; -} - -#endif /* < 3.3.0 */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) -#define HAVE_PCI_IS_BRIDGE_API 1 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) -#define HAVE_MSI_LIST_IN_GENERIC_DEVICE 1 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) -#define HAVE_PCI_MSI_MASK_IRQ 1 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) -#define HAVE_ALLOC_IRQ_VECTORS 1 -#endif - -static inline bool igbuio_kernel_is_locked_down(void) -{ -#ifdef CONFIG_LOCK_DOWN_KERNEL -#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT - return kernel_is_locked_down(NULL); -#elif defined(CONFIG_EFI_SECURE_BOOT_LOCK_DOWN) - return kernel_is_locked_down(); -#else - return false; -#endif -#else - return false; -#endif -} diff --git a/kernel/linux/igb_uio/igb_uio.c b/kernel/linux/igb_uio/igb_uio.c deleted file mode 100644 index 039f5a5f63..0000000000 --- a/kernel/linux/igb_uio/igb_uio.c +++ /dev/null @@ -1,660 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*- - * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "compat.h" - -/** - * A structure describing the private information for a uio device. - */ -struct rte_uio_pci_dev { - struct uio_info info; - struct pci_dev *pdev; - enum rte_intr_mode mode; - atomic_t refcnt; -}; - -static int wc_activate; -static char *intr_mode; -static enum rte_intr_mode igbuio_intr_mode_preferred = RTE_INTR_MODE_MSIX; -/* sriov sysfs */ -static ssize_t -show_max_vfs(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, 10, "%u\n", dev_num_vf(dev)); -} - -static ssize_t -store_max_vfs(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int err = 0; - unsigned long max_vfs; - struct pci_dev *pdev = to_pci_dev(dev); - - if (0 != kstrtoul(buf, 0, &max_vfs)) - return -EINVAL; - - if (0 == max_vfs) - pci_disable_sriov(pdev); - else if (0 == pci_num_vf(pdev)) - err = pci_enable_sriov(pdev, max_vfs); - else /* do nothing if change max_vfs number */ - err = -EINVAL; - - return err ? err : count; -} - -static DEVICE_ATTR(max_vfs, S_IRUGO | S_IWUSR, show_max_vfs, store_max_vfs); - -static struct attribute *dev_attrs[] = { - &dev_attr_max_vfs.attr, - NULL, -}; - -static const struct attribute_group dev_attr_grp = { - .attrs = dev_attrs, -}; - -#ifndef HAVE_PCI_MSI_MASK_IRQ -/* - * It masks the msix on/off of generating MSI-X messages. - */ -static void -igbuio_msix_mask_irq(struct msi_desc *desc, s32 state) -{ - u32 mask_bits = desc->masked; - unsigned int offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_VECTOR_CTRL; - - if (state != 0) - mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; - else - mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; - - if (mask_bits != desc->masked) { - writel(mask_bits, desc->mask_base + offset); - readl(desc->mask_base); - desc->masked = mask_bits; - } -} - -/* - * 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; - - if (!desc->msi_attrib.maskbit) - return; - - if (state != 0) - mask_bits &= ~mask; - else - mask_bits |= mask; - - if (mask_bits != desc->masked) { - pci_write_config_dword(pdev, desc->mask_pos, mask_bits); - desc->masked = mask_bits; - } -} - -static void -igbuio_mask_irq(struct pci_dev *pdev, enum rte_intr_mode mode, s32 irq_state) -{ - struct msi_desc *desc; - struct list_head *msi_list; - -#ifdef HAVE_MSI_LIST_IN_GENERIC_DEVICE - msi_list = &pdev->dev.msi_list; -#else - msi_list = &pdev->msi_list; -#endif - - if (mode == RTE_INTR_MODE_MSIX) { - list_for_each_entry(desc, msi_list, list) - igbuio_msix_mask_irq(desc, irq_state); - } else if (mode == RTE_INTR_MODE_MSI) { - list_for_each_entry(desc, msi_list, list) - igbuio_msi_mask_irq(pdev, desc, irq_state); - } -} -#endif - -/** - * This is the irqcontrol callback to be registered to uio_info. - * It can be used to disable/enable interrupt from user space processes. - * - * @param info - * pointer to uio_info. - * @param irq_state - * state value. 1 to enable interrupt, 0 to disable interrupt. - * - * @return - * - On success, 0. - * - On failure, a negative value. - */ -static int -igbuio_pci_irqcontrol(struct uio_info *info, s32 irq_state) -{ - struct rte_uio_pci_dev *udev = info->priv; - struct pci_dev *pdev = udev->pdev; - -#ifdef HAVE_PCI_MSI_MASK_IRQ - struct irq_data *irq = irq_get_irq_data(udev->info.irq); -#endif - - pci_cfg_access_lock(pdev); - - 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); - else - pci_msi_mask_irq(irq); -#else - igbuio_mask_irq(pdev, udev->mode, irq_state); -#endif - } - - if (udev->mode == RTE_INTR_MODE_LEGACY) - pci_intx(pdev, !!irq_state); - - pci_cfg_access_unlock(pdev); - - return 0; -} - -/** - * This is interrupt handler which will check if the interrupt is for the right device. - * If yes, disable it here and will be enable later. - */ -static irqreturn_t -igbuio_pci_irqhandler(int irq, void *dev_id) -{ - struct rte_uio_pci_dev *udev = (struct rte_uio_pci_dev *)dev_id; - struct uio_info *info = &udev->info; - - /* Legacy mode need to mask in hardware */ - if (udev->mode == RTE_INTR_MODE_LEGACY && - !pci_check_and_mask_intx(udev->pdev)) - return IRQ_NONE; - - uio_event_notify(info); - - /* Message signal mode, no share IRQ and automasked */ - return IRQ_HANDLED; -} - -static int -igbuio_pci_enable_interrupts(struct rte_uio_pci_dev *udev) -{ - int err = 0; -#ifndef HAVE_ALLOC_IRQ_VECTORS - struct msix_entry msix_entry; -#endif - - switch (igbuio_intr_mode_preferred) { - case RTE_INTR_MODE_MSIX: - /* Only 1 msi-x vector needed */ -#ifndef HAVE_ALLOC_IRQ_VECTORS - msix_entry.entry = 0; - if (pci_enable_msix(udev->pdev, &msix_entry, 1) == 0) { - dev_dbg(&udev->pdev->dev, "using MSI-X"); - udev->info.irq_flags = IRQF_NO_THREAD; - udev->info.irq = msix_entry.vector; - udev->mode = RTE_INTR_MODE_MSIX; - break; - } -#else - if (pci_alloc_irq_vectors(udev->pdev, 1, 1, PCI_IRQ_MSIX) == 1) { - dev_dbg(&udev->pdev->dev, "using MSI-X"); - udev->info.irq_flags = IRQF_NO_THREAD; - udev->info.irq = pci_irq_vector(udev->pdev, 0); - udev->mode = RTE_INTR_MODE_MSIX; - break; - } -#endif - - /* falls through - 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 - /* falls through - to INTX */ - case RTE_INTR_MODE_LEGACY: - if (pci_intx_mask_supported(udev->pdev)) { - dev_dbg(&udev->pdev->dev, "using INTX"); - udev->info.irq_flags = IRQF_SHARED | IRQF_NO_THREAD; - udev->info.irq = udev->pdev->irq; - udev->mode = RTE_INTR_MODE_LEGACY; - break; - } - dev_notice(&udev->pdev->dev, "PCI INTX mask not supported\n"); - /* falls through - to no IRQ */ - case RTE_INTR_MODE_NONE: - udev->mode = RTE_INTR_MODE_NONE; - udev->info.irq = UIO_IRQ_NONE; - break; - - default: - dev_err(&udev->pdev->dev, "invalid IRQ mode %u", - igbuio_intr_mode_preferred); - udev->info.irq = UIO_IRQ_NONE; - err = -EINVAL; - } - - if (udev->info.irq != UIO_IRQ_NONE) - err = request_irq(udev->info.irq, igbuio_pci_irqhandler, - udev->info.irq_flags, udev->info.name, - udev); - dev_info(&udev->pdev->dev, "uio device registered with irq %ld\n", - udev->info.irq); - - return err; -} - -static void -igbuio_pci_disable_interrupts(struct rte_uio_pci_dev *udev) -{ - if (udev->info.irq) { - free_irq(udev->info.irq, udev); - udev->info.irq = 0; - } - -#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 || - udev->mode == RTE_INTR_MODE_MSI) - pci_free_irq_vectors(udev->pdev); -#endif -} - - -/** - * This gets called while opening uio device file. - */ -static int -igbuio_pci_open(struct uio_info *info, struct inode *inode) -{ - struct rte_uio_pci_dev *udev = info->priv; - struct pci_dev *dev = udev->pdev; - int err; - - if (atomic_inc_return(&udev->refcnt) != 1) - return 0; - - /* set bus master, which was cleared by the reset function */ - pci_set_master(dev); - - /* enable interrupts */ - err = igbuio_pci_enable_interrupts(udev); - if (err) { - atomic_dec(&udev->refcnt); - dev_err(&dev->dev, "Enable interrupt fails\n"); - } - return err; -} - -static int -igbuio_pci_release(struct uio_info *info, struct inode *inode) -{ - struct rte_uio_pci_dev *udev = info->priv; - struct pci_dev *dev = udev->pdev; - - if (atomic_dec_and_test(&udev->refcnt)) { - /* disable interrupts */ - igbuio_pci_disable_interrupts(udev); - - /* stop the device from further DMA */ - pci_clear_master(dev); - } - - return 0; -} - -/* Remap pci resources described by bar #pci_bar in uio resource n. */ -static int -igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info, - int n, int pci_bar, const char *name) -{ - unsigned long addr, len; - void *internal_addr; - - if (n >= ARRAY_SIZE(info->mem)) - return -EINVAL; - - addr = pci_resource_start(dev, pci_bar); - len = pci_resource_len(dev, pci_bar); - if (addr == 0 || len == 0) - return -1; - if (wc_activate == 0) { - internal_addr = ioremap(addr, len); - if (internal_addr == NULL) - return -1; - } else { - internal_addr = NULL; - } - info->mem[n].name = name; - info->mem[n].addr = addr; - info->mem[n].internal_addr = internal_addr; - info->mem[n].size = len; - info->mem[n].memtype = UIO_MEM_PHYS; - return 0; -} - -/* Get pci port io resources described by bar #pci_bar in uio resource n. */ -static int -igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info, - int n, int pci_bar, const char *name) -{ - unsigned long addr, len; - - if (n >= ARRAY_SIZE(info->port)) - return -EINVAL; - - addr = pci_resource_start(dev, pci_bar); - len = pci_resource_len(dev, pci_bar); - if (addr == 0 || len == 0) - return -EINVAL; - - info->port[n].name = name; - info->port[n].start = addr; - info->port[n].size = len; - info->port[n].porttype = UIO_PORT_X86; - - return 0; -} - -/* Unmap previously ioremap'd resources */ -static void -igbuio_pci_release_iomem(struct uio_info *info) -{ - int i; - - for (i = 0; i < MAX_UIO_MAPS; i++) { - if (info->mem[i].internal_addr) - iounmap(info->mem[i].internal_addr); - } -} - -static int -igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info) -{ - int i, iom, iop, ret; - unsigned long flags; - static const char *bar_names[PCI_STD_RESOURCE_END + 1] = { - "BAR0", - "BAR1", - "BAR2", - "BAR3", - "BAR4", - "BAR5", - }; - - iom = 0; - iop = 0; - - for (i = 0; i < ARRAY_SIZE(bar_names); i++) { - if (pci_resource_len(dev, i) != 0 && - pci_resource_start(dev, i) != 0) { - flags = pci_resource_flags(dev, i); - if (flags & IORESOURCE_MEM) { - ret = igbuio_pci_setup_iomem(dev, info, iom, - i, bar_names[i]); - if (ret != 0) - return ret; - iom++; - } else if (flags & IORESOURCE_IO) { - ret = igbuio_pci_setup_ioport(dev, info, iop, - i, bar_names[i]); - if (ret != 0) - return ret; - iop++; - } - } - } - - return (iom != 0 || iop != 0) ? ret : -ENOENT; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) -static int __devinit -#else -static int -#endif -igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct rte_uio_pci_dev *udev; - dma_addr_t map_dma_addr; - void *map_addr; - int err; - -#ifdef HAVE_PCI_IS_BRIDGE_API - if (pci_is_bridge(dev)) { - dev_warn(&dev->dev, "Ignoring PCI bridge device\n"); - return -ENODEV; - } -#endif - - udev = kzalloc(sizeof(struct rte_uio_pci_dev), GFP_KERNEL); - if (!udev) - return -ENOMEM; - - /* - * enable device: ask low-level code to enable I/O and - * memory - */ - err = pci_enable_device(dev); - if (err != 0) { - dev_err(&dev->dev, "Cannot enable PCI device\n"); - goto fail_free; - } - - /* enable bus mastering on the device */ - pci_set_master(dev); - - /* remap IO memory */ - err = igbuio_setup_bars(dev, &udev->info); - if (err != 0) - goto fail_release_iomem; - - /* set 64-bit DMA mask */ - err = pci_set_dma_mask(dev, DMA_BIT_MASK(64)); - if (err != 0) { - dev_err(&dev->dev, "Cannot set DMA mask\n"); - goto fail_release_iomem; - } - - err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); - if (err != 0) { - dev_err(&dev->dev, "Cannot set consistent DMA mask\n"); - goto fail_release_iomem; - } - - /* fill uio infos */ - udev->info.name = "igb_uio"; - udev->info.version = "0.1"; - udev->info.irqcontrol = igbuio_pci_irqcontrol; - udev->info.open = igbuio_pci_open; - udev->info.release = igbuio_pci_release; - udev->info.priv = udev; - udev->pdev = dev; - atomic_set(&udev->refcnt, 0); - - err = sysfs_create_group(&dev->dev.kobj, &dev_attr_grp); - if (err != 0) - goto fail_release_iomem; - - /* register uio driver */ - err = uio_register_device(&dev->dev, &udev->info); - if (err != 0) - goto fail_remove_group; - - pci_set_drvdata(dev, udev); - - /* - * Doing a harmless dma mapping for attaching the device to - * the iommu identity mapping if kernel boots with iommu=pt. - * Note this is not a problem if no IOMMU at all. - */ - map_addr = dma_alloc_coherent(&dev->dev, 1024, &map_dma_addr, - GFP_KERNEL); - if (map_addr) - memset(map_addr, 0, 1024); - - if (!map_addr) - dev_info(&dev->dev, "dma mapping failed\n"); - else { - dev_info(&dev->dev, "mapping 1K dma=%#llx host=%p\n", - (unsigned long long)map_dma_addr, map_addr); - - dma_free_coherent(&dev->dev, 1024, map_addr, map_dma_addr); - dev_info(&dev->dev, "unmapping 1K dma=%#llx host=%p\n", - (unsigned long long)map_dma_addr, map_addr); - } - - return 0; - -fail_remove_group: - sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); -fail_release_iomem: - igbuio_pci_release_iomem(&udev->info); - pci_disable_device(dev); -fail_free: - kfree(udev); - - return err; -} - -static void -igbuio_pci_remove(struct pci_dev *dev) -{ - struct rte_uio_pci_dev *udev = pci_get_drvdata(dev); - - igbuio_pci_release(&udev->info, NULL); - - sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); - uio_unregister_device(&udev->info); - igbuio_pci_release_iomem(&udev->info); - pci_disable_device(dev); - pci_set_drvdata(dev, NULL); - kfree(udev); -} - -static int -igbuio_config_intr_mode(char *intr_str) -{ - if (!intr_str) { - pr_info("Use MSIX interrupt by default\n"); - return 0; - } - - 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"); - } else { - pr_info("Error: bad parameter - %s\n", intr_str); - return -EINVAL; - } - - return 0; -} - -static struct pci_driver igbuio_pci_driver = { - .name = "igb_uio", - .id_table = NULL, - .probe = igbuio_pci_probe, - .remove = igbuio_pci_remove, -}; - -static int __init -igbuio_pci_init_module(void) -{ - int ret; - - if (igbuio_kernel_is_locked_down()) { - pr_err("Not able to use module, kernel lock down is enabled\n"); - return -EINVAL; - } - - if (wc_activate != 0) - pr_info("wc_activate is set\n"); - - ret = igbuio_config_intr_mode(intr_mode); - if (ret < 0) - return ret; - - return pci_register_driver(&igbuio_pci_driver); -} - -static void __exit -igbuio_pci_exit_module(void) -{ - pci_unregister_driver(&igbuio_pci_driver); -} - -module_init(igbuio_pci_init_module); -module_exit(igbuio_pci_exit_module); - -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"); - -module_param(wc_activate, int, 0); -MODULE_PARM_DESC(wc_activate, -"Activate support for write combining (WC) (default=0)\n" -" 0 - disable\n" -" other - enable\n"); - -MODULE_DESCRIPTION("UIO driver for Intel IGB PCI cards"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Intel Corporation"); diff --git a/kernel/linux/igb_uio/meson.build b/kernel/linux/igb_uio/meson.build deleted file mode 100644 index 80540aecee..0000000000 --- a/kernel/linux/igb_uio/meson.build +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation - -mkfile = custom_target('igb_uio_makefile', - output: 'Makefile', - command: ['touch', '@OUTPUT@']) - -custom_target('igb_uio', - input: ['igb_uio.c', 'Kbuild'], - output: 'igb_uio.ko', - command: ['make', '-C', kernel_dir + '/build', - 'M=' + meson.current_build_dir(), - 'src=' + meson.current_source_dir(), - 'EXTRA_CFLAGS=-I' + meson.current_source_dir() + - '/../../../lib/librte_eal/include', - 'modules'], - depends: mkfile, - install: true, - install_dir: kernel_dir + '/extra/dpdk', - build_by_default: get_option('enable_kmods')) diff --git a/kernel/linux/meson.build b/kernel/linux/meson.build index da79df1687..5c864a4653 100644 --- a/kernel/linux/meson.build +++ b/kernel/linux/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2018 Intel Corporation -subdirs = ['igb_uio', 'kni'] +subdirs = ['kni'] # if we are cross-compiling we need kernel_dir specified if get_option('kernel_dir') == '' and meson.is_cross_build() -- 2.20.1