get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/7368/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 7368,
    "url": "https://patches.dpdk.org/api/patches/7368/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1443785140-8706-3-git-send-email-alejandro.lucero@netronome.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1443785140-8706-3-git-send-email-alejandro.lucero@netronome.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1443785140-8706-3-git-send-email-alejandro.lucero@netronome.com",
    "date": "2015-10-02T11:25:39",
    "name": "[dpdk-dev,2/3] This patch adds a new UIO driver for Netronome NFP PCI cards.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "f6b8a713426a81b3859a8e97c2d95bab3bfc4541",
    "submitter": {
        "id": 270,
        "url": "https://patches.dpdk.org/api/people/270/?format=api",
        "name": "Alejandro Lucero",
        "email": "alejandro.lucero@netronome.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1443785140-8706-3-git-send-email-alejandro.lucero@netronome.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7368/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7368/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 22F558E7D;\n\tFri,  2 Oct 2015 13:25:44 +0200 (CEST)",
            "from ubuntu (host217-39-174-19.in-addr.btopenworld.com\n\t[217.39.174.19]) by dpdk.org (Postfix) with SMTP id F36208E72\n\tfor <dev@dpdk.org>; Fri,  2 Oct 2015 13:25:40 +0200 (CEST)",
            "by ubuntu (Postfix, from userid 5466)\n\tid D03C8E0249; Fri,  2 Oct 2015 12:25:40 +0100 (BST)"
        ],
        "From": "\"Alejandro.Lucero\" <alejandro.lucero@netronome.com>",
        "To": "dev@dpdk.org",
        "Date": "Fri,  2 Oct 2015 12:25:39 +0100",
        "Message-Id": "<1443785140-8706-3-git-send-email-alejandro.lucero@netronome.com>",
        "X-Mailer": "git-send-email 1.7.9.5",
        "In-Reply-To": "<1443785140-8706-1-git-send-email-alejandro.lucero@netronome.com>",
        "References": "<1443785140-8706-1-git-send-email-alejandro.lucero@netronome.com>",
        "Subject": "[dpdk-dev] [PATCH 2/3] This patch adds a new UIO driver for\n\tNetronome NFP PCI cards.",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: \"Alejandro.Lucero\" <alejandro.lucero@netronome.com>\n\nCurrent Netronome's PMD just supports Virtual Functions. Future Physical\nFunction support will require specific Netronome code here.\n\nSigned-off-by: Alejandro.Lucero <alejandro.lucero@netronome.com>\nSigned-off-by: Rolf.Neugebauer <rolf.neugebauer@netronome.com>\n---\n lib/librte_eal/common/include/rte_pci.h   |    1 +\n lib/librte_eal/linuxapp/eal/eal_pci.c     |    4 +\n lib/librte_eal/linuxapp/eal/eal_pci_uio.c |    2 +-\n lib/librte_eal/linuxapp/nfp_uio/Makefile  |   53 +++\n lib/librte_eal/linuxapp/nfp_uio/nfp_uio.c |  497 +++++++++++++++++++++++++++++\n lib/librte_ether/rte_ethdev.c             |    1 +\n 6 files changed, 557 insertions(+), 1 deletion(-)\n create mode 100644 lib/librte_eal/linuxapp/nfp_uio/Makefile\n create mode 100644 lib/librte_eal/linuxapp/nfp_uio/nfp_uio.c",
    "diff": "diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h\nindex 83e3c28..89baaf6 100644\n--- a/lib/librte_eal/common/include/rte_pci.h\n+++ b/lib/librte_eal/common/include/rte_pci.h\n@@ -146,6 +146,7 @@ struct rte_devargs;\n enum rte_kernel_driver {\n \tRTE_KDRV_UNKNOWN = 0,\n \tRTE_KDRV_IGB_UIO,\n+\tRTE_KDRV_NFP_UIO,\n \tRTE_KDRV_VFIO,\n \tRTE_KDRV_UIO_GENERIC,\n \tRTE_KDRV_NIC_UIO,\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\nindex bc5b5be..19a93fe 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c\n@@ -137,6 +137,7 @@ pci_map_device(struct rte_pci_device *dev)\n #endif\n \t\tbreak;\n \tcase RTE_KDRV_IGB_UIO:\n+\tcase RTE_KDRV_NFP_UIO:\n \tcase RTE_KDRV_UIO_GENERIC:\n \t\t/* map resources for devices that use uio */\n \t\tret = pci_uio_map_resource(dev);\n@@ -161,6 +162,7 @@ pci_unmap_device(struct rte_pci_device *dev)\n \t\tRTE_LOG(ERR, EAL, \"Hotplug doesn't support vfio yet\\n\");\n \t\tbreak;\n \tcase RTE_KDRV_IGB_UIO:\n+\tcase RTE_KDRV_NFP_UIO:\n \tcase RTE_KDRV_UIO_GENERIC:\n \t\t/* unmap resources for devices that use uio */\n \t\tpci_uio_unmap_resource(dev);\n@@ -357,6 +359,8 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,\n \t\t\tdev->kdrv = RTE_KDRV_VFIO;\n \t\telse if (!strcmp(driver, \"igb_uio\"))\n \t\t\tdev->kdrv = RTE_KDRV_IGB_UIO;\n+\t\telse if (!strcmp(driver, \"nfp_uio\"))\n+\t\t\tdev->kdrv = RTE_KDRV_NFP_UIO;\n \t\telse if (!strcmp(driver, \"uio_pci_generic\"))\n \t\t\tdev->kdrv = RTE_KDRV_UIO_GENERIC;\n \t\telse\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\nindex ac50e13..29ec9cb 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n@@ -270,7 +270,7 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,\n \t\tgoto error;\n \t}\n \n-\tif (dev->kdrv == RTE_KDRV_IGB_UIO)\n+\tif (dev->kdrv == RTE_KDRV_IGB_UIO || dev->kdrv == RTE_KDRV_NFP_UIO)\n \t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n \telse {\n \t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX;\ndiff --git a/lib/librte_eal/linuxapp/nfp_uio/Makefile b/lib/librte_eal/linuxapp/nfp_uio/Makefile\nnew file mode 100644\nindex 0000000..b9e2f0a\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/nfp_uio/Makefile\n@@ -0,0 +1,53 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2014-2015 Netronome. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# module name and path\n+#\n+MODULE = nfp_uio\n+MODULE_PATH = drivers/net/nfp_uio\n+\n+#\n+# CFLAGS\n+#\n+MODULE_CFLAGS += -I$(SRCDIR) --param max-inline-insns-single=100\n+MODULE_CFLAGS += -I$(RTE_OUTPUT)/include\n+MODULE_CFLAGS += -Winline -Wall -Werror\n+MODULE_CFLAGS += -include $(RTE_OUTPUT)/include/rte_config.h\n+\n+#\n+# all source are stored in SRCS-y\n+#\n+SRCS-y := nfp_uio.c\n+\n+include $(RTE_SDK)/mk/rte.module.mk\ndiff --git a/lib/librte_eal/linuxapp/nfp_uio/nfp_uio.c b/lib/librte_eal/linuxapp/nfp_uio/nfp_uio.c\nnew file mode 100644\nindex 0000000..98192a5\n--- /dev/null\n+++ b/lib/librte_eal/linuxapp/nfp_uio/nfp_uio.c\n@@ -0,0 +1,497 @@\n+/*\n+ * Copyright (c) 2014, 2015 Netronome Systems, Inc.\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or without\n+ * modification, are permitted provided that the following conditions are met:\n+ *\n+ * 1. Redistributions of source code must retain the above copyright notice,\n+ *  this list of conditions and the following disclaimer.\n+ *\n+ * 2. Redistributions in binary form must reproduce the above copyright\n+ *  notice, this list of conditions and the following disclaimer in the\n+ *  documentation and/or other materials provided with the distribution\n+ *\n+ * 3. Neither the name of the copyright holder nor the names of its\n+ *  contributors may be used to endorse or promote products derived from this\n+ *  software without specific prior written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n+ * POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+/*\n+ * Netronome DPDK uio kernel module\n+ */\n+\n+#include <linux/device.h>\n+#include <linux/module.h>\n+#include <linux/pci.h>\n+#include <linux/uio_driver.h>\n+#include <linux/io.h>\n+#include <linux/msi.h>\n+#include <linux/version.h>\n+\n+#ifndef PCI_MSIX_ENTRY_SIZE\n+#define PCI_MSIX_ENTRY_SIZE             16\n+#define PCI_MSIX_ENTRY_LOWER_ADDR       0\n+#define PCI_MSIX_ENTRY_UPPER_ADDR       4\n+#define PCI_MSIX_ENTRY_DATA             8\n+#define PCI_MSIX_ENTRY_VECTOR_CTRL      12\n+#define PCI_MSIX_ENTRY_CTRL_MASKBIT     1\n+#endif\n+\n+/* Ideally we should support two types of interrupts:\n+ *\n+ * - Link Status Change Interrupt\n+ * - Exception Interrupt\n+ *\n+ * But the uio Linux kernel interface just admits one interrupt per uio device.\n+ */\n+#define NFP_NUM_MSI_VECTORS 1\n+\n+/*\n+ * A structure describing the private information for a uio device.\n+ */\n+struct nfp_uio_pci_dev {\n+\tstruct uio_info info;\n+\tstruct pci_dev *pdev;\n+\t/* spinlock for accessing PCI config space or msix\n+\t * data in multi tasks/isr\n+\t */\n+\tspinlock_t lock;\n+\n+\t/* pointer to the msix vectors to be allocated later */\n+\tstruct msix_entry msix_entries[NFP_NUM_MSI_VECTORS];\n+};\n+\n+#define PCI_VENDOR_ID_NETRONOME\t\t0x19ee\n+#define PCI_DEVICE_NFP6000_VF_NIC\t0x6003\n+\n+#define RTE_PCI_DEV_ID_DECL_NETRO(vend, dev) {PCI_DEVICE(vend, dev)},\n+\n+/* PCI device id table */\n+static struct pci_device_id nfp_uio_pci_ids[] = {\n+RTE_PCI_DEV_ID_DECL_NETRO(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_NFP6000_VF_NIC)\n+{ 0, },\n+};\n+\n+MODULE_DEVICE_TABLE(pci, nfp_uio_pci_ids);\n+\n+static inline struct nfp_uio_pci_dev *\n+nfp_uio_get_uio_pci_dev(struct uio_info *info)\n+{\n+\treturn container_of(info, struct nfp_uio_pci_dev, info);\n+}\n+\n+static inline int\n+pci_lock(struct pci_dev *pdev)\n+{\n+\t/* Some function names changes between 3.2.0 and 3.3.0... */\n+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)\n+\tpci_block_user_cfg_access(pdev);\n+\treturn 1;\n+#else\n+\treturn pci_cfg_access_trylock(pdev);\n+#endif\n+}\n+\n+static inline void\n+pci_unlock(struct pci_dev *pdev)\n+{\n+\t/* Some function names changes between 3.2.0 and 3.3.0... */\n+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)\n+\tpci_unblock_user_cfg_access(pdev);\n+#else\n+\tpci_cfg_access_unlock(pdev);\n+#endif\n+}\n+\n+/*\n+ * It masks the msix on/off of generating MSI-X messages.\n+ */\n+static int\n+nfp_uio_msix_mask_irq(struct msi_desc *desc, int32_t state)\n+{\n+\tu32 mask_bits = desc->masked;\n+\tunsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +\n+\t\t\t\t\t\tPCI_MSIX_ENTRY_VECTOR_CTRL;\n+\n+\tif (state != 0)\n+\t\tmask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;\n+\telse\n+\t\tmask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;\n+\n+\tif (mask_bits != desc->masked) {\n+\t\twritel(mask_bits, desc->mask_base + offset);\n+\t\treadl(desc->mask_base);\n+\t\tdesc->masked = mask_bits;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * This function sets/clears the masks for generating LSC interrupts.\n+ *\n+ * @param info\n+ *   The pointer to struct uio_info.\n+ * @param on\n+ *   The on/off flag of masking LSC.\n+ * @return\n+ *   -On success, zero value.\n+ *   -On failure, a negative value.\n+ */\n+static int\n+nfp_uio_set_interrupt_mask(struct nfp_uio_pci_dev *udev, int32_t state)\n+{\n+\tstruct pci_dev *pdev = udev->pdev;\n+\tstruct msi_desc *desc;\n+\n+\t/* TODO: Should we change this based on if the firmware advertises\n+\t\t\t NFP_NET_CFG_CTRL_MSIXAUTO? */\n+\n+\tlist_for_each_entry(desc, &pdev->msi_list, list) {\n+\t\tnfp_uio_msix_mask_irq(desc, state);\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * This is the irqcontrol callback to be registered to uio_info.\n+ * It can be used to disable/enable interrupt from user space processes.\n+ *\n+ * @param info\n+ *  pointer to uio_info.\n+ * @param irq_state\n+ *  state value. 1 to enable interrupt, 0 to disable interrupt.\n+ *\n+ * @return\n+ *  - On success, 0.\n+ *  - On failure, a negative value.\n+ */\n+static int\n+nfp_uio_pci_irqcontrol(struct uio_info *info, s32 irq_state)\n+{\n+\tunsigned long flags;\n+\tstruct nfp_uio_pci_dev *udev = nfp_uio_get_uio_pci_dev(info);\n+\tstruct pci_dev *pdev = udev->pdev;\n+\n+\tspin_lock_irqsave(&udev->lock, flags);\n+\tif (!pci_lock(pdev)) {\n+\t\tspin_unlock_irqrestore(&udev->lock, flags);\n+\t\treturn -1;\n+\t}\n+\n+\tnfp_uio_set_interrupt_mask(udev, irq_state);\n+\n+\tpci_unlock(pdev);\n+\tspin_unlock_irqrestore(&udev->lock, flags);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * This is interrupt handler which will check if the interrupt is for the right\n+   device. If yes, disable it here and will be enable later.\n+ */\n+static irqreturn_t\n+nfp_uio_pci_irqhandler(int irq, struct uio_info *info)\n+{\n+\tirqreturn_t ret = IRQ_NONE;\n+\tunsigned long flags;\n+\tstruct nfp_uio_pci_dev *udev = nfp_uio_get_uio_pci_dev(info);\n+\tstruct pci_dev *pdev = udev->pdev;\n+\n+\tspin_lock_irqsave(&udev->lock, flags);\n+\t/* block userspace PCI config reads/writes */\n+\tif (!pci_lock(pdev))\n+\t\tgoto spin_unlock;\n+\n+\tret = IRQ_HANDLED;\n+\n+\t/* unblock userspace PCI config reads/writes */\n+\tpci_unlock(pdev);\n+spin_unlock:\n+\tspin_unlock_irqrestore(&udev->lock, flags);\n+\tdev_info(&pdev->dev, \"irq 0x%x %s\\n\", irq,\n+\t\t (ret == IRQ_HANDLED) ? \"handled\" : \"not handled\");\n+\n+\treturn ret;\n+}\n+\n+/* Remap pci resources described by bar #pci_bar in uio resource n. */\n+static int\n+nfp_uio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,\n+\t\t\tint n, int pci_bar, const char *name)\n+{\n+\tunsigned long addr, len;\n+\tvoid *internal_addr;\n+\n+\tif (ARRAY_SIZE(info->mem) <= n)\n+\t\treturn -EINVAL;\n+\n+\taddr = pci_resource_start(dev, pci_bar);\n+\tlen = pci_resource_len(dev, pci_bar);\n+\tif (addr == 0 || len == 0)\n+\t\treturn -1;\n+\tinternal_addr = ioremap(addr, len);\n+\tif (!internal_addr)\n+\t\treturn -1;\n+\tinfo->mem[n].name = name;\n+\tinfo->mem[n].addr = addr;\n+\tinfo->mem[n].internal_addr = internal_addr;\n+\tinfo->mem[n].size = len;\n+\tinfo->mem[n].memtype = UIO_MEM_PHYS;\n+\treturn 0;\n+}\n+\n+/* Get pci port io resources described by bar #pci_bar in uio resource n. */\n+static int\n+nfp_uio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info,\n+\t\t\t int n, int pci_bar, const char *name)\n+{\n+\tunsigned long addr, len;\n+\n+\tif (ARRAY_SIZE(info->port) <= n)\n+\t\treturn -EINVAL;\n+\n+\taddr = pci_resource_start(dev, pci_bar);\n+\tlen = pci_resource_len(dev, pci_bar);\n+\tif (addr == 0 || len == 0)\n+\t\treturn -1;\n+\n+\tinfo->port[n].name = name;\n+\tinfo->port[n].start = addr;\n+\tinfo->port[n].size = len;\n+\tinfo->port[n].porttype = UIO_PORT_X86;\n+\n+\treturn 0;\n+}\n+\n+/* Unmap previously ioremap'd resources */\n+static void\n+nfp_uio_pci_release_iomem(struct uio_info *info)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < MAX_UIO_MAPS; i++) {\n+\t\tif (info->mem[i].internal_addr)\n+\t\t\tiounmap(info->mem[i].internal_addr);\n+\t}\n+}\n+\n+static int\n+nfp_uio_setup_bars(struct pci_dev *dev, struct uio_info *info)\n+{\n+\tint i, iom, iop, ret;\n+\tunsigned long flags;\n+\tstatic const char *bar_names[PCI_STD_RESOURCE_END + 1]  = {\n+\t\t\"BAR0\",\n+\t\t\"BAR1\",\n+\t\t\"BAR2\",\n+\t\t\"BAR3\",\n+\t\t\"BAR4\",\n+\t\t\"BAR5\",\n+\t};\n+\n+\tiom = 0;\n+\tiop = 0;\n+\n+\tfor (i = 0; i != ARRAY_SIZE(bar_names); i++) {\n+\t\tif (pci_resource_len(dev, i) == 0 ||\n+\t\t    pci_resource_start(dev, i) == 0)\n+\t\t\tcontinue;\n+\n+\t\tflags = pci_resource_flags(dev, i);\n+\t\tif (flags & IORESOURCE_MEM) {\n+\t\t\tret = nfp_uio_pci_setup_iomem(dev, info, iom, i,\n+\t\t\t\t\t\t      bar_names[i]);\n+\t\t\tif (ret != 0)\n+\t\t\t\treturn ret;\n+\t\t\tiom++;\n+\t\t} else if (flags & IORESOURCE_IO) {\n+\t\t\tret = nfp_uio_pci_setup_ioport(dev, info, iop, i,\n+\t\t\t\t\t\t       bar_names[i]);\n+\t\t\tif (ret != 0)\n+\t\t\t\treturn ret;\n+\t\t\tiop++;\n+\t\t}\n+\t}\n+\n+\treturn (iom != 0) ? ret : -ENOENT;\n+}\n+\n+/* Configuring interrupt. First try MSI-X, then MSI. */\n+static void\n+init_interrupt(struct nfp_uio_pci_dev *udev)\n+{\n+\tint vector;\n+\n+\tfor (vector = 0; vector < NFP_NUM_MSI_VECTORS; vector++)\n+\t\tudev->msix_entries[vector].entry = vector;\n+\n+\tif (pci_enable_msix(udev->pdev, udev->msix_entries,\n+\t\t\t    NFP_NUM_MSI_VECTORS) == 0) {\n+\t\tudev->info.irq_flags = 0;\n+\t\tudev->info.irq = udev->msix_entries[0].vector;\n+\t\tdev_info(&udev->pdev->dev, \"%s configured with MSI-X\\n\",\n+\t\t\t udev->info.name);\n+\t} else\n+\t\tdev_info(&udev->pdev->dev, \"%s MSI-X initialization error\\n\",\n+\t\t\t udev->info.name);\n+}\n+\n+static int\n+nfp_uio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)\n+{\n+\tstruct nfp_uio_pci_dev *udev;\n+\tvoid *map_addr;\n+\tdma_addr_t map_dma_addr;\n+\n+\tudev = kzalloc(sizeof(*udev), GFP_KERNEL);\n+\tif (!udev)\n+\t\treturn -ENOMEM;\n+\n+\t/*\n+\t * enable device: ask low-level code to enable I/O and\n+\t * memory\n+\t */\n+\tif (pci_enable_device(dev)) {\n+\t\tdev_err(&dev->dev, \"Cannot enable PCI device\\n\");\n+\t\tgoto fail_free;\n+\t}\n+\n+\t/*\n+\t * reserve device's PCI memory regions for use by this\n+\t * module\n+\t */\n+\tif (pci_request_regions(dev, \"nfp_uio\")) {\n+\t\tdev_err(&dev->dev, \"Cannot request regions\\n\");\n+\t\tgoto fail_disable;\n+\t}\n+\n+\t/* enable bus mastering on the device */\n+\tpci_set_master(dev);\n+\n+\t/* remap IO memory */\n+\tif (nfp_uio_setup_bars(dev, &udev->info))\n+\t\tgoto fail_release_iomem;\n+\n+\t/* set 40-bit DMA mask */\n+\tif (pci_set_dma_mask(dev,  DMA_BIT_MASK(40))) {\n+\t\tdev_err(&dev->dev, \"Cannot set DMA mask\\n\");\n+\t\tgoto fail_release_iomem;\n+\t} else if (pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(40))) {\n+\t\tdev_err(&dev->dev, \"Cannot set consistent DMA mask\\n\");\n+\t\tgoto fail_release_iomem;\n+\t}\n+\n+\t/* fill uio infos */\n+\tudev->info.name = \"Netronome NFP UIO\";\n+\tudev->info.version = \"0.1\";\n+\tudev->info.handler = nfp_uio_pci_irqhandler;\n+\tudev->info.irqcontrol = nfp_uio_pci_irqcontrol;\n+\tudev->info.priv = udev;\n+\tudev->pdev = dev;\n+\tspin_lock_init(&udev->lock);\n+\n+\tinit_interrupt(udev);\n+\n+\tpci_set_drvdata(dev, &udev->info);\n+\tnfp_uio_pci_irqcontrol(&udev->info, 0);\n+\n+\t/* register uio driver */\n+\tif (uio_register_device(&dev->dev, &udev->info))\n+\t\tgoto fail_release_iomem;\n+\n+\tdev_info(&dev->dev, \"uio device registered with irq %lx\\n\",\n+\t\t udev->info.irq);\n+\n+\t/* When binding drivers to devices, some old kernels do not\n+\t * link devices to iommu identity mapping if iommu=pt is used.\n+\t *\n+\t * This is not a problem if the driver does later some call to\n+\t * the DMA API because the mapping can be done then. But DPDK\n+\t * apps do not use that DMA API at all.\n+\t *\n+\t * Doing a harmless dma mapping for attaching the device to\n+\t * the iommu identity mapping\n+\t */\n+\n+\tmap_addr = dma_zalloc_coherent(&dev->dev, 1024,\n+\t\t\t\t       &map_dma_addr, GFP_KERNEL);\n+\n+\tpr_info(\"nfp_uio: mapping 1K dma=%#llx host=%p\\n\",\n+\t\t(unsigned long long)map_dma_addr, map_addr);\n+\n+\tdma_free_coherent(&dev->dev, 1024, map_addr, map_dma_addr);\n+\n+\tpr_info(\"nfp_uio: unmapping 1K dma=%#llx host=%p\\n\",\n+\t\t(unsigned long long)map_dma_addr, map_addr);\n+\n+\treturn 0;\n+\n+fail_release_iomem:\n+\tnfp_uio_pci_release_iomem(&udev->info);\n+\tpci_disable_msix(udev->pdev);\n+\tpci_release_regions(dev);\n+fail_disable:\n+\tpci_disable_device(dev);\n+fail_free:\n+\tkfree(udev);\n+\n+\treturn -ENODEV;\n+}\n+\n+static void\n+nfp_uio_pci_remove(struct pci_dev *dev)\n+{\n+\tstruct uio_info *info = pci_get_drvdata(dev);\n+\n+\tBUG_ON(!info);\n+\tBUG_ON(!info->priv);\n+\n+\tuio_unregister_device(info);\n+\tnfp_uio_pci_release_iomem(info);\n+\tpci_disable_msix(dev);\n+\tpci_release_regions(dev);\n+\tpci_disable_device(dev);\n+\tpci_set_drvdata(dev, NULL);\n+\tkfree(info);\n+}\n+\n+static struct pci_driver nfp_uio_pci_driver = {\n+\t.name = \"nfp_uio\",\n+\t.id_table = nfp_uio_pci_ids,\n+\t.probe = nfp_uio_pci_probe,\n+\t.remove = nfp_uio_pci_remove,\n+};\n+\n+static int __init\n+nfp_uio_pci_init_module(void)\n+{\n+\treturn pci_register_driver(&nfp_uio_pci_driver);\n+}\n+\n+static void __exit\n+nfp_uio_pci_exit_module(void)\n+{\n+\tpci_unregister_driver(&nfp_uio_pci_driver);\n+}\n+\n+module_init(nfp_uio_pci_init_module);\n+module_exit(nfp_uio_pci_exit_module);\n+\n+MODULE_DESCRIPTION(\"UIO driver for Netronome NFP PCI cards\");\n+MODULE_LICENSE(\"GPL\");\n+MODULE_AUTHOR(\"Netronome Systems <support@netronome.com>\");\ndiff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c\nindex f593f6e..a84bc63 100644\n--- a/lib/librte_ether/rte_ethdev.c\n+++ b/lib/librte_ether/rte_ethdev.c\n@@ -513,6 +513,7 @@ rte_eth_dev_is_detachable(uint8_t port_id)\n \tif (rte_eth_devices[port_id].dev_type == RTE_ETH_DEV_PCI) {\n \t\tswitch (rte_eth_devices[port_id].pci_dev->kdrv) {\n \t\tcase RTE_KDRV_IGB_UIO:\n+\t\tcase RTE_KDRV_NFP_UIO:\n \t\tcase RTE_KDRV_UIO_GENERIC:\n \t\tcase RTE_KDRV_NIC_UIO:\n \t\t\tbreak;\n",
    "prefixes": [
        "dpdk-dev",
        "2/3"
    ]
}