get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 28830,
    "url": "https://patches.dpdk.org/api/patches/28830/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/618e47fbcfbc9ead4c009f0456faab563f22a426.1505726803.git.gaetan.rivet@6wind.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": "<618e47fbcfbc9ead4c009f0456faab563f22a426.1505726803.git.gaetan.rivet@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/618e47fbcfbc9ead4c009f0456faab563f22a426.1505726803.git.gaetan.rivet@6wind.com",
    "date": "2017-09-18T09:31:39",
    "name": "[dpdk-dev,v2,05/14] pci: introduce PCI lib and bus",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "78cc53fdd1352dc2ce5680ba33a9ac4214bb8a10",
    "submitter": {
        "id": 269,
        "url": "https://patches.dpdk.org/api/people/269/?format=api",
        "name": "Gaëtan Rivet",
        "email": "gaetan.rivet@6wind.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/618e47fbcfbc9ead4c009f0456faab563f22a426.1505726803.git.gaetan.rivet@6wind.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/28830/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/28830/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 851EE1B1AA;\n\tMon, 18 Sep 2017 11:32:21 +0200 (CEST)",
            "from mail-wm0-f41.google.com (mail-wm0-f41.google.com\n\t[74.125.82.41]) by dpdk.org (Postfix) with ESMTP id 407F3199B6\n\tfor <dev@dpdk.org>; Mon, 18 Sep 2017 11:32:12 +0200 (CEST)",
            "by mail-wm0-f41.google.com with SMTP id i189so882932wmf.1\n\tfor <dev@dpdk.org>; Mon, 18 Sep 2017 02:32:12 -0700 (PDT)",
            "from bidouze.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com.\n\t[62.23.145.78]) by smtp.gmail.com with ESMTPSA id\n\tf89sm6416859wmh.18.2017.09.18.02.32.07\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tMon, 18 Sep 2017 02:32:07 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references\n\t:in-reply-to:references;\n\tbh=+TBi/tiY9vix3J4Av4eXQKnzwXUKPX53Ow13FnzIoIA=;\n\tb=vPiYUme4yGcuLYGxBjMokYPloh4Nklni7QMxEia8AN/yrd9gDnmNQLWqz/y23r3zOk\n\tKq/lTHtKbVAmqZrkAu6PMxu3SHb7789TsXfpTPyP3U/31JimDascXqCI9DtF3dMyvq6m\n\t3ZnfJz+iS9hgvNYzxg1SGWjtDUyscO1evHja4X9r+Tu3+1ZZbl8vU0pJf3CNdjvD2YdD\n\t7RWYofKy1FC8/wTR+vy/cethn0XfJOohRd1jLJUsOR7khop3og7eqAX3LX+a3j6GgNn7\n\tJPno0pwAF//SoqIZw7oIe72cUtS1tVI215OEvyau2RgH/jav4J3+00NmWwLRyga/bzg1\n\tOqRw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references:in-reply-to:references;\n\tbh=+TBi/tiY9vix3J4Av4eXQKnzwXUKPX53Ow13FnzIoIA=;\n\tb=RvNXNRYhoJk/OtNz9GIby65+PRNtrFEtJuMoHIZ2paloLOkIMdkDk3GFIfXYTh0X9S\n\t1D064VW+85NqsRhQGv+HMALWBr6ebcFdsFuZz52Qoi6vq+mLz1FugZIUQm1xbmyHmilD\n\tpgWy0LgfSn/Vw8Mzu9bQ2Vk8zyZGrhmeFcmTpFs7HPhILkI5LEw1Bqo84uoU6GY7RqbT\n\tdb3kcHZkZXatoG2RehTayPNkcR4g38/mZkV01tUKiJndX+GsNYeZfnuHz6Z9H531mjYc\n\tFPsOlRS+tE55rxll+fkx4nXrAb7eERvYoDQPLM9NNwHuV+/uFN816mrKVHach8yKb+6L\n\tPtGg==",
        "X-Gm-Message-State": "AHPjjUjjlB7KmV2tQSc+ifksvSoHTGA3y7Jz1zDhpZVSFatL/h/auSVo\n\tKaJfd11l7UO/bREw/8Xq1N/pzOAw",
        "X-Google-Smtp-Source": "AOwi7QDJ0XfKQihv8LeUa3JSWIN5XYgNycyefyYNY4fmyiLqRyvmVol2Wc8yPhGwq/YXGDPENKXt8g==",
        "X-Received": "by 10.28.214.206 with SMTP id n197mr8012244wmg.21.1505727128589; \n\tMon, 18 Sep 2017 02:32:08 -0700 (PDT)",
        "From": "Gaetan Rivet <gaetan.rivet@6wind.com>",
        "To": "dev@dpdk.org",
        "Cc": "Gaetan Rivet <gaetan.rivet@6wind.com>",
        "Date": "Mon, 18 Sep 2017 11:31:39 +0200",
        "Message-Id": "<618e47fbcfbc9ead4c009f0456faab563f22a426.1505726803.git.gaetan.rivet@6wind.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": [
            "<cover.1505726803.git.gaetan.rivet@6wind.com>",
            "<cover.1505726803.git.gaetan.rivet@6wind.com>"
        ],
        "References": [
            "<cover.1503651392.git.gaetan.rivet@6wind.com>\n\t<cover.1505726803.git.gaetan.rivet@6wind.com>",
            "<cover.1505726803.git.gaetan.rivet@6wind.com>"
        ],
        "Subject": "[dpdk-dev] [PATCH v2 05/14] pci: introduce PCI lib and bus",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <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": "The PCI lib defines the types and methods allowing to use PCI elements.\n\nThe PCI bus implements a bus driver for PCI devices by constructing\nrte_bus elements using the PCI lib.\n\nMove the relevant code out of the EAL to their expected place.\n\nSigned-off-by: Gaetan Rivet <gaetan.rivet@6wind.com>\n---\n config/common_base                              |  10 +\n drivers/bus/Makefile                            |   2 +\n drivers/bus/pci/Makefile                        |  59 ++\n drivers/bus/pci/bsd/Makefile                    |  32 ++\n drivers/bus/pci/bsd/rte_pci.c                   | 670 ++++++++++++++++++++++\n drivers/bus/pci/include/rte_bus_pci.h           | 387 +++++++++++++\n drivers/bus/pci/linux/Makefile                  |  37 ++\n drivers/bus/pci/linux/rte_pci.c                 | 722 ++++++++++++++++++++++++\n drivers/bus/pci/linux/rte_pci_init.h            |  97 ++++\n drivers/bus/pci/linux/rte_pci_uio.c             | 567 +++++++++++++++++++\n drivers/bus/pci/linux/rte_pci_vfio.c            | 674 ++++++++++++++++++++++\n drivers/bus/pci/linux/rte_vfio_mp_sync.c        | 424 ++++++++++++++\n drivers/bus/pci/private.h                       | 173 ++++++\n drivers/bus/pci/rte_bus_pci_version.map         |  21 +\n drivers/bus/pci/rte_pci_common.c                | 542 ++++++++++++++++++\n drivers/bus/pci/rte_pci_common_uio.c            | 234 ++++++++\n lib/Makefile                                    |   2 +\n lib/librte_eal/bsdapp/eal/Makefile              |   3 -\n lib/librte_eal/bsdapp/eal/eal_pci.c             | 670 ----------------------\n lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 -\n lib/librte_eal/common/Makefile                  |   2 +-\n lib/librte_eal/common/eal_common_pci.c          | 580 -------------------\n lib/librte_eal/common/eal_common_pci_uio.c      | 233 --------\n lib/librte_eal/common/include/rte_pci.h         | 598 --------------------\n lib/librte_eal/linuxapp/eal/Makefile            |  10 -\n lib/librte_eal/linuxapp/eal/eal_pci.c           | 722 ------------------------\n lib/librte_eal/linuxapp/eal/eal_pci_init.h      |  97 ----\n lib/librte_eal/linuxapp/eal/eal_pci_uio.c       | 567 -------------------\n lib/librte_eal/linuxapp/eal/eal_pci_vfio.c      | 674 ----------------------\n lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c  | 424 --------------\n lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 -\n lib/librte_ether/rte_ethdev.h                   |   2 -\n lib/librte_pci/Makefile                         |  48 ++\n lib/librte_pci/include/rte_pci.h                | 279 +++++++++\n lib/librte_pci/rte_pci.c                        |  92 +++\n lib/librte_pci/rte_pci_version.map              |   8 +\n mk/rte.app.mk                                   |   3 +\n 37 files changed, 5084 insertions(+), 4611 deletions(-)\n create mode 100644 drivers/bus/pci/Makefile\n create mode 100644 drivers/bus/pci/bsd/Makefile\n create mode 100644 drivers/bus/pci/bsd/rte_pci.c\n create mode 100644 drivers/bus/pci/include/rte_bus_pci.h\n create mode 100644 drivers/bus/pci/linux/Makefile\n create mode 100644 drivers/bus/pci/linux/rte_pci.c\n create mode 100644 drivers/bus/pci/linux/rte_pci_init.h\n create mode 100644 drivers/bus/pci/linux/rte_pci_uio.c\n create mode 100644 drivers/bus/pci/linux/rte_pci_vfio.c\n create mode 100644 drivers/bus/pci/linux/rte_vfio_mp_sync.c\n create mode 100644 drivers/bus/pci/private.h\n create mode 100644 drivers/bus/pci/rte_bus_pci_version.map\n create mode 100644 drivers/bus/pci/rte_pci_common.c\n create mode 100644 drivers/bus/pci/rte_pci_common_uio.c\n delete mode 100644 lib/librte_eal/bsdapp/eal/eal_pci.c\n delete mode 100644 lib/librte_eal/common/eal_common_pci.c\n delete mode 100644 lib/librte_eal/common/eal_common_pci_uio.c\n delete mode 100644 lib/librte_eal/common/include/rte_pci.h\n delete mode 100644 lib/librte_eal/linuxapp/eal/eal_pci.c\n delete mode 100644 lib/librte_eal/linuxapp/eal/eal_pci_init.h\n delete mode 100644 lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n delete mode 100644 lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n delete mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c\n create mode 100644 lib/librte_pci/Makefile\n create mode 100644 lib/librte_pci/include/rte_pci.h\n create mode 100644 lib/librte_pci/rte_pci.c\n create mode 100644 lib/librte_pci/rte_pci_version.map",
    "diff": "diff --git a/config/common_base b/config/common_base\nindex 5e97a08..08db392 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -122,6 +122,11 @@ CONFIG_RTE_EAL_PMD_PATH=\"\"\n CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y\n \n #\n+# Compile the PCI library\n+#\n+CONFIG_RTE_LIBRTE_PCI=y\n+\n+#\n # Compile the argument parser library\n #\n CONFIG_RTE_LIBRTE_KVARGS=y\n@@ -146,6 +151,11 @@ CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y\n CONFIG_RTE_ETHDEV_TX_PREPARE_NOOP=n\n \n #\n+# Compile PCI bus driver\n+#\n+CONFIG_RTE_LIBRTE_PCI_BUS=y\n+\n+#\n # Compile burst-oriented Amazon ENA PMD driver\n #\n CONFIG_RTE_LIBRTE_ENA_PMD=y\ndiff --git a/drivers/bus/Makefile b/drivers/bus/Makefile\nindex 0224214..4b5bafe 100644\n--- a/drivers/bus/Makefile\n+++ b/drivers/bus/Makefile\n@@ -34,5 +34,7 @@ core-libs := librte_eal librte_mbuf librte_mempool librte_ring librte_ether\n \n DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc\n DEPDIRS-fslmc = $(core-libs)\n+DIRS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci\n+DEPDIRS-pci = $(core-libs)\n \n include $(RTE_SDK)/mk/rte.subdir.mk\ndiff --git a/drivers/bus/pci/Makefile b/drivers/bus/pci/Makefile\nnew file mode 100644\nindex 0000000..7365925\n--- /dev/null\n+++ b/drivers/bus/pci/Makefile\n@@ -0,0 +1,59 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2017 6WIND S.A.\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 6WIND 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+LIB = librte_bus_pci.a\n+LIBABIVER := 1\n+EXPORT_MAP := rte_bus_pci_version.map\n+\n+CFLAGS := -I$(SRCDIR)/include -I$(SRCDIR) $(CFLAGS)\n+CFLAGS += -O3 $(WERROR_FLAGS)\n+\n+ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),)\n+SYSTEM := linux\n+endif\n+ifneq ($(CONFIG_RTE_EXEC_ENV_BSDAPP),)\n+SYSTEM := bsd\n+endif\n+\n+CFLAGS += -I$(RTE_SDK)/drivers/bus/pci/$(SYSTEM)\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common\n+CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal\n+\n+include $(RTE_SDK)/drivers/bus/pci/$(SYSTEM)/Makefile\n+SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) := $(addprefix $(SYSTEM)/,$(SRCS))\n+SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += rte_pci_common.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += rte_pci_common_uio.c\n+\n+SYMLINK-$(CONFIG_RTE_LIBRTE_PCI_BUS)-include += include/rte_bus_pci.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/drivers/bus/pci/bsd/Makefile b/drivers/bus/pci/bsd/Makefile\nnew file mode 100644\nindex 0000000..77cf539\n--- /dev/null\n+++ b/drivers/bus/pci/bsd/Makefile\n@@ -0,0 +1,32 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2017 6WIND S.A.\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 6WIND 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+SRCS += rte_pci.c\ndiff --git a/drivers/bus/pci/bsd/rte_pci.c b/drivers/bus/pci/bsd/rte_pci.c\nnew file mode 100644\nindex 0000000..5bd0f4b\n--- /dev/null\n+++ b/drivers/bus/pci/bsd/rte_pci.c\n@@ -0,0 +1,670 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#include <ctype.h>\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <stdarg.h>\n+#include <unistd.h>\n+#include <inttypes.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <fcntl.h>\n+#include <errno.h>\n+#include <dirent.h>\n+#include <limits.h>\n+#include <sys/queue.h>\n+#include <sys/mman.h>\n+#include <sys/ioctl.h>\n+#include <sys/pciio.h>\n+#include <dev/pci/pcireg.h>\n+\n+#if defined(RTE_ARCH_X86)\n+#include <machine/cpufunc.h>\n+#endif\n+\n+#include <rte_interrupts.h>\n+#include <rte_log.h>\n+#include <rte_pci.h>\n+#include <rte_common.h>\n+#include <rte_launch.h>\n+#include <rte_memory.h>\n+#include <rte_memzone.h>\n+#include <rte_eal.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_per_lcore.h>\n+#include <rte_lcore.h>\n+#include <rte_malloc.h>\n+#include <rte_string_fns.h>\n+#include <rte_debug.h>\n+#include <rte_devargs.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"private.h\"\n+\n+/**\n+ * @file\n+ * PCI probing under linux\n+ *\n+ * This code is used to simulate a PCI probe by parsing information in\n+ * sysfs. Moreover, when a registered driver matches a device, the\n+ * kernel driver currently using it is unloaded and replaced by\n+ * igb_uio module, which is a very minimal userland driver for Intel\n+ * network card, only providing access to PCI BAR to applications, and\n+ * enabling bus master.\n+ */\n+\n+extern struct rte_pci_bus rte_pci_bus;\n+\n+/* Map pci device */\n+int\n+rte_pci_map_device(struct rte_pci_device *dev)\n+{\n+\tint ret = -1;\n+\n+\t/* try mapping the NIC resources */\n+\tswitch (dev->kdrv) {\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\t/* map resources for devices that use uio */\n+\t\tret = pci_uio_map_resource(dev);\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n+\t\tret = 1;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* Unmap pci device */\n+void\n+rte_pci_unmap_device(struct rte_pci_device *dev)\n+{\n+\t/* try unmapping the NIC resources */\n+\tswitch (dev->kdrv) {\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\t/* unmap resources for devices that use uio */\n+\t\tpci_uio_unmap_resource(dev);\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n+\t\tbreak;\n+\t}\n+}\n+\n+void\n+pci_uio_free_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource *uio_res)\n+{\n+\trte_free(uio_res);\n+\n+\tif (dev->intr_handle.fd) {\n+\t\tclose(dev->intr_handle.fd);\n+\t\tdev->intr_handle.fd = -1;\n+\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+\t}\n+}\n+\n+int\n+pci_uio_alloc_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource **uio_res)\n+{\n+\tchar devname[PATH_MAX]; /* contains the /dev/uioX */\n+\tstruct rte_pci_addr *loc;\n+\n+\tloc = &dev->addr;\n+\n+\tsnprintf(devname, sizeof(devname), \"/dev/uio@pci:%u:%u:%u\",\n+\t\t\tdev->addr.bus, dev->addr.devid, dev->addr.function);\n+\n+\tif (access(devname, O_RDWR) < 0) {\n+\t\tRTE_LOG(WARNING, EAL, \"  \"PCI_PRI_FMT\" not managed by UIO driver, \"\n+\t\t\t\t\"skipping\\n\", loc->domain, loc->bus, loc->devid, loc->function);\n+\t\treturn 1;\n+\t}\n+\n+\t/* save fd if in primary process */\n+\tdev->intr_handle.fd = open(devname, O_RDWR);\n+\tif (dev->intr_handle.fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\tdevname, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n+\n+\t/* allocate the mapping details for secondary processes*/\n+\t*uio_res = rte_zmalloc(\"UIO_RES\", sizeof(**uio_res), 0);\n+\tif (*uio_res == NULL) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tsnprintf((*uio_res)->path, sizeof((*uio_res)->path), \"%s\", devname);\n+\tmemcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));\n+\n+\treturn 0;\n+\n+error:\n+\tpci_uio_free_resource(dev, *uio_res);\n+\treturn -1;\n+}\n+\n+int\n+pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n+\t\tstruct mapped_pci_resource *uio_res, int map_idx)\n+{\n+\tint fd;\n+\tchar *devname;\n+\tvoid *mapaddr;\n+\tuint64_t offset;\n+\tuint64_t pagesz;\n+\tstruct pci_map *maps;\n+\n+\tmaps = uio_res->maps;\n+\tdevname = uio_res->path;\n+\tpagesz = sysconf(_SC_PAGESIZE);\n+\n+\t/* allocate memory to keep path */\n+\tmaps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0);\n+\tif (maps[map_idx].path == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot allocate memory for path: %s\\n\",\n+\t\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\t/*\n+\t * open resource file, to mmap it\n+\t */\n+\tfd = open(devname, O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\t\tdevname, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\t/* if matching map is found, then use it */\n+\toffset = res_idx * pagesz;\n+\tmapaddr = pci_map_resource(NULL, fd, (off_t)offset,\n+\t\t\t(size_t)dev->mem_resource[res_idx].len, 0);\n+\tclose(fd);\n+\tif (mapaddr == MAP_FAILED)\n+\t\tgoto error;\n+\n+\tmaps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;\n+\tmaps[map_idx].size = dev->mem_resource[res_idx].len;\n+\tmaps[map_idx].addr = mapaddr;\n+\tmaps[map_idx].offset = offset;\n+\tstrcpy(maps[map_idx].path, devname);\n+\tdev->mem_resource[res_idx].addr = mapaddr;\n+\n+\treturn 0;\n+\n+error:\n+\trte_free(maps[map_idx].path);\n+\treturn -1;\n+}\n+\n+static int\n+pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n+{\n+\tstruct rte_pci_device *dev;\n+\tstruct pci_bar_io bar;\n+\tunsigned i, max;\n+\n+\tdev = malloc(sizeof(*dev));\n+\tif (dev == NULL) {\n+\t\treturn -1;\n+\t}\n+\n+\tmemset(dev, 0, sizeof(*dev));\n+\tdev->addr.domain = conf->pc_sel.pc_domain;\n+\tdev->addr.bus = conf->pc_sel.pc_bus;\n+\tdev->addr.devid = conf->pc_sel.pc_dev;\n+\tdev->addr.function = conf->pc_sel.pc_func;\n+\n+\t/* get vendor id */\n+\tdev->id.vendor_id = conf->pc_vendor;\n+\n+\t/* get device id */\n+\tdev->id.device_id = conf->pc_device;\n+\n+\t/* get subsystem_vendor id */\n+\tdev->id.subsystem_vendor_id = conf->pc_subvendor;\n+\n+\t/* get subsystem_device id */\n+\tdev->id.subsystem_device_id = conf->pc_subdevice;\n+\n+\t/* get class id */\n+\tdev->id.class_id = (conf->pc_class << 16) |\n+\t\t\t   (conf->pc_subclass << 8) |\n+\t\t\t   (conf->pc_progif);\n+\n+\t/* TODO: get max_vfs */\n+\tdev->max_vfs = 0;\n+\n+\t/* FreeBSD has no NUMA support (yet) */\n+\tdev->device.numa_node = 0;\n+\n+\tpci_name_set(dev);\n+\n+\t/* FreeBSD has only one pass through driver */\n+\tdev->kdrv = RTE_KDRV_NIC_UIO;\n+\n+\t/* parse resources */\n+\tswitch (conf->pc_hdr & PCIM_HDRTYPE) {\n+\tcase PCIM_HDRTYPE_NORMAL:\n+\t\tmax = PCIR_MAX_BAR_0;\n+\t\tbreak;\n+\tcase PCIM_HDRTYPE_BRIDGE:\n+\t\tmax = PCIR_MAX_BAR_1;\n+\t\tbreak;\n+\tcase PCIM_HDRTYPE_CARDBUS:\n+\t\tmax = PCIR_MAX_BAR_2;\n+\t\tbreak;\n+\tdefault:\n+\t\tgoto skipdev;\n+\t}\n+\n+\tfor (i = 0; i <= max; i++) {\n+\t\tbar.pbi_sel = conf->pc_sel;\n+\t\tbar.pbi_reg = PCIR_BAR(i);\n+\t\tif (ioctl(dev_pci_fd, PCIOCGETBAR, &bar) < 0)\n+\t\t\tcontinue;\n+\n+\t\tdev->mem_resource[i].len = bar.pbi_length;\n+\t\tif (PCI_BAR_IO(bar.pbi_base)) {\n+\t\t\tdev->mem_resource[i].addr = (void *)(bar.pbi_base & ~((uint64_t)0xf));\n+\t\t\tcontinue;\n+\t\t}\n+\t\tdev->mem_resource[i].phys_addr = bar.pbi_base & ~((uint64_t)0xf);\n+\t}\n+\n+\t/* device is valid, add in list (sorted) */\n+\tif (TAILQ_EMPTY(&rte_pci_bus.device_list)) {\n+\t\trte_pci_add_device(dev);\n+\t}\n+\telse {\n+\t\tstruct rte_pci_device *dev2 = NULL;\n+\t\tint ret;\n+\n+\t\tTAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {\n+\t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n+\t\t\tif (ret > 0)\n+\t\t\t\tcontinue;\n+\t\t\telse if (ret < 0) {\n+\t\t\t\trte_pci_insert_device(dev2, dev);\n+\t\t\t} else { /* already registered */\n+\t\t\t\tdev2->kdrv = dev->kdrv;\n+\t\t\t\tdev2->max_vfs = dev->max_vfs;\n+\t\t\t\tpci_name_set(dev2);\n+\t\t\t\tmemmove(dev2->mem_resource,\n+\t\t\t\t\tdev->mem_resource,\n+\t\t\t\t\tsizeof(dev->mem_resource));\n+\t\t\t\tfree(dev);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\t\trte_pci_add_device(dev);\n+\t}\n+\n+\treturn 0;\n+\n+skipdev:\n+\tfree(dev);\n+\treturn 0;\n+}\n+\n+/*\n+ * Scan the content of the PCI bus, and add the devices in the devices\n+ * list. Call pci_scan_one() for each pci entry found.\n+ */\n+int\n+rte_pci_scan(void)\n+{\n+\tint fd;\n+\tunsigned dev_count = 0;\n+\tstruct pci_conf matches[16];\n+\tstruct pci_conf_io conf_io = {\n+\t\t\t.pat_buf_len = 0,\n+\t\t\t.num_patterns = 0,\n+\t\t\t.patterns = NULL,\n+\t\t\t.match_buf_len = sizeof(matches),\n+\t\t\t.matches = &matches[0],\n+\t};\n+\n+\t/* for debug purposes, PCI can be disabled */\n+\tif (internal_config.no_pci)\n+\t\treturn 0;\n+\n+\tfd = open(\"/dev/pci\", O_RDONLY);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tdo {\n+\t\tunsigned i;\n+\t\tif (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"%s(): error with ioctl on /dev/pci: %s\\n\",\n+\t\t\t\t\t__func__, strerror(errno));\n+\t\t\tgoto error;\n+\t\t}\n+\n+\t\tfor (i = 0; i < conf_io.num_matches; i++)\n+\t\t\tif (pci_scan_one(fd, &matches[i]) < 0)\n+\t\t\t\tgoto error;\n+\n+\t\tdev_count += conf_io.num_matches;\n+\t} while(conf_io.status == PCI_GETCONF_MORE_DEVS);\n+\n+\tclose(fd);\n+\n+\tRTE_LOG(DEBUG, EAL, \"PCI scan found %u devices\\n\", dev_count);\n+\treturn 0;\n+\n+error:\n+\tif (fd >= 0)\n+\t\tclose(fd);\n+\treturn -1;\n+}\n+\n+int\n+pci_update_device(const struct rte_pci_addr *addr)\n+{\n+\tint fd;\n+\tstruct pci_conf matches[2];\n+\tstruct pci_match_conf match = {\n+\t\t.pc_sel = {\n+\t\t\t.pc_domain = addr->domain,\n+\t\t\t.pc_bus = addr->bus,\n+\t\t\t.pc_dev = addr->devid,\n+\t\t\t.pc_func = addr->function,\n+\t\t},\n+\t};\n+\tstruct pci_conf_io conf_io = {\n+\t\t.pat_buf_len = 0,\n+\t\t.num_patterns = 1,\n+\t\t.patterns = &match,\n+\t\t.match_buf_len = sizeof(matches),\n+\t\t.matches = &matches[0],\n+\t};\n+\n+\tfd = open(\"/dev/pci\", O_RDONLY);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tif (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): error with ioctl on /dev/pci: %s\\n\",\n+\t\t\t\t__func__, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\tif (conf_io.num_matches != 1)\n+\t\tgoto error;\n+\n+\tif (pci_scan_one(fd, &matches[0]) < 0)\n+\t\tgoto error;\n+\n+\tclose(fd);\n+\n+\treturn 0;\n+\n+error:\n+\tif (fd >= 0)\n+\t\tclose(fd);\n+\treturn -1;\n+}\n+\n+/* Read PCI config space. */\n+int rte_pci_read_config(const struct rte_pci_device *dev,\n+\t\tvoid *buf, size_t len, off_t offset)\n+{\n+\tint fd = -1;\n+\tint size;\n+\tstruct pci_io pi = {\n+\t\t.pi_sel = {\n+\t\t\t.pc_domain = dev->addr.domain,\n+\t\t\t.pc_bus = dev->addr.bus,\n+\t\t\t.pc_dev = dev->addr.devid,\n+\t\t\t.pc_func = dev->addr.function,\n+\t\t},\n+\t\t.pi_reg = offset,\n+\t};\n+\n+\tfd = open(\"/dev/pci\", O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\twhile (len > 0) {\n+\t\tsize = (len >= 4) ? 4 : ((len >= 2) ? 2 : 1);\n+\t\tpi.pi_width = size;\n+\n+\t\tif (ioctl(fd, PCIOCREAD, &pi) < 0)\n+\t\t\tgoto error;\n+\t\tmemcpy(buf, &pi.pi_data, size);\n+\n+\t\tbuf = (char *)buf + size;\n+\t\tpi.pi_reg += size;\n+\t\tlen -= size;\n+\t}\n+\tclose(fd);\n+\n+\treturn 0;\n+\n+ error:\n+\tif (fd >= 0)\n+\t\tclose(fd);\n+\treturn -1;\n+}\n+\n+/* Write PCI config space. */\n+int rte_pci_write_config(const struct rte_pci_device *dev,\n+\t\tconst void *buf, size_t len, off_t offset)\n+{\n+\tint fd = -1;\n+\n+\tstruct pci_io pi = {\n+\t\t.pi_sel = {\n+\t\t\t.pc_domain = dev->addr.domain,\n+\t\t\t.pc_bus = dev->addr.bus,\n+\t\t\t.pc_dev = dev->addr.devid,\n+\t\t\t.pc_func = dev->addr.function,\n+\t\t},\n+\t\t.pi_reg = offset,\n+\t\t.pi_data = *(const uint32_t *)buf,\n+\t\t.pi_width = len,\n+\t};\n+\n+\tif (len == 3 || len > sizeof(pi.pi_data)) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): invalid pci read length\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tmemcpy(&pi.pi_data, buf, len);\n+\n+\tfd = open(\"/dev/pci\", O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tif (ioctl(fd, PCIOCWRITE, &pi) < 0)\n+\t\tgoto error;\n+\n+\tclose(fd);\n+\treturn 0;\n+\n+ error:\n+\tif (fd >= 0)\n+\t\tclose(fd);\n+\treturn -1;\n+}\n+\n+int\n+rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\tstruct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (dev->kdrv) {\n+#if defined(RTE_ARCH_X86)\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\tif ((uintptr_t) dev->mem_resource[bar].addr <= UINT16_MAX) {\n+\t\t\tp->base = (uintptr_t)dev->mem_resource[bar].addr;\n+\t\t\tret = 0;\n+\t\t} else\n+\t\t\tret = -1;\n+\t\tbreak;\n+#endif\n+\tdefault:\n+\t\tret = -1;\n+\t\tbreak;\n+\t}\n+\n+\tif (!ret)\n+\t\tp->dev = dev;\n+\n+\treturn ret;\n+}\n+\n+static void\n+pci_uio_ioport_read(struct rte_pci_ioport *p,\n+\t\tvoid *data, size_t len, off_t offset)\n+{\n+#if defined(RTE_ARCH_X86)\n+\tuint8_t *d;\n+\tint size;\n+\tunsigned short reg = p->base + offset;\n+\n+\tfor (d = data; len > 0; d += size, reg += size, len -= size) {\n+\t\tif (len >= 4) {\n+\t\t\tsize = 4;\n+\t\t\t*(uint32_t *)d = inl(reg);\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+\t\t\t*(uint16_t *)d = inw(reg);\n+\t\t} else {\n+\t\t\tsize = 1;\n+\t\t\t*d = inb(reg);\n+\t\t}\n+\t}\n+#else\n+\tRTE_SET_USED(p);\n+\tRTE_SET_USED(data);\n+\tRTE_SET_USED(len);\n+\tRTE_SET_USED(offset);\n+#endif\n+}\n+\n+void\n+rte_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\tvoid *data, size_t len, off_t offset)\n+{\n+\tswitch (p->dev->kdrv) {\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+static void\n+pci_uio_ioport_write(struct rte_pci_ioport *p,\n+\t\tconst void *data, size_t len, off_t offset)\n+{\n+#if defined(RTE_ARCH_X86)\n+\tconst uint8_t *s;\n+\tint size;\n+\tunsigned short reg = p->base + offset;\n+\n+\tfor (s = data; len > 0; s += size, reg += size, len -= size) {\n+\t\tif (len >= 4) {\n+\t\t\tsize = 4;\n+\t\t\toutl(reg, *(const uint32_t *)s);\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+\t\t\toutw(reg, *(const uint16_t *)s);\n+\t\t} else {\n+\t\t\tsize = 1;\n+\t\t\toutb(reg, *s);\n+\t\t}\n+\t}\n+#else\n+\tRTE_SET_USED(p);\n+\tRTE_SET_USED(data);\n+\tRTE_SET_USED(len);\n+\tRTE_SET_USED(offset);\n+#endif\n+}\n+\n+void\n+rte_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\tconst void *data, size_t len, off_t offset)\n+{\n+\tswitch (p->dev->kdrv) {\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+int\n+rte_pci_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (p->dev->kdrv) {\n+#if defined(RTE_ARCH_X86)\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\tret = 0;\n+\t\tbreak;\n+#endif\n+\tdefault:\n+\t\tret = -1;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/bus/pci/include/rte_bus_pci.h b/drivers/bus/pci/include/rte_bus_pci.h\nnew file mode 100644\nindex 0000000..b05dbf9\n--- /dev/null\n+++ b/drivers/bus/pci/include/rte_bus_pci.h\n@@ -0,0 +1,387 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   Copyright 2013-2014 6WIND S.A.\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+\n+#ifndef _RTE_BUS_PCI_H_\n+#define _RTE_BUS_PCI_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE PCI Bus Interface\n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <limits.h>\n+#include <errno.h>\n+#include <sys/queue.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+\n+#include <rte_debug.h>\n+#include <rte_interrupts.h>\n+#include <rte_dev.h>\n+#include <rte_bus.h>\n+#include <rte_pci.h>\n+\n+/** Pathname of PCI devices directory. */\n+const char *pci_get_sysfs_path(void);\n+\n+/* Forward declarations */\n+struct rte_pci_device;\n+struct rte_pci_driver;\n+\n+/** List of PCI devices */\n+TAILQ_HEAD(rte_pci_device_list, rte_pci_device);\n+/** List of PCI drivers */\n+TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);\n+\n+/* PCI Bus iterators */\n+#define FOREACH_DEVICE_ON_PCIBUS(p)\t\\\n+\t\tTAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)\n+\n+#define FOREACH_DRIVER_ON_PCIBUS(p)\t\\\n+\t\tTAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)\n+\n+struct rte_devargs;\n+\n+/**\n+ * A structure describing a PCI device.\n+ */\n+struct rte_pci_device {\n+\tTAILQ_ENTRY(rte_pci_device) next;   /**< Next probed PCI device. */\n+\tstruct rte_device device;           /**< Inherit core device */\n+\tstruct rte_pci_addr addr;           /**< PCI location. */\n+\tstruct rte_pci_id id;               /**< PCI ID. */\n+\tstruct rte_mem_resource mem_resource[PCI_MAX_RESOURCE];\n+\t\t\t\t\t    /**< PCI Memory Resource */\n+\tstruct rte_intr_handle intr_handle; /**< Interrupt handle */\n+\tstruct rte_pci_driver *driver;      /**< Associated driver */\n+\tuint16_t max_vfs;                   /**< sriov enable if not zero */\n+\tenum rte_kernel_driver kdrv;        /**< Kernel driver passthrough */\n+\tchar name[PCI_PRI_STR_SIZE+1];      /**< PCI location (ASCII) */\n+};\n+\n+/**\n+ * @internal\n+ * Helper macro for drivers that need to convert to struct rte_pci_device.\n+ */\n+#define RTE_DEV_TO_PCI(ptr) container_of(ptr, struct rte_pci_device, device)\n+\n+#define RTE_ETH_DEV_TO_PCI(eth_dev)\tRTE_DEV_TO_PCI((eth_dev)->device)\n+\n+/** Any PCI device identifier (vendor, device, ...) */\n+#define PCI_ANY_ID (0xffff)\n+#define RTE_CLASS_ANY_ID (0xffffff)\n+\n+#ifdef __cplusplus\n+/** C++ macro used to help building up tables of device IDs */\n+#define RTE_PCI_DEVICE(vend, dev) \\\n+\tRTE_CLASS_ANY_ID,         \\\n+\t(vend),                   \\\n+\t(dev),                    \\\n+\tPCI_ANY_ID,               \\\n+\tPCI_ANY_ID\n+#else\n+/** Macro used to help building up tables of device IDs */\n+#define RTE_PCI_DEVICE(vend, dev)          \\\n+\t.class_id = RTE_CLASS_ANY_ID,      \\\n+\t.vendor_id = (vend),               \\\n+\t.device_id = (dev),                \\\n+\t.subsystem_vendor_id = PCI_ANY_ID, \\\n+\t.subsystem_device_id = PCI_ANY_ID\n+#endif\n+\n+/**\n+ * Initialisation function for the driver called during PCI probing.\n+ */\n+typedef int (pci_probe_t)(struct rte_pci_driver *, struct rte_pci_device *);\n+\n+/**\n+ * Uninitialisation function for the driver called during hotplugging.\n+ */\n+typedef int (pci_remove_t)(struct rte_pci_device *);\n+\n+/**\n+ * A structure describing a PCI driver.\n+ */\n+struct rte_pci_driver {\n+\tTAILQ_ENTRY(rte_pci_driver) next;  /**< Next in list. */\n+\tstruct rte_driver driver;          /**< Inherit core driver. */\n+\tstruct rte_pci_bus *bus;           /**< PCI bus reference. */\n+\tpci_probe_t *probe;                /**< Device Probe function. */\n+\tpci_remove_t *remove;              /**< Device Remove function. */\n+\tconst struct rte_pci_id *id_table; /**< ID table, NULL terminated. */\n+\tuint32_t drv_flags;                /**< Flags contolling handling of device. */\n+};\n+\n+/**\n+ * Structure describing the PCI bus\n+ */\n+struct rte_pci_bus {\n+\tstruct rte_bus bus;               /**< Inherit the generic class */\n+\tstruct rte_pci_device_list device_list;  /**< List of PCI devices */\n+\tstruct rte_pci_driver_list driver_list;  /**< List of PCI drivers */\n+};\n+\n+/** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */\n+#define RTE_PCI_DRV_NEED_MAPPING 0x0001\n+/** Device driver supports link state interrupt */\n+#define RTE_PCI_DRV_INTR_LSC\t0x0008\n+/** Device driver supports device removal interrupt */\n+#define RTE_PCI_DRV_INTR_RMV 0x0010\n+/** Device driver needs to keep mapped resources if unsupported dev detected */\n+#define RTE_PCI_DRV_KEEP_MAPPED_RES 0x0020\n+\n+/**\n+ * Scan the content of the PCI bus, and the devices in the devices\n+ * list\n+ *\n+ * @return\n+ *  0 on success, negative on error\n+ */\n+int rte_pci_scan(void);\n+\n+/**\n+ * Probe the PCI bus\n+ *\n+ * @return\n+ *   - 0 on success.\n+ *   - !0 on error.\n+ */\n+int\n+rte_pci_probe(void);\n+\n+/**\n+ * Map the PCI device resources in user space virtual memory address\n+ *\n+ * Note that driver should not call this function when flag\n+ * RTE_PCI_DRV_NEED_MAPPING is set, as EAL will do that for\n+ * you when it's on.\n+ *\n+ * @param dev\n+ *   A pointer to a rte_pci_device structure describing the device\n+ *   to use\n+ *\n+ * @return\n+ *   0 on success, negative on error and positive if no driver\n+ *   is found for the device.\n+ */\n+int rte_pci_map_device(struct rte_pci_device *dev);\n+\n+/**\n+ * Unmap this device\n+ *\n+ * @param dev\n+ *   A pointer to a rte_pci_device structure describing the device\n+ *   to use\n+ */\n+void rte_pci_unmap_device(struct rte_pci_device *dev);\n+\n+/**\n+ * Probe the single PCI device.\n+ *\n+ * Scan the content of the PCI bus, and find the pci device specified by pci\n+ * address, then call the probe() function for registered driver that has a\n+ * matching entry in its id_table for discovered device.\n+ *\n+ * @param addr\n+ *\tThe PCI Bus-Device-Function address to probe.\n+ * @return\n+ *   - 0 on success.\n+ *   - Negative on error.\n+ */\n+int rte_pci_probe_one(const struct rte_pci_addr *addr);\n+\n+/**\n+ * Close the single PCI device.\n+ *\n+ * Scan the content of the PCI bus, and find the pci device specified by pci\n+ * address, then call the remove() function for registered driver that has a\n+ * matching entry in its id_table for discovered device.\n+ *\n+ * @param addr\n+ *\tThe PCI Bus-Device-Function address to close.\n+ * @return\n+ *   - 0 on success.\n+ *   - Negative on error.\n+ */\n+int rte_pci_detach(const struct rte_pci_addr *addr);\n+\n+/**\n+ * Dump the content of the PCI bus.\n+ *\n+ * @param f\n+ *   A pointer to a file for output\n+ */\n+void rte_pci_dump(FILE *f);\n+\n+/**\n+ * Register a PCI driver.\n+ *\n+ * @param driver\n+ *   A pointer to a rte_pci_driver structure describing the driver\n+ *   to be registered.\n+ */\n+void rte_pci_register(struct rte_pci_driver *driver);\n+\n+/** Helper for PCI device registration from driver (eth, crypto) instance */\n+#define RTE_PMD_REGISTER_PCI(nm, pci_drv) \\\n+RTE_INIT(pciinitfn_ ##nm); \\\n+static void pciinitfn_ ##nm(void) \\\n+{\\\n+\t(pci_drv).driver.name = RTE_STR(nm);\\\n+\trte_pci_register(&pci_drv); \\\n+} \\\n+RTE_PMD_EXPORT_NAME(nm, __COUNTER__)\n+\n+/**\n+ * Unregister a PCI driver.\n+ *\n+ * @param driver\n+ *   A pointer to a rte_pci_driver structure describing the driver\n+ *   to be unregistered.\n+ */\n+void rte_pci_unregister(struct rte_pci_driver *driver);\n+\n+/**\n+ * Read PCI config space.\n+ *\n+ * @param device\n+ *   A pointer to a rte_pci_device structure describing the device\n+ *   to use\n+ * @param buf\n+ *   A data buffer where the bytes should be read into\n+ * @param len\n+ *   The length of the data buffer.\n+ * @param offset\n+ *   The offset into PCI config space\n+ */\n+int rte_pci_read_config(const struct rte_pci_device *device,\n+\t\tvoid *buf, size_t len, off_t offset);\n+\n+/**\n+ * Write PCI config space.\n+ *\n+ * @param device\n+ *   A pointer to a rte_pci_device structure describing the device\n+ *   to use\n+ * @param buf\n+ *   A data buffer containing the bytes should be written\n+ * @param len\n+ *   The length of the data buffer.\n+ * @param offset\n+ *   The offset into PCI config space\n+ */\n+int rte_pci_write_config(const struct rte_pci_device *device,\n+\t\tconst void *buf, size_t len, off_t offset);\n+\n+/**\n+ * A structure used to access io resources for a pci device.\n+ * rte_pci_ioport is arch, os, driver specific, and should not be used outside\n+ * of pci ioport api.\n+ */\n+struct rte_pci_ioport {\n+\tstruct rte_pci_device *dev;\n+\tuint64_t base;\n+\tuint64_t len; /* only filled for memory mapped ports */\n+};\n+\n+/**\n+ * Initialize a rte_pci_ioport object for a pci device io resource.\n+ *\n+ * This object is then used to gain access to those io resources (see below).\n+ *\n+ * @param dev\n+ *   A pointer to a rte_pci_device structure describing the device\n+ *   to use.\n+ * @param bar\n+ *   Index of the io pci resource we want to access.\n+ * @param p\n+ *   The rte_pci_ioport object to be initialized.\n+ * @return\n+ *  0 on success, negative on error.\n+ */\n+int rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\tstruct rte_pci_ioport *p);\n+\n+/**\n+ * Release any resources used in a rte_pci_ioport object.\n+ *\n+ * @param p\n+ *   The rte_pci_ioport object to be uninitialized.\n+ * @return\n+ *  0 on success, negative on error.\n+ */\n+int rte_pci_ioport_unmap(struct rte_pci_ioport *p);\n+\n+/**\n+ * Read from a io pci resource.\n+ *\n+ * @param p\n+ *   The rte_pci_ioport object from which we want to read.\n+ * @param data\n+ *   A data buffer where the bytes should be read into\n+ * @param len\n+ *   The length of the data buffer.\n+ * @param offset\n+ *   The offset into the pci io resource.\n+ */\n+void rte_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\tvoid *data, size_t len, off_t offset);\n+\n+/**\n+ * Write to a io pci resource.\n+ *\n+ * @param p\n+ *   The rte_pci_ioport object to which we want to write.\n+ * @param data\n+ *   A data buffer where the bytes should be read into\n+ * @param len\n+ *   The length of the data buffer.\n+ * @param offset\n+ *   The offset into the pci io resource.\n+ */\n+void rte_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\tconst void *data, size_t len, off_t offset);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_BUS_PCI_H_ */\ndiff --git a/drivers/bus/pci/linux/Makefile b/drivers/bus/pci/linux/Makefile\nnew file mode 100644\nindex 0000000..d2ea84c\n--- /dev/null\n+++ b/drivers/bus/pci/linux/Makefile\n@@ -0,0 +1,37 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2017 6WIND S.A.\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 6WIND 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+SRCS += rte_pci.c\n+SRCS += rte_pci_uio.c\n+SRCS += rte_pci_vfio.c\n+SRCS += rte_vfio_mp_sync.c\n+\n+CFLAGS += -D_GNU_SOURCE\ndiff --git a/drivers/bus/pci/linux/rte_pci.c b/drivers/bus/pci/linux/rte_pci.c\nnew file mode 100644\nindex 0000000..c2ac82b\n--- /dev/null\n+++ b/drivers/bus/pci/linux/rte_pci.c\n@@ -0,0 +1,722 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#include <string.h>\n+#include <dirent.h>\n+\n+#include <rte_log.h>\n+#include <rte_bus.h>\n+#include <rte_pci.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_malloc.h>\n+#include <rte_devargs.h>\n+#include <rte_memcpy.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"private.h\"\n+#include \"rte_pci_init.h\"\n+\n+/**\n+ * @file\n+ * PCI probing under linux\n+ *\n+ * This code is used to simulate a PCI probe by parsing information in sysfs.\n+ * When a registered device matches a driver, it is then initialized with\n+ * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).\n+ */\n+\n+extern struct rte_pci_bus rte_pci_bus;\n+\n+static int\n+pci_get_kernel_driver_by_path(const char *filename, char *dri_name)\n+{\n+\tint count;\n+\tchar path[PATH_MAX];\n+\tchar *name;\n+\n+\tif (!filename || !dri_name)\n+\t\treturn -1;\n+\n+\tcount = readlink(filename, path, PATH_MAX);\n+\tif (count >= PATH_MAX)\n+\t\treturn -1;\n+\n+\t/* For device does not have a driver */\n+\tif (count < 0)\n+\t\treturn 1;\n+\n+\tpath[count] = '\\0';\n+\n+\tname = strrchr(path, '/');\n+\tif (name) {\n+\t\tstrncpy(dri_name, name + 1, strlen(name + 1) + 1);\n+\t\treturn 0;\n+\t}\n+\n+\treturn -1;\n+}\n+\n+/* Map pci device */\n+int\n+rte_pci_map_device(struct rte_pci_device *dev)\n+{\n+\tint ret = -1;\n+\n+\t/* try mapping the NIC resources using VFIO if it exists */\n+\tswitch (dev->kdrv) {\n+\tcase RTE_KDRV_VFIO:\n+#ifdef VFIO_PRESENT\n+\t\tif (pci_vfio_is_enabled())\n+\t\t\tret = pci_vfio_map_resource(dev);\n+#endif\n+\t\tbreak;\n+\tcase RTE_KDRV_IGB_UIO:\n+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tif (rte_eal_using_phys_addrs()) {\n+\t\t\t/* map resources for devices that use uio */\n+\t\t\tret = pci_uio_map_resource(dev);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n+\t\tret = 1;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/* Unmap pci device */\n+void\n+rte_pci_unmap_device(struct rte_pci_device *dev)\n+{\n+\t/* try unmapping the NIC resources using VFIO if it exists */\n+\tswitch (dev->kdrv) {\n+\tcase RTE_KDRV_VFIO:\n+#ifdef VFIO_PRESENT\n+\t\tif (pci_vfio_is_enabled())\n+\t\t\tpci_vfio_unmap_resource(dev);\n+#endif\n+\t\tbreak;\n+\tcase RTE_KDRV_IGB_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+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n+\t\tbreak;\n+\t}\n+}\n+\n+void *\n+pci_find_max_end_va(void)\n+{\n+\tconst struct rte_memseg *seg = rte_eal_get_physmem_layout();\n+\tconst struct rte_memseg *last = seg;\n+\tunsigned i = 0;\n+\n+\tfor (i = 0; i < RTE_MAX_MEMSEG; i++, seg++) {\n+\t\tif (seg->addr == NULL)\n+\t\t\tbreak;\n+\n+\t\tif (seg->addr > last->addr)\n+\t\t\tlast = seg;\n+\n+\t}\n+\treturn RTE_PTR_ADD(last->addr, last->len);\n+}\n+\n+/* parse one line of the \"resource\" sysfs file (note that the 'line'\n+ * string is modified)\n+ */\n+int\n+pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,\n+\tuint64_t *end_addr, uint64_t *flags)\n+{\n+\tunion pci_resource_info {\n+\t\tstruct {\n+\t\t\tchar *phys_addr;\n+\t\t\tchar *end_addr;\n+\t\t\tchar *flags;\n+\t\t};\n+\t\tchar *ptrs[PCI_RESOURCE_FMT_NVAL];\n+\t} res_info;\n+\n+\tif (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"%s(): bad resource format\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\terrno = 0;\n+\t*phys_addr = strtoull(res_info.phys_addr, NULL, 16);\n+\t*end_addr = strtoull(res_info.end_addr, NULL, 16);\n+\t*flags = strtoull(res_info.flags, NULL, 16);\n+\tif (errno != 0) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"%s(): bad resource format\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* parse the \"resource\" sysfs file */\n+static int\n+pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)\n+{\n+\tFILE *f;\n+\tchar buf[BUFSIZ];\n+\tint i;\n+\tuint64_t phys_addr, end_addr, flags;\n+\n+\tf = fopen(filename, \"r\");\n+\tif (f == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open sysfs resource\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tfor (i = 0; i<PCI_MAX_RESOURCE; i++) {\n+\n+\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\"%s(): cannot read resource\\n\", __func__);\n+\t\t\tgoto error;\n+\t\t}\n+\t\tif (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,\n+\t\t\t\t&end_addr, &flags) < 0)\n+\t\t\tgoto error;\n+\n+\t\tif (flags & IORESOURCE_MEM) {\n+\t\t\tdev->mem_resource[i].phys_addr = phys_addr;\n+\t\t\tdev->mem_resource[i].len = end_addr - phys_addr + 1;\n+\t\t\t/* not mapped for now */\n+\t\t\tdev->mem_resource[i].addr = NULL;\n+\t\t}\n+\t}\n+\tfclose(f);\n+\treturn 0;\n+\n+error:\n+\tfclose(f);\n+\treturn -1;\n+}\n+\n+/* Scan one pci sysfs entry, and fill the devices list from it. */\n+static int\n+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)\n+{\n+\tchar filename[PATH_MAX];\n+\tunsigned long tmp;\n+\tstruct rte_pci_device *dev;\n+\tchar driver[PATH_MAX];\n+\tint ret;\n+\n+\tdev = malloc(sizeof(*dev));\n+\tif (dev == NULL)\n+\t\treturn -1;\n+\n+\tmemset(dev, 0, sizeof(*dev));\n+\tdev->addr = *addr;\n+\n+\t/* get vendor id */\n+\tsnprintf(filename, sizeof(filename), \"%s/vendor\", dirname);\n+\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\tdev->id.vendor_id = (uint16_t)tmp;\n+\n+\t/* get device id */\n+\tsnprintf(filename, sizeof(filename), \"%s/device\", dirname);\n+\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\tdev->id.device_id = (uint16_t)tmp;\n+\n+\t/* get subsystem_vendor id */\n+\tsnprintf(filename, sizeof(filename), \"%s/subsystem_vendor\",\n+\t\t dirname);\n+\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\tdev->id.subsystem_vendor_id = (uint16_t)tmp;\n+\n+\t/* get subsystem_device id */\n+\tsnprintf(filename, sizeof(filename), \"%s/subsystem_device\",\n+\t\t dirname);\n+\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\tdev->id.subsystem_device_id = (uint16_t)tmp;\n+\n+\t/* get class_id */\n+\tsnprintf(filename, sizeof(filename), \"%s/class\",\n+\t\t dirname);\n+\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\t/* the least 24 bits are valid: class, subclass, program interface */\n+\tdev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;\n+\n+\t/* get max_vfs */\n+\tdev->max_vfs = 0;\n+\tsnprintf(filename, sizeof(filename), \"%s/max_vfs\", dirname);\n+\tif (!access(filename, F_OK) &&\n+\t    eal_parse_sysfs_value(filename, &tmp) == 0)\n+\t\tdev->max_vfs = (uint16_t)tmp;\n+\telse {\n+\t\t/* for non igb_uio driver, need kernel version >= 3.8 */\n+\t\tsnprintf(filename, sizeof(filename),\n+\t\t\t \"%s/sriov_numvfs\", dirname);\n+\t\tif (!access(filename, F_OK) &&\n+\t\t    eal_parse_sysfs_value(filename, &tmp) == 0)\n+\t\t\tdev->max_vfs = (uint16_t)tmp;\n+\t}\n+\n+\t/* get numa node, default to 0 if not present */\n+\tsnprintf(filename, sizeof(filename), \"%s/numa_node\",\n+\t\t dirname);\n+\n+\tif (access(filename, F_OK) != -1) {\n+\t\tif (eal_parse_sysfs_value(filename, &tmp) == 0)\n+\t\t\tdev->device.numa_node = tmp;\n+\t\telse\n+\t\t\tdev->device.numa_node = -1;\n+\t} else {\n+\t\tdev->device.numa_node = 0;\n+\t}\n+\n+\tpci_name_set(dev);\n+\n+\t/* parse resources */\n+\tsnprintf(filename, sizeof(filename), \"%s/resource\", dirname);\n+\tif (pci_parse_sysfs_resource(filename, dev) < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse resource\\n\", __func__);\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\n+\t/* parse driver */\n+\tsnprintf(filename, sizeof(filename), \"%s/driver\", dirname);\n+\tret = pci_get_kernel_driver_by_path(filename, driver);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Fail to get kernel driver\\n\");\n+\t\tfree(dev);\n+\t\treturn -1;\n+\t}\n+\n+\tif (!ret) {\n+\t\tif (!strcmp(driver, \"vfio-pci\"))\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, \"uio_pci_generic\"))\n+\t\t\tdev->kdrv = RTE_KDRV_UIO_GENERIC;\n+\t\telse\n+\t\t\tdev->kdrv = RTE_KDRV_UNKNOWN;\n+\t} else\n+\t\tdev->kdrv = RTE_KDRV_NONE;\n+\n+\t/* device is valid, add in list (sorted) */\n+\tif (TAILQ_EMPTY(&rte_pci_bus.device_list)) {\n+\t\trte_pci_add_device(dev);\n+\t} else {\n+\t\tstruct rte_pci_device *dev2;\n+\t\tint ret;\n+\n+\t\tTAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {\n+\t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n+\t\t\tif (ret > 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (ret < 0) {\n+\t\t\t\trte_pci_insert_device(dev2, dev);\n+\t\t\t} else { /* already registered */\n+\t\t\t\tdev2->kdrv = dev->kdrv;\n+\t\t\t\tdev2->max_vfs = dev->max_vfs;\n+\t\t\t\tpci_name_set(dev2);\n+\t\t\t\tmemmove(dev2->mem_resource, dev->mem_resource,\n+\t\t\t\t\tsizeof(dev->mem_resource));\n+\t\t\t\tfree(dev);\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\trte_pci_add_device(dev);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int\n+pci_update_device(const struct rte_pci_addr *addr)\n+{\n+\tchar filename[PATH_MAX];\n+\n+\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT,\n+\t\t pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,\n+\t\t addr->function);\n+\n+\treturn pci_scan_one(filename, addr);\n+}\n+\n+/*\n+ * split up a pci address into its constituent parts.\n+ */\n+static int\n+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)\n+{\n+\t/* first split on ':' */\n+\tunion splitaddr {\n+\t\tstruct {\n+\t\t\tchar *domain;\n+\t\t\tchar *bus;\n+\t\t\tchar *devid;\n+\t\t\tchar *function;\n+\t\t};\n+\t\tchar *str[PCI_FMT_NVAL]; /* last element-separator is \".\" not \":\" */\n+\t} splitaddr;\n+\n+\tchar *buf_copy = strndup(buf, bufsize);\n+\tif (buf_copy == NULL)\n+\t\treturn -1;\n+\n+\tif (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')\n+\t\t\t!= PCI_FMT_NVAL - 1)\n+\t\tgoto error;\n+\t/* final split is on '.' between devid and function */\n+\tsplitaddr.function = strchr(splitaddr.devid,'.');\n+\tif (splitaddr.function == NULL)\n+\t\tgoto error;\n+\t*splitaddr.function++ = '\\0';\n+\n+\t/* now convert to int values */\n+\terrno = 0;\n+\taddr->domain = strtoul(splitaddr.domain, NULL, 16);\n+\taddr->bus = strtoul(splitaddr.bus, NULL, 16);\n+\taddr->devid = strtoul(splitaddr.devid, NULL, 16);\n+\taddr->function = strtoul(splitaddr.function, NULL, 10);\n+\tif (errno != 0)\n+\t\tgoto error;\n+\n+\tfree(buf_copy); /* free the copy made with strdup */\n+\treturn 0;\n+error:\n+\tfree(buf_copy);\n+\treturn -1;\n+}\n+\n+/*\n+ * Scan the content of the PCI bus, and the devices in the devices\n+ * list\n+ */\n+int\n+rte_pci_scan(void)\n+{\n+\tstruct dirent *e;\n+\tDIR *dir;\n+\tchar dirname[PATH_MAX];\n+\tstruct rte_pci_addr addr;\n+\n+\t/* for debug purposes, PCI can be disabled */\n+\tif (internal_config.no_pci)\n+\t\treturn 0;\n+\n+\tdir = opendir(pci_get_sysfs_path());\n+\tif (dir == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): opendir failed: %s\\n\",\n+\t\t\t__func__, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\twhile ((e = readdir(dir)) != NULL) {\n+\t\tif (e->d_name[0] == '.')\n+\t\t\tcontinue;\n+\n+\t\tif (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)\n+\t\t\tcontinue;\n+\n+\t\tsnprintf(dirname, sizeof(dirname), \"%s/%s\",\n+\t\t\t\tpci_get_sysfs_path(), e->d_name);\n+\n+\t\tif (pci_scan_one(dirname, &addr) < 0)\n+\t\t\tgoto error;\n+\t}\n+\tclosedir(dir);\n+\treturn 0;\n+\n+error:\n+\tclosedir(dir);\n+\treturn -1;\n+}\n+\n+/* Read PCI config space. */\n+int rte_pci_read_config(const struct rte_pci_device *device,\n+\t\tvoid *buf, size_t len, off_t offset)\n+{\n+\tconst struct rte_intr_handle *intr_handle = &device->intr_handle;\n+\n+\tswitch (intr_handle->type) {\n+\tcase RTE_INTR_HANDLE_UIO:\n+\tcase RTE_INTR_HANDLE_UIO_INTX:\n+\t\treturn pci_uio_read_config(intr_handle, buf, len, offset);\n+\n+#ifdef VFIO_PRESENT\n+\tcase RTE_INTR_HANDLE_VFIO_MSIX:\n+\tcase RTE_INTR_HANDLE_VFIO_MSI:\n+\tcase RTE_INTR_HANDLE_VFIO_LEGACY:\n+\t\treturn pci_vfio_read_config(intr_handle, buf, len, offset);\n+#endif\n+\tdefault:\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Unknown handle type of fd %d\\n\",\n+\t\t\t\t\tintr_handle->fd);\n+\t\treturn -1;\n+\t}\n+}\n+\n+/* Write PCI config space. */\n+int rte_pci_write_config(const struct rte_pci_device *device,\n+\t\tconst void *buf, size_t len, off_t offset)\n+{\n+\tconst struct rte_intr_handle *intr_handle = &device->intr_handle;\n+\n+\tswitch (intr_handle->type) {\n+\tcase RTE_INTR_HANDLE_UIO:\n+\tcase RTE_INTR_HANDLE_UIO_INTX:\n+\t\treturn pci_uio_write_config(intr_handle, buf, len, offset);\n+\n+#ifdef VFIO_PRESENT\n+\tcase RTE_INTR_HANDLE_VFIO_MSIX:\n+\tcase RTE_INTR_HANDLE_VFIO_MSI:\n+\tcase RTE_INTR_HANDLE_VFIO_LEGACY:\n+\t\treturn pci_vfio_write_config(intr_handle, buf, len, offset);\n+#endif\n+\tdefault:\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Unknown handle type of fd %d\\n\",\n+\t\t\t\t\tintr_handle->fd);\n+\t\treturn -1;\n+\t}\n+}\n+\n+#if defined(RTE_ARCH_X86)\n+static int\n+pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,\n+\t\tstruct rte_pci_ioport *p)\n+{\n+\tuint16_t start, end;\n+\tFILE *fp;\n+\tchar *line = NULL;\n+\tchar pci_id[16];\n+\tint found = 0;\n+\tsize_t linesz;\n+\n+\tsnprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,\n+\t\t dev->addr.domain, dev->addr.bus,\n+\t\t dev->addr.devid, dev->addr.function);\n+\n+\tfp = fopen(\"/proc/ioports\", \"r\");\n+\tif (fp == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): can't open ioports\\n\", __func__);\n+\t\treturn -1;\n+\t}\n+\n+\twhile (getdelim(&line, &linesz, '\\n', fp) > 0) {\n+\t\tchar *ptr = line;\n+\t\tchar *left;\n+\t\tint n;\n+\n+\t\tn = strcspn(ptr, \":\");\n+\t\tptr[n] = 0;\n+\t\tleft = &ptr[n + 1];\n+\n+\t\twhile (*left && isspace(*left))\n+\t\t\tleft++;\n+\n+\t\tif (!strncmp(left, pci_id, strlen(pci_id))) {\n+\t\t\tfound = 1;\n+\n+\t\t\twhile (*ptr && isspace(*ptr))\n+\t\t\t\tptr++;\n+\n+\t\t\tsscanf(ptr, \"%04hx-%04hx\", &start, &end);\n+\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tfree(line);\n+\tfclose(fp);\n+\n+\tif (!found)\n+\t\treturn -1;\n+\n+\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+\tp->base = start;\n+\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%x\\n\", start);\n+\n+\treturn 0;\n+}\n+#endif\n+\n+int\n+rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\tstruct rte_pci_ioport *p)\n+{\n+\tint ret = -1;\n+\n+\tswitch (dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tif (pci_vfio_is_enabled())\n+\t\t\tret = pci_vfio_ioport_map(dev, bar, p);\n+\t\tbreak;\n+#endif\n+\tcase RTE_KDRV_IGB_UIO:\n+\t\tret = pci_uio_ioport_map(dev, bar, p);\n+\t\tbreak;\n+\tcase RTE_KDRV_UIO_GENERIC:\n+#if defined(RTE_ARCH_X86)\n+\t\tret = pci_ioport_map(dev, bar, p);\n+#else\n+\t\tret = pci_uio_ioport_map(dev, bar, p);\n+#endif\n+\t\tbreak;\n+\tcase RTE_KDRV_NONE:\n+#if defined(RTE_ARCH_X86)\n+\t\tret = pci_ioport_map(dev, bar, p);\n+#endif\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tif (!ret)\n+\t\tp->dev = dev;\n+\n+\treturn ret;\n+}\n+\n+void\n+rte_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\tvoid *data, size_t len, off_t offset)\n+{\n+\tswitch (p->dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tpci_vfio_ioport_read(p, data, len, offset);\n+\t\tbreak;\n+#endif\n+\tcase RTE_KDRV_IGB_UIO:\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+\t\tbreak;\n+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+\t\tbreak;\n+\tcase RTE_KDRV_NONE:\n+#if defined(RTE_ARCH_X86)\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+#endif\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+void\n+rte_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\tconst void *data, size_t len, off_t offset)\n+{\n+\tswitch (p->dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tpci_vfio_ioport_write(p, data, len, offset);\n+\t\tbreak;\n+#endif\n+\tcase RTE_KDRV_IGB_UIO:\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+\t\tbreak;\n+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+\t\tbreak;\n+\tcase RTE_KDRV_NONE:\n+#if defined(RTE_ARCH_X86)\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+#endif\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+int\n+rte_pci_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tint ret = -1;\n+\n+\tswitch (p->dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tif (pci_vfio_is_enabled())\n+\t\t\tret = pci_vfio_ioport_unmap(p);\n+\t\tbreak;\n+#endif\n+\tcase RTE_KDRV_IGB_UIO:\n+\t\tret = pci_uio_ioport_unmap(p);\n+\t\tbreak;\n+\tcase RTE_KDRV_UIO_GENERIC:\n+#if defined(RTE_ARCH_X86)\n+\t\tret = 0;\n+#else\n+\t\tret = pci_uio_ioport_unmap(p);\n+#endif\n+\t\tbreak;\n+\tcase RTE_KDRV_NONE:\n+#if defined(RTE_ARCH_X86)\n+\t\tret = 0;\n+#endif\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\ndiff --git a/drivers/bus/pci/linux/rte_pci_init.h b/drivers/bus/pci/linux/rte_pci_init.h\nnew file mode 100644\nindex 0000000..ae2980d\n--- /dev/null\n+++ b/drivers/bus/pci/linux/rte_pci_init.h\n@@ -0,0 +1,97 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#ifndef EAL_PCI_INIT_H_\n+#define EAL_PCI_INIT_H_\n+\n+#include \"eal_vfio.h\"\n+\n+/** IO resource type: */\n+#define IORESOURCE_IO         0x00000100\n+#define IORESOURCE_MEM        0x00000200\n+\n+/*\n+ * Helper function to map PCI resources right after hugepages in virtual memory\n+ */\n+extern void *pci_map_addr;\n+void *pci_find_max_end_va(void);\n+\n+/* parse one line of the \"resource\" sysfs file (note that the 'line'\n+ * string is modified)\n+ */\n+int pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,\n+\tuint64_t *end_addr, uint64_t *flags);\n+\n+int pci_uio_alloc_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource **uio_res);\n+void pci_uio_free_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource *uio_res);\n+int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n+\t\tstruct mapped_pci_resource *uio_res, int map_idx);\n+\n+int pci_uio_read_config(const struct rte_intr_handle *intr_handle,\n+\t\t\tvoid *buf, size_t len, off_t offs);\n+int pci_uio_write_config(const struct rte_intr_handle *intr_handle,\n+\t\t\t const void *buf, size_t len, off_t offs);\n+\n+int pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t       struct rte_pci_ioport *p);\n+void pci_uio_ioport_read(struct rte_pci_ioport *p,\n+\t\t\t void *data, size_t len, off_t offset);\n+void pci_uio_ioport_write(struct rte_pci_ioport *p,\n+\t\t\t  const void *data, size_t len, off_t offset);\n+int pci_uio_ioport_unmap(struct rte_pci_ioport *p);\n+\n+#ifdef VFIO_PRESENT\n+\n+/* access config space */\n+int pci_vfio_read_config(const struct rte_intr_handle *intr_handle,\n+\t\t\t void *buf, size_t len, off_t offs);\n+int pci_vfio_write_config(const struct rte_intr_handle *intr_handle,\n+\t\t\t  const void *buf, size_t len, off_t offs);\n+\n+int pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t        struct rte_pci_ioport *p);\n+void pci_vfio_ioport_read(struct rte_pci_ioport *p,\n+\t\t\t  void *data, size_t len, off_t offset);\n+void pci_vfio_ioport_write(struct rte_pci_ioport *p,\n+\t\t\t   const void *data, size_t len, off_t offset);\n+int pci_vfio_ioport_unmap(struct rte_pci_ioport *p);\n+\n+/* map/unmap VFIO resource prototype */\n+int pci_vfio_map_resource(struct rte_pci_device *dev);\n+int pci_vfio_unmap_resource(struct rte_pci_device *dev);\n+\n+#endif\n+\n+#endif /* EAL_PCI_INIT_H_ */\ndiff --git a/drivers/bus/pci/linux/rte_pci_uio.c b/drivers/bus/pci/linux/rte_pci_uio.c\nnew file mode 100644\nindex 0000000..eed6d0f\n--- /dev/null\n+++ b/drivers/bus/pci/linux/rte_pci_uio.c\n@@ -0,0 +1,567 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#include <string.h>\n+#include <unistd.h>\n+#include <fcntl.h>\n+#include <dirent.h>\n+#include <inttypes.h>\n+#include <sys/stat.h>\n+#include <sys/mman.h>\n+#include <sys/sysmacros.h>\n+#include <linux/pci_regs.h>\n+\n+#if defined(RTE_ARCH_X86)\n+#include <sys/io.h>\n+#endif\n+\n+#include <rte_log.h>\n+#include <rte_pci.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_common.h>\n+#include <rte_malloc.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"rte_pci_init.h\"\n+\n+void *pci_map_addr = NULL;\n+\n+#define OFF_MAX              ((uint64_t)(off_t)-1)\n+\n+int\n+pci_uio_read_config(const struct rte_intr_handle *intr_handle,\n+\t\t    void *buf, size_t len, off_t offset)\n+{\n+\treturn pread(intr_handle->uio_cfg_fd, buf, len, offset);\n+}\n+\n+int\n+pci_uio_write_config(const struct rte_intr_handle *intr_handle,\n+\t\t     const void *buf, size_t len, off_t offset)\n+{\n+\treturn pwrite(intr_handle->uio_cfg_fd, buf, len, offset);\n+}\n+\n+static int\n+pci_uio_set_bus_master(int dev_fd)\n+{\n+\tuint16_t reg;\n+\tint ret;\n+\n+\tret = pread(dev_fd, &reg, sizeof(reg), PCI_COMMAND);\n+\tif (ret != sizeof(reg)) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Cannot read command from PCI config space!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* return if bus mastering is already on */\n+\tif (reg & PCI_COMMAND_MASTER)\n+\t\treturn 0;\n+\n+\treg |= PCI_COMMAND_MASTER;\n+\n+\tret = pwrite(dev_fd, &reg, sizeof(reg), PCI_COMMAND);\n+\tif (ret != sizeof(reg)) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Cannot write command to PCI config space!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)\n+{\n+\tFILE *f;\n+\tchar filename[PATH_MAX];\n+\tint ret;\n+\tunsigned major, minor;\n+\tdev_t dev;\n+\n+\t/* get the name of the sysfs file that contains the major and minor\n+\t * of the uio device and read its content */\n+\tsnprintf(filename, sizeof(filename), \"%s/dev\", sysfs_uio_path);\n+\n+\tf = fopen(filename, \"r\");\n+\tif (f == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot open sysfs to get major:minor\\n\",\n+\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\n+\tret = fscanf(f, \"%u:%u\", &major, &minor);\n+\tif (ret != 2) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse sysfs to get major:minor\\n\",\n+\t\t\t__func__);\n+\t\tfclose(f);\n+\t\treturn -1;\n+\t}\n+\tfclose(f);\n+\n+\t/* create the char device \"mknod /dev/uioX c major minor\" */\n+\tsnprintf(filename, sizeof(filename), \"/dev/uio%u\", uio_num);\n+\tdev = makedev(major, minor);\n+\tret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);\n+\tif (ret != 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): mknod() failed %s\\n\",\n+\t\t\t__func__, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/*\n+ * Return the uioX char device used for a pci device. On success, return\n+ * the UIO number and fill dstbuf string with the path of the device in\n+ * sysfs. On error, return a negative value. In this case dstbuf is\n+ * invalid.\n+ */\n+static int\n+pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,\n+\t\t\t   unsigned int buflen, int create)\n+{\n+\tstruct rte_pci_addr *loc = &dev->addr;\n+\tunsigned int uio_num;\n+\tstruct dirent *e;\n+\tDIR *dir;\n+\tchar dirname[PATH_MAX];\n+\n+\t/* depending on kernel version, uio can be located in uio/uioX\n+\t * or uio:uioX */\n+\n+\tsnprintf(dirname, sizeof(dirname),\n+\t\t\t\"%s/\" PCI_PRI_FMT \"/uio\", pci_get_sysfs_path(),\n+\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n+\n+\tdir = opendir(dirname);\n+\tif (dir == NULL) {\n+\t\t/* retry with the parent directory */\n+\t\tsnprintf(dirname, sizeof(dirname),\n+\t\t\t\t\"%s/\" PCI_PRI_FMT, pci_get_sysfs_path(),\n+\t\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n+\t\tdir = opendir(dirname);\n+\n+\t\tif (dir == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot opendir %s\\n\", dirname);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* take the first file starting with \"uio\" */\n+\twhile ((e = readdir(dir)) != NULL) {\n+\t\t/* format could be uio%d ...*/\n+\t\tint shortprefix_len = sizeof(\"uio\") - 1;\n+\t\t/* ... or uio:uio%d */\n+\t\tint longprefix_len = sizeof(\"uio:uio\") - 1;\n+\t\tchar *endptr;\n+\n+\t\tif (strncmp(e->d_name, \"uio\", 3) != 0)\n+\t\t\tcontinue;\n+\n+\t\t/* first try uio%d */\n+\t\terrno = 0;\n+\t\tuio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);\n+\t\tif (errno == 0 && endptr != (e->d_name + shortprefix_len)) {\n+\t\t\tsnprintf(dstbuf, buflen, \"%s/uio%u\", dirname, uio_num);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* then try uio:uio%d */\n+\t\terrno = 0;\n+\t\tuio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);\n+\t\tif (errno == 0 && endptr != (e->d_name + longprefix_len)) {\n+\t\t\tsnprintf(dstbuf, buflen, \"%s/uio:uio%u\", dirname, uio_num);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tclosedir(dir);\n+\n+\t/* No uio resource found */\n+\tif (e == NULL)\n+\t\treturn -1;\n+\n+\t/* create uio device if we've been asked to */\n+\tif (internal_config.create_uio_dev && create &&\n+\t\t\tpci_mknod_uio_dev(dstbuf, uio_num) < 0)\n+\t\tRTE_LOG(WARNING, EAL, \"Cannot create /dev/uio%u\\n\", uio_num);\n+\n+\treturn uio_num;\n+}\n+\n+void\n+pci_uio_free_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource *uio_res)\n+{\n+\trte_free(uio_res);\n+\n+\tif (dev->intr_handle.uio_cfg_fd >= 0) {\n+\t\tclose(dev->intr_handle.uio_cfg_fd);\n+\t\tdev->intr_handle.uio_cfg_fd = -1;\n+\t}\n+\tif (dev->intr_handle.fd >= 0) {\n+\t\tclose(dev->intr_handle.fd);\n+\t\tdev->intr_handle.fd = -1;\n+\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+\t}\n+}\n+\n+int\n+pci_uio_alloc_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource **uio_res)\n+{\n+\tchar dirname[PATH_MAX];\n+\tchar cfgname[PATH_MAX];\n+\tchar devname[PATH_MAX]; /* contains the /dev/uioX */\n+\tint uio_num;\n+\tstruct rte_pci_addr *loc;\n+\n+\tloc = &dev->addr;\n+\n+\t/* find uio resource */\n+\tuio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1);\n+\tif (uio_num < 0) {\n+\t\tRTE_LOG(WARNING, EAL, \"  \"PCI_PRI_FMT\" not managed by UIO driver, \"\n+\t\t\t\t\"skipping\\n\", loc->domain, loc->bus, loc->devid, loc->function);\n+\t\treturn 1;\n+\t}\n+\tsnprintf(devname, sizeof(devname), \"/dev/uio%u\", uio_num);\n+\n+\t/* save fd if in primary process */\n+\tdev->intr_handle.fd = open(devname, O_RDWR);\n+\tif (dev->intr_handle.fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\tdevname, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\tsnprintf(cfgname, sizeof(cfgname),\n+\t\t\t\"/sys/class/uio/uio%u/device/config\", uio_num);\n+\tdev->intr_handle.uio_cfg_fd = open(cfgname, O_RDWR);\n+\tif (dev->intr_handle.uio_cfg_fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\tcfgname, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\tif (dev->kdrv == RTE_KDRV_IGB_UIO)\n+\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n+\telse {\n+\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX;\n+\n+\t\t/* set bus master that is not done by uio_pci_generic */\n+\t\tif (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot set up bus mastering!\\n\");\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\n+\t/* allocate the mapping details for secondary processes*/\n+\t*uio_res = rte_zmalloc(\"UIO_RES\", sizeof(**uio_res), 0);\n+\tif (*uio_res == NULL) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n+\t\tgoto error;\n+\t}\n+\n+\tsnprintf((*uio_res)->path, sizeof((*uio_res)->path), \"%s\", devname);\n+\tmemcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));\n+\n+\treturn 0;\n+\n+error:\n+\tpci_uio_free_resource(dev, *uio_res);\n+\treturn -1;\n+}\n+\n+int\n+pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n+\t\tstruct mapped_pci_resource *uio_res, int map_idx)\n+{\n+\tint fd;\n+\tchar devname[PATH_MAX];\n+\tvoid *mapaddr;\n+\tstruct rte_pci_addr *loc;\n+\tstruct pci_map *maps;\n+\n+\tloc = &dev->addr;\n+\tmaps = uio_res->maps;\n+\n+\t/* update devname for mmap  */\n+\tsnprintf(devname, sizeof(devname),\n+\t\t\t\"%s/\" PCI_PRI_FMT \"/resource%d\",\n+\t\t\tpci_get_sysfs_path(),\n+\t\t\tloc->domain, loc->bus, loc->devid,\n+\t\t\tloc->function, res_idx);\n+\n+\t/* allocate memory to keep path */\n+\tmaps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0);\n+\tif (maps[map_idx].path == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot allocate memory for path: %s\\n\",\n+\t\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\t/*\n+\t * open resource file, to mmap it\n+\t */\n+\tfd = open(devname, O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\t\tdevname, strerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\t/* try mapping somewhere close to the end of hugepages */\n+\tif (pci_map_addr == NULL)\n+\t\tpci_map_addr = pci_find_max_end_va();\n+\n+\tmapaddr = pci_map_resource(pci_map_addr, fd, 0,\n+\t\t\t(size_t)dev->mem_resource[res_idx].len, 0);\n+\tclose(fd);\n+\tif (mapaddr == MAP_FAILED)\n+\t\tgoto error;\n+\n+\tpci_map_addr = RTE_PTR_ADD(mapaddr,\n+\t\t\t(size_t)dev->mem_resource[res_idx].len);\n+\n+\tmaps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;\n+\tmaps[map_idx].size = dev->mem_resource[res_idx].len;\n+\tmaps[map_idx].addr = mapaddr;\n+\tmaps[map_idx].offset = 0;\n+\tstrcpy(maps[map_idx].path, devname);\n+\tdev->mem_resource[res_idx].addr = mapaddr;\n+\n+\treturn 0;\n+\n+error:\n+\trte_free(maps[map_idx].path);\n+\treturn -1;\n+}\n+\n+#if defined(RTE_ARCH_X86)\n+int\n+pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t   struct rte_pci_ioport *p)\n+{\n+\tchar dirname[PATH_MAX];\n+\tchar filename[PATH_MAX];\n+\tint uio_num;\n+\tunsigned long start;\n+\n+\tuio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0);\n+\tif (uio_num < 0)\n+\t\treturn -1;\n+\n+\t/* get portio start */\n+\tsnprintf(filename, sizeof(filename),\n+\t\t \"%s/portio/port%d/start\", dirname, bar);\n+\tif (eal_parse_sysfs_value(filename, &start) < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse portio start\\n\",\n+\t\t\t__func__);\n+\t\treturn -1;\n+\t}\n+\t/* ensure we don't get anything funny here, read/write will cast to\n+\t * uin16_t */\n+\tif (start > UINT16_MAX)\n+\t\treturn -1;\n+\n+\t/* FIXME only for primary process ? */\n+\tif (dev->intr_handle.type == RTE_INTR_HANDLE_UNKNOWN) {\n+\n+\t\tsnprintf(filename, sizeof(filename), \"/dev/uio%u\", uio_num);\n+\t\tdev->intr_handle.fd = open(filename, O_RDWR);\n+\t\tif (dev->intr_handle.fd < 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\t\tfilename, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n+\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n+\t}\n+\n+\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%lx\\n\", start);\n+\n+\tp->base = start;\n+\tp->len = 0;\n+\treturn 0;\n+}\n+#else\n+int\n+pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t   struct rte_pci_ioport *p)\n+{\n+\tFILE *f;\n+\tchar buf[BUFSIZ];\n+\tchar filename[PATH_MAX];\n+\tuint64_t phys_addr, end_addr, flags;\n+\tint fd, i;\n+\tvoid *addr;\n+\n+\t/* open and read addresses of the corresponding resource in sysfs */\n+\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT \"/resource\",\n+\t\tpci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,\n+\t\tdev->addr.devid, dev->addr.function);\n+\tf = fopen(filename, \"r\");\n+\tif (f == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open sysfs resource: %s\\n\",\n+\t\t\tstrerror(errno));\n+\t\treturn -1;\n+\t}\n+\tfor (i = 0; i < bar + 1; i++) {\n+\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot read sysfs resource\\n\");\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\tif (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,\n+\t\t\t&end_addr, &flags) < 0)\n+\t\tgoto error;\n+\tif ((flags & IORESOURCE_IO) == 0) {\n+\t\tRTE_LOG(ERR, EAL, \"BAR %d is not an IO resource\\n\", bar);\n+\t\tgoto error;\n+\t}\n+\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT \"/resource%d\",\n+\t\tpci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,\n+\t\tdev->addr.devid, dev->addr.function, bar);\n+\n+\t/* mmap the pci resource */\n+\tfd = open(filename, O_RDWR);\n+\tif (fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\", filename,\n+\t\t\tstrerror(errno));\n+\t\tgoto error;\n+\t}\n+\taddr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,\n+\t\tMAP_SHARED, fd, 0);\n+\tclose(fd);\n+\tif (addr == MAP_FAILED) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot mmap IO port resource: %s\\n\",\n+\t\t\tstrerror(errno));\n+\t\tgoto error;\n+\t}\n+\n+\t/* strangely, the base address is mmap addr + phys_addr */\n+\tp->base = (uintptr_t)addr + phys_addr;\n+\tp->len = end_addr + 1;\n+\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%\"PRIx64\"\\n\", p->base);\n+\tfclose(f);\n+\n+\treturn 0;\n+\n+error:\n+\tfclose(f);\n+\treturn -1;\n+}\n+#endif\n+\n+void\n+pci_uio_ioport_read(struct rte_pci_ioport *p,\n+\t\t    void *data, size_t len, off_t offset)\n+{\n+\tuint8_t *d;\n+\tint size;\n+\tuintptr_t reg = p->base + offset;\n+\n+\tfor (d = data; len > 0; d += size, reg += size, len -= size) {\n+\t\tif (len >= 4) {\n+\t\t\tsize = 4;\n+#if defined(RTE_ARCH_X86)\n+\t\t\t*(uint32_t *)d = inl(reg);\n+#else\n+\t\t\t*(uint32_t *)d = *(volatile uint32_t *)reg;\n+#endif\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+#if defined(RTE_ARCH_X86)\n+\t\t\t*(uint16_t *)d = inw(reg);\n+#else\n+\t\t\t*(uint16_t *)d = *(volatile uint16_t *)reg;\n+#endif\n+\t\t} else {\n+\t\t\tsize = 1;\n+#if defined(RTE_ARCH_X86)\n+\t\t\t*d = inb(reg);\n+#else\n+\t\t\t*d = *(volatile uint8_t *)reg;\n+#endif\n+\t\t}\n+\t}\n+}\n+\n+void\n+pci_uio_ioport_write(struct rte_pci_ioport *p,\n+\t\t     const void *data, size_t len, off_t offset)\n+{\n+\tconst uint8_t *s;\n+\tint size;\n+\tuintptr_t reg = p->base + offset;\n+\n+\tfor (s = data; len > 0; s += size, reg += size, len -= size) {\n+\t\tif (len >= 4) {\n+\t\t\tsize = 4;\n+#if defined(RTE_ARCH_X86)\n+\t\t\toutl_p(*(const uint32_t *)s, reg);\n+#else\n+\t\t\t*(volatile uint32_t *)reg = *(const uint32_t *)s;\n+#endif\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+#if defined(RTE_ARCH_X86)\n+\t\t\toutw_p(*(const uint16_t *)s, reg);\n+#else\n+\t\t\t*(volatile uint16_t *)reg = *(const uint16_t *)s;\n+#endif\n+\t\t} else {\n+\t\t\tsize = 1;\n+#if defined(RTE_ARCH_X86)\n+\t\t\toutb_p(*s, reg);\n+#else\n+\t\t\t*(volatile uint8_t *)reg = *s;\n+#endif\n+\t\t}\n+\t}\n+}\n+\n+int\n+pci_uio_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+#if defined(RTE_ARCH_X86)\n+\tRTE_SET_USED(p);\n+\t/* FIXME close intr fd ? */\n+\treturn 0;\n+#else\n+\treturn munmap((void *)(uintptr_t)p->base, p->len);\n+#endif\n+}\ndiff --git a/drivers/bus/pci/linux/rte_pci_vfio.c b/drivers/bus/pci/linux/rte_pci_vfio.c\nnew file mode 100644\nindex 0000000..81b67c9\n--- /dev/null\n+++ b/drivers/bus/pci/linux/rte_pci_vfio.c\n@@ -0,0 +1,674 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#include <string.h>\n+#include <fcntl.h>\n+#include <linux/pci_regs.h>\n+#include <sys/eventfd.h>\n+#include <sys/socket.h>\n+#include <sys/ioctl.h>\n+#include <sys/mman.h>\n+#include <stdbool.h>\n+\n+#include <rte_log.h>\n+#include <rte_pci.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_malloc.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"rte_pci_init.h\"\n+#include \"eal_vfio.h\"\n+#include \"private.h\"\n+\n+/**\n+ * @file\n+ * PCI probing under linux (VFIO version)\n+ *\n+ * This code tries to determine if the PCI device is bound to VFIO driver,\n+ * and initialize it (map BARs, set up interrupts) if that's the case.\n+ *\n+ * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to \"y\".\n+ */\n+\n+#ifdef VFIO_PRESENT\n+\n+#define PAGE_SIZE   (sysconf(_SC_PAGESIZE))\n+#define PAGE_MASK   (~(PAGE_SIZE - 1))\n+\n+static struct rte_tailq_elem rte_vfio_tailq = {\n+\t.name = \"VFIO_RESOURCE_LIST\",\n+};\n+EAL_REGISTER_TAILQ(rte_vfio_tailq)\n+\n+int\n+pci_vfio_read_config(const struct rte_intr_handle *intr_handle,\n+\t\t    void *buf, size_t len, off_t offs)\n+{\n+\treturn pread64(intr_handle->vfio_dev_fd, buf, len,\n+\t       VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);\n+}\n+\n+int\n+pci_vfio_write_config(const struct rte_intr_handle *intr_handle,\n+\t\t    const void *buf, size_t len, off_t offs)\n+{\n+\treturn pwrite64(intr_handle->vfio_dev_fd, buf, len,\n+\t       VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);\n+}\n+\n+/* get PCI BAR number where MSI-X interrupts are */\n+static int\n+pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset,\n+\t\t      uint32_t *msix_table_size)\n+{\n+\tint ret;\n+\tuint32_t reg;\n+\tuint16_t flags;\n+\tuint8_t cap_id, cap_offset;\n+\n+\t/* read PCI capability pointer from config space */\n+\tret = pread64(fd, &reg, sizeof(reg),\n+\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\tPCI_CAPABILITY_LIST);\n+\tif (ret != sizeof(reg)) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot read capability pointer from PCI \"\n+\t\t\t\t\"config space!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* we need first byte */\n+\tcap_offset = reg & 0xFF;\n+\n+\twhile (cap_offset) {\n+\n+\t\t/* read PCI capability ID */\n+\t\tret = pread64(fd, &reg, sizeof(reg),\n+\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\t\tcap_offset);\n+\t\tif (ret != sizeof(reg)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Cannot read capability ID from PCI \"\n+\t\t\t\t\t\"config space!\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* we need first byte */\n+\t\tcap_id = reg & 0xFF;\n+\n+\t\t/* if we haven't reached MSI-X, check next capability */\n+\t\tif (cap_id != PCI_CAP_ID_MSIX) {\n+\t\t\tret = pread64(fd, &reg, sizeof(reg),\n+\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\t\t\tcap_offset);\n+\t\t\tif (ret != sizeof(reg)) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read capability pointer from PCI \"\n+\t\t\t\t\t\t\"config space!\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\t/* we need second byte */\n+\t\t\tcap_offset = (reg & 0xFF00) >> 8;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\t\t/* else, read table offset */\n+\t\telse {\n+\t\t\t/* table offset resides in the next 4 bytes */\n+\t\t\tret = pread64(fd, &reg, sizeof(reg),\n+\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\t\t\tcap_offset + 4);\n+\t\t\tif (ret != sizeof(reg)) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read table offset from PCI config \"\n+\t\t\t\t\t\t\"space!\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\tret = pread64(fd, &flags, sizeof(flags),\n+\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\t\t\tcap_offset + 2);\n+\t\t\tif (ret != sizeof(flags)) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read table flags from PCI config \"\n+\t\t\t\t\t\t\"space!\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\t*msix_bar = reg & RTE_PCI_MSIX_TABLE_BIR;\n+\t\t\t*msix_table_offset = reg & RTE_PCI_MSIX_TABLE_OFFSET;\n+\t\t\t*msix_table_size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE));\n+\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/* set PCI bus mastering */\n+static int\n+pci_vfio_set_bus_master(int dev_fd, bool op)\n+{\n+\tuint16_t reg;\n+\tint ret;\n+\n+\tret = pread64(dev_fd, &reg, sizeof(reg),\n+\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\tPCI_COMMAND);\n+\tif (ret != sizeof(reg)) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot read command from PCI config space!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tif (op)\n+\t\t/* set the master bit */\n+\t\treg |= PCI_COMMAND_MASTER;\n+\telse\n+\t\treg &= ~(PCI_COMMAND_MASTER);\n+\n+\tret = pwrite64(dev_fd, &reg, sizeof(reg),\n+\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\tPCI_COMMAND);\n+\n+\tif (ret != sizeof(reg)) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot write command to PCI config space!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/* set up interrupt support (but not enable interrupts) */\n+static int\n+pci_vfio_setup_interrupts(struct rte_pci_device *dev, int vfio_dev_fd)\n+{\n+\tint i, ret, intr_idx;\n+\n+\t/* default to invalid index */\n+\tintr_idx = VFIO_PCI_NUM_IRQS;\n+\n+\t/* get interrupt type from internal config (MSI-X by default, can be\n+\t * overridden from the command line\n+\t */\n+\tswitch (internal_config.vfio_intr_mode) {\n+\tcase RTE_INTR_MODE_MSIX:\n+\t\tintr_idx = VFIO_PCI_MSIX_IRQ_INDEX;\n+\t\tbreak;\n+\tcase RTE_INTR_MODE_MSI:\n+\t\tintr_idx = VFIO_PCI_MSI_IRQ_INDEX;\n+\t\tbreak;\n+\tcase RTE_INTR_MODE_LEGACY:\n+\t\tintr_idx = VFIO_PCI_INTX_IRQ_INDEX;\n+\t\tbreak;\n+\t/* don't do anything if we want to automatically determine interrupt type */\n+\tcase RTE_INTR_MODE_NONE:\n+\t\tbreak;\n+\tdefault:\n+\t\tRTE_LOG(ERR, EAL, \"  unknown default interrupt type!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\t/* start from MSI-X interrupt type */\n+\tfor (i = VFIO_PCI_MSIX_IRQ_INDEX; i >= 0; i--) {\n+\t\tstruct vfio_irq_info irq = { .argsz = sizeof(irq) };\n+\t\tint fd = -1;\n+\n+\t\t/* skip interrupt modes we don't want */\n+\t\tif (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE &&\n+\t\t\t\ti != intr_idx)\n+\t\t\tcontinue;\n+\n+\t\tirq.index = i;\n+\n+\t\tret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  cannot get IRQ info, \"\n+\t\t\t\t\t\"error %i (%s)\\n\", errno, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* if this vector cannot be used with eventfd, fail if we explicitly\n+\t\t * specified interrupt type, otherwise continue */\n+\t\tif ((irq.flags & VFIO_IRQ_INFO_EVENTFD) == 0) {\n+\t\t\tif (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE) {\n+\t\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\t\t\"  interrupt vector does not support eventfd!\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t} else\n+\t\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* set up an eventfd for interrupts */\n+\t\tfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);\n+\t\tif (fd < 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  cannot set up eventfd, \"\n+\t\t\t\t\t\"error %i (%s)\\n\", errno, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tdev->intr_handle.fd = fd;\n+\t\tdev->intr_handle.vfio_dev_fd = vfio_dev_fd;\n+\n+\t\tswitch (i) {\n+\t\tcase VFIO_PCI_MSIX_IRQ_INDEX:\n+\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_MSIX;\n+\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSIX;\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_MSI_IRQ_INDEX:\n+\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_MSI;\n+\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSI;\n+\t\t\tbreak;\n+\t\tcase VFIO_PCI_INTX_IRQ_INDEX:\n+\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_LEGACY;\n+\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_LEGACY;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tRTE_LOG(ERR, EAL, \"  unknown interrupt type!\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/* if we're here, we haven't found a suitable interrupt vector */\n+\treturn -1;\n+}\n+\n+/*\n+ * map the PCI resources of a PCI device in virtual memory (VFIO version).\n+ * primary and secondary processes follow almost exactly the same path\n+ */\n+int\n+pci_vfio_map_resource(struct rte_pci_device *dev)\n+{\n+\tstruct vfio_device_info device_info = { .argsz = sizeof(device_info) };\n+\tchar pci_addr[PATH_MAX] = {0};\n+\tint vfio_dev_fd;\n+\tstruct rte_pci_addr *loc = &dev->addr;\n+\tint i, ret, msix_bar;\n+\tstruct mapped_pci_resource *vfio_res = NULL;\n+\tstruct mapped_pci_res_list *vfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);\n+\n+\tstruct pci_map *maps;\n+\tuint32_t msix_table_offset = 0;\n+\tuint32_t msix_table_size = 0;\n+\tuint32_t ioport_bar;\n+\n+\tdev->intr_handle.fd = -1;\n+\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+\n+\t/* store PCI address string */\n+\tsnprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,\n+\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n+\n+\tif ((ret = vfio_setup_device(pci_get_sysfs_path(), pci_addr,\n+\t\t\t\t\t&vfio_dev_fd, &device_info)))\n+\t\treturn ret;\n+\n+\t/* get MSI-X BAR, if any (we have to know where it is because we can't\n+\t * easily mmap it when using VFIO) */\n+\tmsix_bar = -1;\n+\tret = pci_vfio_get_msix_bar(vfio_dev_fd, &msix_bar,\n+\t\t\t\t    &msix_table_offset, &msix_table_size);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"  %s cannot get MSI-X BAR number!\\n\", pci_addr);\n+\t\tclose(vfio_dev_fd);\n+\t\treturn -1;\n+\t}\n+\n+\t/* if we're in a primary process, allocate vfio_res and get region info */\n+\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n+\t\tvfio_res = rte_zmalloc(\"VFIO_RES\", sizeof(*vfio_res), 0);\n+\t\tif (vfio_res == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tmemcpy(&vfio_res->pci_addr, &dev->addr, sizeof(vfio_res->pci_addr));\n+\n+\t\t/* get number of registers (up to BAR5) */\n+\t\tvfio_res->nb_maps = RTE_MIN((int) device_info.num_regions,\n+\t\t\t\tVFIO_PCI_BAR5_REGION_INDEX + 1);\n+\t} else {\n+\t\t/* if we're in a secondary process, just find our tailq entry */\n+\t\tTAILQ_FOREACH(vfio_res, vfio_res_list, next) {\n+\t\t\tif (rte_eal_compare_pci_addr(&vfio_res->pci_addr,\n+\t\t\t\t\t\t     &dev->addr))\n+\t\t\t\tcontinue;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* if we haven't found our tailq entry, something's wrong */\n+\t\tif (vfio_res == NULL) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot find TAILQ entry for PCI device!\\n\",\n+\t\t\t\t\tpci_addr);\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\t/* map BARs */\n+\tmaps = vfio_res->maps;\n+\n+\tfor (i = 0; i < (int) vfio_res->nb_maps; i++) {\n+\t\tstruct vfio_region_info reg = { .argsz = sizeof(reg) };\n+\t\tvoid *bar_addr;\n+\t\tstruct memreg {\n+\t\t\tunsigned long offset, size;\n+\t\t} memreg[2] = {};\n+\n+\t\treg.index = i;\n+\n+\t\tret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg);\n+\n+\t\tif (ret) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot get device region info \"\n+\t\t\t\t\t\"error %i (%s)\\n\", pci_addr, errno, strerror(errno));\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n+\t\t\t\trte_free(vfio_res);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* chk for io port region */\n+\t\tret = pread64(vfio_dev_fd, &ioport_bar, sizeof(ioport_bar),\n+\t\t\t      VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX)\n+\t\t\t      + PCI_BASE_ADDRESS_0 + i*4);\n+\n+\t\tif (ret != sizeof(ioport_bar)) {\n+\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\"Cannot read command (%x) from config space!\\n\",\n+\t\t\t\tPCI_BASE_ADDRESS_0 + i*4);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tif (ioport_bar & PCI_BASE_ADDRESS_SPACE_IO) {\n+\t\t\tRTE_LOG(INFO, EAL,\n+\t\t\t\t\"Ignore mapping IO port bar(%d) addr: %x\\n\",\n+\t\t\t\t i, ioport_bar);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* skip non-mmapable BARs */\n+\t\tif ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0)\n+\t\t\tcontinue;\n+\n+\t\tif (i == msix_bar) {\n+\t\t\t/*\n+\t\t\t * VFIO will not let us map the MSI-X table,\n+\t\t\t * but we can map around it.\n+\t\t\t */\n+\t\t\tuint32_t table_start = msix_table_offset;\n+\t\t\tuint32_t table_end = table_start + msix_table_size;\n+\t\t\ttable_end = (table_end + ~PAGE_MASK) & PAGE_MASK;\n+\t\t\ttable_start &= PAGE_MASK;\n+\n+\t\t\tif (table_start == 0 && table_end >= reg.size) {\n+\t\t\t\t/* Cannot map this BAR */\n+\t\t\t\tRTE_LOG(DEBUG, EAL, \"Skipping BAR %d\\n\", i);\n+\t\t\t\tcontinue;\n+\t\t\t} else {\n+\t\t\t\tmemreg[0].offset = reg.offset;\n+\t\t\t\tmemreg[0].size = table_start;\n+\t\t\t\tmemreg[1].offset = reg.offset + table_end;\n+\t\t\t\tmemreg[1].size = reg.size - table_end;\n+\n+\t\t\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\t\t\"Trying to map BAR %d that contains the MSI-X \"\n+\t\t\t\t\t\"table. Trying offsets: \"\n+\t\t\t\t\t\"0x%04lx:0x%04lx, 0x%04lx:0x%04lx\\n\", i,\n+\t\t\t\t\tmemreg[0].offset, memreg[0].size,\n+\t\t\t\t\tmemreg[1].offset, memreg[1].size);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tmemreg[0].offset = reg.offset;\n+\t\t\tmemreg[0].size = reg.size;\n+\t\t}\n+\n+\t\t/* try to figure out an address */\n+\t\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n+\t\t\t/* try mapping somewhere close to the end of hugepages */\n+\t\t\tif (pci_map_addr == NULL)\n+\t\t\t\tpci_map_addr = pci_find_max_end_va();\n+\n+\t\t\tbar_addr = pci_map_addr;\n+\t\t\tpci_map_addr = RTE_PTR_ADD(bar_addr, (size_t) reg.size);\n+\t\t} else {\n+\t\t\tbar_addr = maps[i].addr;\n+\t\t}\n+\n+\t\t/* reserve the address using an inaccessible mapping */\n+\t\tbar_addr = mmap(bar_addr, reg.size, 0, MAP_PRIVATE |\n+\t\t\t\tMAP_ANONYMOUS, -1, 0);\n+\t\tif (bar_addr != MAP_FAILED) {\n+\t\t\tvoid *map_addr = NULL;\n+\t\t\tif (memreg[0].size) {\n+\t\t\t\t/* actual map of first part */\n+\t\t\t\tmap_addr = pci_map_resource(bar_addr, vfio_dev_fd,\n+\t\t\t\t\t\t\t    memreg[0].offset,\n+\t\t\t\t\t\t\t    memreg[0].size,\n+\t\t\t\t\t\t\t    MAP_FIXED);\n+\t\t\t}\n+\n+\t\t\t/* if there's a second part, try to map it */\n+\t\t\tif (map_addr != MAP_FAILED\n+\t\t\t    && memreg[1].offset && memreg[1].size) {\n+\t\t\t\tvoid *second_addr = RTE_PTR_ADD(bar_addr,\n+\t\t\t\t\t\t\t\tmemreg[1].offset -\n+\t\t\t\t\t\t\t\t(uintptr_t)reg.offset);\n+\t\t\t\tmap_addr = pci_map_resource(second_addr,\n+\t\t\t\t\t\t\t    vfio_dev_fd, memreg[1].offset,\n+\t\t\t\t\t\t\t    memreg[1].size,\n+\t\t\t\t\t\t\t    MAP_FIXED);\n+\t\t\t}\n+\n+\t\t\tif (map_addr == MAP_FAILED || !map_addr) {\n+\t\t\t\tmunmap(bar_addr, reg.size);\n+\t\t\t\tbar_addr = MAP_FAILED;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (bar_addr == MAP_FAILED ||\n+\t\t\t\t(internal_config.process_type == RTE_PROC_SECONDARY &&\n+\t\t\t\t\t\tbar_addr != maps[i].addr)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  %s mapping BAR%i failed: %s\\n\", pci_addr, i,\n+\t\t\t\t\tstrerror(errno));\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n+\t\t\t\trte_free(vfio_res);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tmaps[i].addr = bar_addr;\n+\t\tmaps[i].offset = reg.offset;\n+\t\tmaps[i].size = reg.size;\n+\t\tmaps[i].path = NULL; /* vfio doesn't have per-resource paths */\n+\t\tdev->mem_resource[i].addr = bar_addr;\n+\t}\n+\n+\t/* if secondary process, do not set up interrupts */\n+\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n+\t\tif (pci_vfio_setup_interrupts(dev, vfio_dev_fd) != 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  %s error setting up interrupts!\\n\", pci_addr);\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\trte_free(vfio_res);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* set bus mastering for the device */\n+\t\tif (pci_vfio_set_bus_master(vfio_dev_fd, true)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot set up bus mastering!\\n\", pci_addr);\n+\t\t\tclose(vfio_dev_fd);\n+\t\t\trte_free(vfio_res);\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\t/* Reset the device */\n+\t\tioctl(vfio_dev_fd, VFIO_DEVICE_RESET);\n+\t}\n+\n+\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n+\t\tTAILQ_INSERT_TAIL(vfio_res_list, vfio_res, next);\n+\n+\treturn 0;\n+}\n+\n+int\n+pci_vfio_unmap_resource(struct rte_pci_device *dev)\n+{\n+\tchar pci_addr[PATH_MAX] = {0};\n+\tstruct rte_pci_addr *loc = &dev->addr;\n+\tint i, ret;\n+\tstruct mapped_pci_resource *vfio_res = NULL;\n+\tstruct mapped_pci_res_list *vfio_res_list;\n+\n+\tstruct pci_map *maps;\n+\n+\t/* store PCI address string */\n+\tsnprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,\n+\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n+\n+\n+\tif (close(dev->intr_handle.fd) < 0) {\n+\t\tRTE_LOG(INFO, EAL, \"Error when closing eventfd file descriptor for %s\\n\",\n+\t\t\tpci_addr);\n+\t\treturn -1;\n+\t}\n+\n+\tif (pci_vfio_set_bus_master(dev->intr_handle.vfio_dev_fd, false)) {\n+\t\tRTE_LOG(ERR, EAL, \"  %s cannot unset bus mastering for PCI device!\\n\",\n+\t\t\t\tpci_addr);\n+\t\treturn -1;\n+\t}\n+\n+\tret = vfio_release_device(pci_get_sysfs_path(), pci_addr,\n+\t\t\t\t  dev->intr_handle.vfio_dev_fd);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"%s(): cannot release device\\n\", __func__);\n+\t\treturn ret;\n+\t}\n+\n+\tvfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);\n+\t/* Get vfio_res */\n+\tTAILQ_FOREACH(vfio_res, vfio_res_list, next) {\n+\t\tif (memcmp(&vfio_res->pci_addr, &dev->addr, sizeof(dev->addr)))\n+\t\t\tcontinue;\n+\t\tbreak;\n+\t}\n+\t/* if we haven't found our tailq entry, something's wrong */\n+\tif (vfio_res == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"  %s cannot find TAILQ entry for PCI device!\\n\",\n+\t\t\t\tpci_addr);\n+\t\treturn -1;\n+\t}\n+\n+\t/* unmap BARs */\n+\tmaps = vfio_res->maps;\n+\n+\tRTE_LOG(INFO, EAL, \"Releasing pci mapped resource for %s\\n\",\n+\t\tpci_addr);\n+\tfor (i = 0; i < (int) vfio_res->nb_maps; i++) {\n+\n+\t\t/*\n+\t\t * We do not need to be aware of MSI-X table BAR mappings as\n+\t\t * when mapping. Just using current maps array is enough\n+\t\t */\n+\t\tif (maps[i].addr) {\n+\t\t\tRTE_LOG(INFO, EAL, \"Calling pci_unmap_resource for %s at %p\\n\",\n+\t\t\t\tpci_addr, maps[i].addr);\n+\t\t\tpci_unmap_resource(maps[i].addr, maps[i].size);\n+\t\t}\n+\t}\n+\n+\tTAILQ_REMOVE(vfio_res_list, vfio_res, next);\n+\n+\treturn 0;\n+}\n+\n+int\n+pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t    struct rte_pci_ioport *p)\n+{\n+\tif (bar < VFIO_PCI_BAR0_REGION_INDEX ||\n+\t    bar > VFIO_PCI_BAR5_REGION_INDEX) {\n+\t\tRTE_LOG(ERR, EAL, \"invalid bar (%d)!\\n\", bar);\n+\t\treturn -1;\n+\t}\n+\n+\tp->dev = dev;\n+\tp->base = VFIO_GET_REGION_ADDR(bar);\n+\treturn 0;\n+}\n+\n+void\n+pci_vfio_ioport_read(struct rte_pci_ioport *p,\n+\t\t     void *data, size_t len, off_t offset)\n+{\n+\tconst struct rte_intr_handle *intr_handle = &p->dev->intr_handle;\n+\n+\tif (pread64(intr_handle->vfio_dev_fd, data,\n+\t\t    len, p->base + offset) <= 0)\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Can't read from PCI bar (%\" PRIu64 \") : offset (%x)\\n\",\n+\t\t\tVFIO_GET_REGION_IDX(p->base), (int)offset);\n+}\n+\n+void\n+pci_vfio_ioport_write(struct rte_pci_ioport *p,\n+\t\t      const void *data, size_t len, off_t offset)\n+{\n+\tconst struct rte_intr_handle *intr_handle = &p->dev->intr_handle;\n+\n+\tif (pwrite64(intr_handle->vfio_dev_fd, data,\n+\t\t     len, p->base + offset) <= 0)\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Can't write to PCI bar (%\" PRIu64 \") : offset (%x)\\n\",\n+\t\t\tVFIO_GET_REGION_IDX(p->base), (int)offset);\n+}\n+\n+int\n+pci_vfio_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tRTE_SET_USED(p);\n+\treturn -1;\n+}\n+\n+int\n+pci_vfio_enable(void)\n+{\n+\treturn vfio_enable(\"vfio_pci\");\n+}\n+\n+int\n+pci_vfio_is_enabled(void)\n+{\n+\treturn vfio_is_enabled(\"vfio_pci\");\n+}\n+#endif\ndiff --git a/drivers/bus/pci/linux/rte_vfio_mp_sync.c b/drivers/bus/pci/linux/rte_vfio_mp_sync.c\nnew file mode 100644\nindex 0000000..2c1654d\n--- /dev/null\n+++ b/drivers/bus/pci/linux/rte_vfio_mp_sync.c\n@@ -0,0 +1,424 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. 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+\n+#include <string.h>\n+#include <fcntl.h>\n+#include <sys/socket.h>\n+#include <pthread.h>\n+\n+/* sys/un.h with __USE_MISC uses strlen, which is unsafe */\n+#ifdef __USE_MISC\n+#define REMOVED_USE_MISC\n+#undef __USE_MISC\n+#endif\n+#include <sys/un.h>\n+/* make sure we redefine __USE_MISC only if it was previously undefined */\n+#ifdef REMOVED_USE_MISC\n+#define __USE_MISC\n+#undef REMOVED_USE_MISC\n+#endif\n+\n+#include <rte_log.h>\n+#include <rte_pci.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_malloc.h>\n+\n+#include \"eal_filesystem.h\"\n+#include \"eal_thread.h\"\n+#include \"rte_pci_init.h\"\n+\n+/**\n+ * @file\n+ * VFIO socket for communication between primary and secondary processes.\n+ *\n+ * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to \"y\".\n+ */\n+\n+#ifdef VFIO_PRESENT\n+\n+#define SOCKET_PATH_FMT \"%s/.%s_mp_socket\"\n+#define CMSGLEN (CMSG_LEN(sizeof(int)))\n+#define FD_TO_CMSGHDR(fd, chdr) \\\n+\t\tdo {\\\n+\t\t\t(chdr).cmsg_len = CMSGLEN;\\\n+\t\t\t(chdr).cmsg_level = SOL_SOCKET;\\\n+\t\t\t(chdr).cmsg_type = SCM_RIGHTS;\\\n+\t\t\tmemcpy((chdr).__cmsg_data, &(fd), sizeof(fd));\\\n+\t\t} while (0)\n+#define CMSGHDR_TO_FD(chdr, fd) \\\n+\t\t\tmemcpy(&(fd), (chdr).__cmsg_data, sizeof(fd))\n+\n+static pthread_t socket_thread;\n+static int mp_socket_fd;\n+\n+\n+/* get socket path (/var/run if root, $HOME otherwise) */\n+static void\n+get_socket_path(char *buffer, int bufsz)\n+{\n+\tconst char *dir = \"/var/run\";\n+\tconst char *home_dir = getenv(\"HOME\");\n+\n+\tif (getuid() != 0 && home_dir != NULL)\n+\t\tdir = home_dir;\n+\n+\t/* use current prefix as file path */\n+\tsnprintf(buffer, bufsz, SOCKET_PATH_FMT, dir,\n+\t\t\tinternal_config.hugefile_prefix);\n+}\n+\n+\n+\n+/*\n+ * data flow for socket comm protocol:\n+ * 1. client sends SOCKET_REQ_CONTAINER or SOCKET_REQ_GROUP\n+ * 1a. in case of SOCKET_REQ_GROUP, client also then sends group number\n+ * 2. server receives message\n+ * 2a. in case of invalid group, SOCKET_ERR is sent back to client\n+ * 2b. in case of unbound group, SOCKET_NO_FD is sent back to client\n+ * 2c. in case of valid group, SOCKET_OK is sent and immediately followed by fd\n+ *\n+ * in case of any error, socket is closed.\n+ */\n+\n+/* send a request, return -1 on error */\n+int\n+vfio_mp_sync_send_request(int socket, int req)\n+{\n+\tstruct msghdr hdr;\n+\tstruct iovec iov;\n+\tint buf;\n+\tint ret;\n+\n+\tmemset(&hdr, 0, sizeof(hdr));\n+\n+\tbuf = req;\n+\n+\thdr.msg_iov = &iov;\n+\thdr.msg_iovlen = 1;\n+\tiov.iov_base = (char *) &buf;\n+\tiov.iov_len = sizeof(buf);\n+\n+\tret = sendmsg(socket, &hdr, 0);\n+\tif (ret < 0)\n+\t\treturn -1;\n+\treturn 0;\n+}\n+\n+/* receive a request and return it */\n+int\n+vfio_mp_sync_receive_request(int socket)\n+{\n+\tint buf;\n+\tstruct msghdr hdr;\n+\tstruct iovec iov;\n+\tint ret, req;\n+\n+\tmemset(&hdr, 0, sizeof(hdr));\n+\n+\tbuf = SOCKET_ERR;\n+\n+\thdr.msg_iov = &iov;\n+\thdr.msg_iovlen = 1;\n+\tiov.iov_base = (char *) &buf;\n+\tiov.iov_len = sizeof(buf);\n+\n+\tret = recvmsg(socket, &hdr, 0);\n+\tif (ret < 0)\n+\t\treturn -1;\n+\n+\treq = buf;\n+\n+\treturn req;\n+}\n+\n+/* send OK in message, fd in control message */\n+int\n+vfio_mp_sync_send_fd(int socket, int fd)\n+{\n+\tint buf;\n+\tstruct msghdr hdr;\n+\tstruct cmsghdr *chdr;\n+\tchar chdr_buf[CMSGLEN];\n+\tstruct iovec iov;\n+\tint ret;\n+\n+\tchdr = (struct cmsghdr *) chdr_buf;\n+\tmemset(chdr, 0, sizeof(chdr_buf));\n+\tmemset(&hdr, 0, sizeof(hdr));\n+\n+\thdr.msg_iov = &iov;\n+\thdr.msg_iovlen = 1;\n+\tiov.iov_base = (char *) &buf;\n+\tiov.iov_len = sizeof(buf);\n+\thdr.msg_control = chdr;\n+\thdr.msg_controllen = CMSGLEN;\n+\n+\tbuf = SOCKET_OK;\n+\tFD_TO_CMSGHDR(fd, *chdr);\n+\n+\tret = sendmsg(socket, &hdr, 0);\n+\tif (ret < 0)\n+\t\treturn -1;\n+\treturn 0;\n+}\n+\n+/* receive OK in message, fd in control message */\n+int\n+vfio_mp_sync_receive_fd(int socket)\n+{\n+\tint buf;\n+\tstruct msghdr hdr;\n+\tstruct cmsghdr *chdr;\n+\tchar chdr_buf[CMSGLEN];\n+\tstruct iovec iov;\n+\tint ret, req, fd;\n+\n+\tbuf = SOCKET_ERR;\n+\n+\tchdr = (struct cmsghdr *) chdr_buf;\n+\tmemset(chdr, 0, sizeof(chdr_buf));\n+\tmemset(&hdr, 0, sizeof(hdr));\n+\n+\thdr.msg_iov = &iov;\n+\thdr.msg_iovlen = 1;\n+\tiov.iov_base = (char *) &buf;\n+\tiov.iov_len = sizeof(buf);\n+\thdr.msg_control = chdr;\n+\thdr.msg_controllen = CMSGLEN;\n+\n+\tret = recvmsg(socket, &hdr, 0);\n+\tif (ret < 0)\n+\t\treturn -1;\n+\n+\treq = buf;\n+\n+\tif (req != SOCKET_OK)\n+\t\treturn -1;\n+\n+\tCMSGHDR_TO_FD(*chdr, fd);\n+\n+\treturn fd;\n+}\n+\n+/* connect socket_fd in secondary process to the primary process's socket */\n+int\n+vfio_mp_sync_connect_to_primary(void)\n+{\n+\tstruct sockaddr_un addr;\n+\tsocklen_t sockaddr_len;\n+\tint socket_fd;\n+\n+\t/* set up a socket */\n+\tsocket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\tif (socket_fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to create socket!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tget_socket_path(addr.sun_path, sizeof(addr.sun_path));\n+\taddr.sun_family = AF_UNIX;\n+\n+\tsockaddr_len = sizeof(struct sockaddr_un);\n+\n+\tif (connect(socket_fd, (struct sockaddr *) &addr, sockaddr_len) == 0)\n+\t\treturn socket_fd;\n+\n+\t/* if connect failed */\n+\tclose(socket_fd);\n+\treturn -1;\n+}\n+\n+\n+\n+/*\n+ * socket listening thread for primary process\n+ */\n+static __attribute__((noreturn)) void *\n+vfio_mp_sync_thread(void __rte_unused * arg)\n+{\n+\tint ret, fd, vfio_data;\n+\n+\t/* wait for requests on the socket */\n+\tfor (;;) {\n+\t\tint conn_sock;\n+\t\tstruct sockaddr_un addr;\n+\t\tsocklen_t sockaddr_len = sizeof(addr);\n+\n+\t\t/* this is a blocking call */\n+\t\tconn_sock = accept(mp_socket_fd, (struct sockaddr *) &addr,\n+\t\t\t\t&sockaddr_len);\n+\n+\t\t/* just restart on error */\n+\t\tif (conn_sock == -1)\n+\t\t\tcontinue;\n+\n+\t\t/* set socket to linger after close */\n+\t\tstruct linger l;\n+\t\tl.l_onoff = 1;\n+\t\tl.l_linger = 60;\n+\n+\t\tif (setsockopt(conn_sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0)\n+\t\t\tRTE_LOG(WARNING, EAL, \"Cannot set SO_LINGER option \"\n+\t\t\t\t\t\"on listen socket (%s)\\n\", strerror(errno));\n+\n+\t\tret = vfio_mp_sync_receive_request(conn_sock);\n+\n+\t\tswitch (ret) {\n+\t\tcase SOCKET_REQ_CONTAINER:\n+\t\t\tfd = vfio_get_container_fd();\n+\t\t\tif (fd < 0)\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n+\t\t\telse\n+\t\t\t\tvfio_mp_sync_send_fd(conn_sock, fd);\n+\t\t\tclose(fd);\n+\t\t\tbreak;\n+\t\tcase SOCKET_REQ_GROUP:\n+\t\t\t/* wait for group number */\n+\t\t\tvfio_data = vfio_mp_sync_receive_request(conn_sock);\n+\t\t\tif (vfio_data < 0) {\n+\t\t\t\tclose(conn_sock);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tfd = vfio_get_group_fd(vfio_data);\n+\n+\t\t\tif (fd < 0)\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n+\t\t\t/* if VFIO group exists but isn't bound to VFIO driver */\n+\t\t\telse if (fd == 0)\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD);\n+\t\t\t/* if group exists and is bound to VFIO driver */\n+\t\t\telse {\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_OK);\n+\t\t\t\tvfio_mp_sync_send_fd(conn_sock, fd);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\tcase SOCKET_CLR_GROUP:\n+\t\t\t/* wait for group fd */\n+\t\t\tvfio_data = vfio_mp_sync_receive_request(conn_sock);\n+\t\t\tif (vfio_data < 0) {\n+\t\t\t\tclose(conn_sock);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\tret = clear_group(vfio_data);\n+\n+\t\t\tif (ret < 0)\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD);\n+\t\t\telse\n+\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_OK);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n+\t\t\tbreak;\n+\t\t}\n+\t\tclose(conn_sock);\n+\t}\n+}\n+\n+static int\n+vfio_mp_sync_socket_setup(void)\n+{\n+\tint ret, socket_fd;\n+\tstruct sockaddr_un addr;\n+\tsocklen_t sockaddr_len;\n+\n+\t/* set up a socket */\n+\tsocket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n+\tif (socket_fd < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to create socket!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tget_socket_path(addr.sun_path, sizeof(addr.sun_path));\n+\taddr.sun_family = AF_UNIX;\n+\n+\tsockaddr_len = sizeof(struct sockaddr_un);\n+\n+\tunlink(addr.sun_path);\n+\n+\tret = bind(socket_fd, (struct sockaddr *) &addr, sockaddr_len);\n+\tif (ret) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to bind socket: %s!\\n\", strerror(errno));\n+\t\tclose(socket_fd);\n+\t\treturn -1;\n+\t}\n+\n+\tret = listen(socket_fd, 50);\n+\tif (ret) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to listen: %s!\\n\", strerror(errno));\n+\t\tclose(socket_fd);\n+\t\treturn -1;\n+\t}\n+\n+\t/* save the socket in local configuration */\n+\tmp_socket_fd = socket_fd;\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * set up a local socket and tell it to listen for incoming connections\n+ */\n+int\n+vfio_mp_sync_setup(void)\n+{\n+\tint ret;\n+\tchar thread_name[RTE_MAX_THREAD_NAME_LEN];\n+\n+\tif (vfio_mp_sync_socket_setup() < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Failed to set up local socket!\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = pthread_create(&socket_thread, NULL,\n+\t\t\tvfio_mp_sync_thread, NULL);\n+\tif (ret) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\"Failed to create thread for communication with secondary processes!\\n\");\n+\t\tclose(mp_socket_fd);\n+\t\treturn -1;\n+\t}\n+\n+\t/* Set thread_name for aid in debugging. */\n+\tsnprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, \"vfio-sync\");\n+\tret = rte_thread_setname(socket_thread, thread_name);\n+\tif (ret)\n+\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\"Failed to set thread name for secondary processes!\\n\");\n+\n+\treturn 0;\n+}\n+\n+#endif\ndiff --git a/drivers/bus/pci/private.h b/drivers/bus/pci/private.h\nnew file mode 100644\nindex 0000000..7ff1fc4\n--- /dev/null\n+++ b/drivers/bus/pci/private.h\n@@ -0,0 +1,173 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 6WIND. 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 6WIND 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+\n+#ifndef _PCI_PRIVATE_H_\n+#define _PCI_PRIVATE_H_\n+\n+#include <stdbool.h>\n+#include <stdio.h>\n+#include <rte_pci.h>\n+\n+struct rte_pci_driver;\n+struct rte_pci_device;\n+\n+/**\n+ * Find the name of a PCI device.\n+ */\n+void\n+pci_name_set(struct rte_pci_device *dev);\n+\n+/**\n+ * Add a PCI device to the PCI Bus (append to PCI Device list). This function\n+ * also updates the bus references of the PCI Device (and the generic device\n+ * object embedded within.\n+ *\n+ * @param pci_dev\n+ *\tPCI device to add\n+ * @return void\n+ */\n+void rte_pci_add_device(struct rte_pci_device *pci_dev);\n+\n+/**\n+ * Insert a PCI device in the PCI Bus at a particular location in the device\n+ * list. It also updates the PCI Bus reference of the new devices to be\n+ * inserted.\n+ *\n+ * @param exist_pci_dev\n+ *\tExisting PCI device in PCI Bus\n+ * @param new_pci_dev\n+ *\tPCI device to be added before exist_pci_dev\n+ * @return void\n+ */\n+void rte_pci_insert_device(struct rte_pci_device *exist_pci_dev,\n+\t\tstruct rte_pci_device *new_pci_dev);\n+\n+/**\n+ * Remove a PCI device from the PCI Bus. This sets to NULL the bus references\n+ * in the PCI device object as well as the generic device object.\n+ *\n+ * @param pci_device\n+ *\tPCI device to be removed from PCI Bus\n+ * @return void\n+ */\n+void rte_pci_remove_device(struct rte_pci_device *pci_device);\n+\n+/**\n+ * Update a pci device object by asking the kernel for the latest information.\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @param addr\n+ *\tThe PCI Bus-Device-Function address to look for\n+ * @return\n+ *   - 0 on success.\n+ *   - negative on error.\n+ */\n+int pci_update_device(const struct rte_pci_addr *addr);\n+\n+/**\n+ * Unbind kernel driver for this device\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @return\n+ *   0 on success, negative on error\n+ */\n+int pci_unbind_kernel_driver(struct rte_pci_device *dev);\n+\n+/**\n+ * Map the PCI resource of a PCI device in virtual memory\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @return\n+ *   0 on success, negative on error\n+ */\n+int pci_uio_map_resource(struct rte_pci_device *dev);\n+\n+/**\n+ * Unmap the PCI resource of a PCI device\n+ *\n+ * This function is private to EAL.\n+ */\n+void pci_uio_unmap_resource(struct rte_pci_device *dev);\n+\n+/**\n+ * Allocate uio resource for PCI device\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @param dev\n+ *   PCI device to allocate uio resource\n+ * @param uio_res\n+ *   Pointer to uio resource.\n+ *   If the function returns 0, the pointer will be filled.\n+ * @return\n+ *   0 on success, negative on error\n+ */\n+int pci_uio_alloc_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource **uio_res);\n+\n+/**\n+ * Free uio resource for PCI device\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @param dev\n+ *   PCI device to free uio resource\n+ * @param uio_res\n+ *   Pointer to uio resource.\n+ */\n+void pci_uio_free_resource(struct rte_pci_device *dev,\n+\t\tstruct mapped_pci_resource *uio_res);\n+\n+/**\n+ * Map device memory to uio resource\n+ *\n+ * This function is private to EAL.\n+ *\n+ * @param dev\n+ *   PCI device that has memory information.\n+ * @param res_idx\n+ *   Memory resource index of the PCI device.\n+ * @param uio_res\n+ *  uio resource that will keep mapping information.\n+ * @param map_idx\n+ *   Mapping information index of the uio resource.\n+ * @return\n+ *   0 on success, negative on error\n+ */\n+int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n+\t\tstruct mapped_pci_resource *uio_res, int map_idx);\n+\n+#endif /* _PCI_PRIVATE_H_ */\ndiff --git a/drivers/bus/pci/rte_bus_pci_version.map b/drivers/bus/pci/rte_bus_pci_version.map\nnew file mode 100644\nindex 0000000..eca49e9\n--- /dev/null\n+++ b/drivers/bus/pci/rte_bus_pci_version.map\n@@ -0,0 +1,21 @@\n+DPDK_17.08 {\n+\tglobal:\n+\n+\trte_pci_detach;\n+\trte_pci_dump;\n+\trte_pci_ioport_map;\n+\trte_pci_ioport_read;\n+\trte_pci_ioport_unmap;\n+\trte_pci_ioport_write;\n+\trte_pci_map_device;\n+\trte_pci_probe;\n+\trte_pci_probe_one;\n+\trte_pci_read_config;\n+\trte_pci_register;\n+\trte_pci_scan;\n+\trte_pci_unmap_device;\n+\trte_pci_unregister;\n+\trte_pci_write_config;\n+\n+\tlocal: *;\n+};\ndiff --git a/drivers/bus/pci/rte_pci_common.c b/drivers/bus/pci/rte_pci_common.c\nnew file mode 100644\nindex 0000000..c37b85b\n--- /dev/null\n+++ b/drivers/bus/pci/rte_pci_common.c\n@@ -0,0 +1,542 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright 2013-2014 6WIND S.A.\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+\n+#include <string.h>\n+#include <inttypes.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <sys/queue.h>\n+#include <sys/mman.h>\n+\n+#include <rte_errno.h>\n+#include <rte_interrupts.h>\n+#include <rte_log.h>\n+#include <rte_bus.h>\n+#include <rte_pci.h>\n+#include <rte_per_lcore.h>\n+#include <rte_memory.h>\n+#include <rte_memzone.h>\n+#include <rte_eal.h>\n+#include <rte_string_fns.h>\n+#include <rte_common.h>\n+#include <rte_devargs.h>\n+\n+#include \"private.h\"\n+\n+extern struct rte_pci_bus rte_pci_bus;\n+\n+#define SYSFS_PCI_DEVICES \"/sys/bus/pci/devices\"\n+\n+const char *pci_get_sysfs_path(void)\n+{\n+\tconst char *path = NULL;\n+\n+\tpath = getenv(\"SYSFS_PCI_DEVICES\");\n+\tif (path == NULL)\n+\t\treturn SYSFS_PCI_DEVICES;\n+\n+\treturn path;\n+}\n+\n+static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)\n+{\n+\tstruct rte_devargs *devargs;\n+\tstruct rte_pci_addr addr;\n+\tstruct rte_bus *pbus;\n+\n+\tpbus = rte_bus_find_by_name(\"pci\");\n+\tTAILQ_FOREACH(devargs, &devargs_list, next) {\n+\t\tif (devargs->bus != pbus)\n+\t\t\tcontinue;\n+\t\tdevargs->bus->parse(devargs->name, &addr);\n+\t\tif (!rte_eal_compare_pci_addr(&dev->addr, &addr))\n+\t\t\treturn devargs;\n+\t}\n+\treturn NULL;\n+}\n+\n+void\n+pci_name_set(struct rte_pci_device *dev)\n+{\n+\tstruct rte_devargs *devargs;\n+\n+\t/* Each device has its internal, canonical name set. */\n+\trte_pci_device_name(&dev->addr,\n+\t\t\tdev->name, sizeof(dev->name));\n+\tdevargs = pci_devargs_lookup(dev);\n+\tdev->device.devargs = devargs;\n+\t/* In blacklist mode, if the device is not blacklisted, no\n+\t * rte_devargs exists for it.\n+\t */\n+\tif (devargs != NULL)\n+\t\t/* If an rte_devargs exists, the generic rte_device uses the\n+\t\t * given name as its namea\n+\t\t */\n+\t\tdev->device.name = dev->device.devargs->name;\n+\telse\n+\t\t/* Otherwise, it uses the internal, canonical form. */\n+\t\tdev->device.name = dev->name;\n+}\n+\n+/*\n+ * Match the PCI Driver and Device using the ID Table\n+ *\n+ * @param pci_drv\n+ *\tPCI driver from which ID table would be extracted\n+ * @param pci_dev\n+ *\tPCI device to match against the driver\n+ * @return\n+ *\t1 for successful match\n+ *\t0 for unsuccessful match\n+ */\n+static int\n+rte_pci_match(const struct rte_pci_driver *pci_drv,\n+\t      const struct rte_pci_device *pci_dev)\n+{\n+\tconst struct rte_pci_id *id_table;\n+\n+\tfor (id_table = pci_drv->id_table; id_table->vendor_id != 0;\n+\t     id_table++) {\n+\t\t/* check if device's identifiers match the driver's ones */\n+\t\tif (id_table->vendor_id != pci_dev->id.vendor_id &&\n+\t\t\t\tid_table->vendor_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->device_id != pci_dev->id.device_id &&\n+\t\t\t\tid_table->device_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->subsystem_vendor_id !=\n+\t\t    pci_dev->id.subsystem_vendor_id &&\n+\t\t    id_table->subsystem_vendor_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->subsystem_device_id !=\n+\t\t    pci_dev->id.subsystem_device_id &&\n+\t\t    id_table->subsystem_device_id != PCI_ANY_ID)\n+\t\t\tcontinue;\n+\t\tif (id_table->class_id != pci_dev->id.class_id &&\n+\t\t\t\tid_table->class_id != RTE_CLASS_ANY_ID)\n+\t\t\tcontinue;\n+\n+\t\treturn 1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * If vendor/device ID match, call the probe() function of the\n+ * driver.\n+ */\n+static int\n+rte_pci_probe_one_driver(struct rte_pci_driver *dr,\n+\t\t\t struct rte_pci_device *dev)\n+{\n+\tint ret;\n+\tstruct rte_pci_addr *loc;\n+\n+\tif ((dr == NULL) || (dev == NULL))\n+\t\treturn -EINVAL;\n+\n+\tloc = &dev->addr;\n+\n+\t/* The device is not blacklisted; Check if driver supports it */\n+\tif (!rte_pci_match(dr, dev))\n+\t\t/* Match of device and driver failed */\n+\t\treturn 1;\n+\n+\tRTE_LOG(INFO, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n+\t\t\tloc->domain, loc->bus, loc->devid, loc->function,\n+\t\t\tdev->device.numa_node);\n+\n+\t/* no initialization when blacklisted, return without error */\n+\tif (dev->device.devargs != NULL &&\n+\t\tdev->device.devargs->policy ==\n+\t\t\tRTE_DEV_BLACKLISTED) {\n+\t\tRTE_LOG(INFO, EAL, \"  Device is blacklisted, not\"\n+\t\t\t\" initializing\\n\");\n+\t\treturn 1;\n+\t}\n+\n+\tif (dev->device.numa_node < 0) {\n+\t\tRTE_LOG(WARNING, EAL, \"  Invalid NUMA socket, default to 0\\n\");\n+\t\tdev->device.numa_node = 0;\n+\t}\n+\n+\tRTE_LOG(INFO, EAL, \"  probe driver: %x:%x %s\\n\", dev->id.vendor_id,\n+\t\tdev->id.device_id, dr->driver.name);\n+\n+\tif (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {\n+\t\t/* map resources for devices that use igb_uio */\n+\t\tret = rte_pci_map_device(dev);\n+\t\tif (ret != 0)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/* reference driver structure */\n+\tdev->driver = dr;\n+\tdev->device.driver = &dr->driver;\n+\n+\t/* call the driver probe() function */\n+\tret = dr->probe(dr, dev);\n+\tif (ret) {\n+\t\tdev->driver = NULL;\n+\t\tdev->device.driver = NULL;\n+\t\tif ((dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) &&\n+\t\t\t/* Don't unmap if device is unsupported and\n+\t\t\t * driver needs mapped resources.\n+\t\t\t */\n+\t\t\t!(ret > 0 &&\n+\t\t\t\t(dr->drv_flags & RTE_PCI_DRV_KEEP_MAPPED_RES)))\n+\t\t\trte_pci_unmap_device(dev);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/*\n+ * If vendor/device ID match, call the remove() function of the\n+ * driver.\n+ */\n+static int\n+rte_pci_detach_dev(struct rte_pci_device *dev)\n+{\n+\tstruct rte_pci_addr *loc;\n+\tstruct rte_pci_driver *dr;\n+\n+\tif (dev == NULL)\n+\t\treturn -EINVAL;\n+\n+\tdr = dev->driver;\n+\tloc = &dev->addr;\n+\n+\tRTE_LOG(DEBUG, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n+\t\t\tloc->domain, loc->bus, loc->devid,\n+\t\t\tloc->function, dev->device.numa_node);\n+\n+\tRTE_LOG(DEBUG, EAL, \"  remove driver: %x:%x %s\\n\", dev->id.vendor_id,\n+\t\t\tdev->id.device_id, dr->driver.name);\n+\n+\tif (dr->remove && (dr->remove(dev) < 0))\n+\t\treturn -1;\t/* negative value is an error */\n+\n+\t/* clear driver structure */\n+\tdev->driver = NULL;\n+\n+\tif (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)\n+\t\t/* unmap resources for devices that use igb_uio */\n+\t\trte_pci_unmap_device(dev);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * If vendor/device ID match, call the probe() function of all\n+ * registered driver for the given device. Return -1 if initialization\n+ * failed, return 1 if no driver is found for this device.\n+ */\n+static int\n+pci_probe_all_drivers(struct rte_pci_device *dev)\n+{\n+\tstruct rte_pci_driver *dr = NULL;\n+\tint rc = 0;\n+\n+\tif (dev == NULL)\n+\t\treturn -1;\n+\n+\t/* Check if a driver is already loaded */\n+\tif (dev->driver != NULL)\n+\t\treturn 0;\n+\n+\tFOREACH_DRIVER_ON_PCIBUS(dr) {\n+\t\trc = rte_pci_probe_one_driver(dr, dev);\n+\t\tif (rc < 0)\n+\t\t\t/* negative value is an error */\n+\t\t\treturn -1;\n+\t\tif (rc > 0)\n+\t\t\t/* positive value means driver doesn't support it */\n+\t\t\tcontinue;\n+\t\treturn 0;\n+\t}\n+\treturn 1;\n+}\n+\n+/*\n+ * Find the pci device specified by pci address, then invoke probe function of\n+ * the driver of the device.\n+ */\n+int\n+rte_pci_probe_one(const struct rte_pci_addr *addr)\n+{\n+\tstruct rte_pci_device *dev = NULL;\n+\n+\tint ret = 0;\n+\n+\tif (addr == NULL)\n+\t\treturn -1;\n+\n+\t/* update current pci device in global list, kernel bindings might have\n+\t * changed since last time we looked at it.\n+\t */\n+\tif (pci_update_device(addr) < 0)\n+\t\tgoto err_return;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n+\t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n+\t\t\tcontinue;\n+\n+\t\tret = pci_probe_all_drivers(dev);\n+\t\tif (ret)\n+\t\t\tgoto err_return;\n+\t\treturn 0;\n+\t}\n+\treturn -1;\n+\n+err_return:\n+\tRTE_LOG(WARNING, EAL,\n+\t\t\"Requested device \" PCI_PRI_FMT \" cannot be used\\n\",\n+\t\taddr->domain, addr->bus, addr->devid, addr->function);\n+\treturn -1;\n+}\n+\n+/*\n+ * Detach device specified by its pci address.\n+ */\n+int\n+rte_pci_detach(const struct rte_pci_addr *addr)\n+{\n+\tstruct rte_pci_device *dev = NULL;\n+\tint ret = 0;\n+\n+\tif (addr == NULL)\n+\t\treturn -1;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n+\t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n+\t\t\tcontinue;\n+\n+\t\tret = rte_pci_detach_dev(dev);\n+\t\tif (ret < 0)\n+\t\t\t/* negative value is an error */\n+\t\t\tgoto err_return;\n+\t\tif (ret > 0)\n+\t\t\t/* positive value means driver doesn't support it */\n+\t\t\tcontinue;\n+\n+\t\trte_pci_remove_device(dev);\n+\t\tfree(dev);\n+\t\treturn 0;\n+\t}\n+\treturn -1;\n+\n+err_return:\n+\tRTE_LOG(WARNING, EAL, \"Requested device \" PCI_PRI_FMT\n+\t\t\t\" cannot be used\\n\", dev->addr.domain, dev->addr.bus,\n+\t\t\tdev->addr.devid, dev->addr.function);\n+\treturn -1;\n+}\n+\n+/*\n+ * Scan the content of the PCI bus, and call the probe() function for\n+ * all registered drivers that have a matching entry in its id_table\n+ * for discovered devices.\n+ */\n+int\n+rte_pci_probe(void)\n+{\n+\tstruct rte_pci_device *dev = NULL;\n+\tsize_t probed = 0, failed = 0;\n+\tstruct rte_devargs *devargs;\n+\tint probe_all = 0;\n+\tint ret = 0;\n+\n+\tif (rte_pci_bus.bus.conf.scan_mode != RTE_BUS_SCAN_WHITELIST)\n+\t\tprobe_all = 1;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n+\t\tprobed++;\n+\n+\t\tdevargs = dev->device.devargs;\n+\t\t/* probe all or only whitelisted devices */\n+\t\tif (probe_all)\n+\t\t\tret = pci_probe_all_drivers(dev);\n+\t\telse if (devargs != NULL &&\n+\t\t\tdevargs->policy == RTE_DEV_WHITELISTED)\n+\t\t\tret = pci_probe_all_drivers(dev);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Requested device \" PCI_PRI_FMT\n+\t\t\t\t \" cannot be used\\n\", dev->addr.domain, dev->addr.bus,\n+\t\t\t\t dev->addr.devid, dev->addr.function);\n+\t\t\trte_errno = errno;\n+\t\t\tfailed++;\n+\t\t\tret = 0;\n+\t\t}\n+\t}\n+\n+\treturn (probed && probed == failed) ? -1 : 0;\n+}\n+\n+/* dump one device */\n+static int\n+pci_dump_one_device(FILE *f, struct rte_pci_device *dev)\n+{\n+\tint i;\n+\n+\tfprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,\n+\t       dev->addr.devid, dev->addr.function);\n+\tfprintf(f, \" - vendor:%x device:%x\\n\", dev->id.vendor_id,\n+\t       dev->id.device_id);\n+\n+\tfor (i = 0; i != sizeof(dev->mem_resource) /\n+\t\tsizeof(dev->mem_resource[0]); i++) {\n+\t\tfprintf(f, \"   %16.16\"PRIx64\" %16.16\"PRIx64\"\\n\",\n+\t\t\tdev->mem_resource[i].phys_addr,\n+\t\t\tdev->mem_resource[i].len);\n+\t}\n+\treturn 0;\n+}\n+\n+/* dump devices on the bus */\n+void\n+rte_pci_dump(FILE *f)\n+{\n+\tstruct rte_pci_device *dev = NULL;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n+\t\tpci_dump_one_device(f, dev);\n+\t}\n+}\n+\n+static int\n+pci_parse(const char *name, void *addr)\n+{\n+\tstruct rte_pci_addr *out = addr;\n+\tstruct rte_pci_addr pci_addr;\n+\tbool parse;\n+\n+\tparse = (eal_parse_pci_BDF(name, &pci_addr) == 0 ||\n+\t\t eal_parse_pci_DomBDF(name, &pci_addr) == 0);\n+\tif (parse && addr != NULL)\n+\t\t*out = pci_addr;\n+\treturn parse == false;\n+}\n+\n+/* register a driver */\n+void\n+rte_pci_register(struct rte_pci_driver *driver)\n+{\n+\tTAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);\n+\tdriver->bus = &rte_pci_bus;\n+}\n+\n+/* unregister a driver */\n+void\n+rte_pci_unregister(struct rte_pci_driver *driver)\n+{\n+\tTAILQ_REMOVE(&rte_pci_bus.driver_list, driver, next);\n+\tdriver->bus = NULL;\n+}\n+\n+/* Add a device to PCI bus */\n+void\n+rte_pci_add_device(struct rte_pci_device *pci_dev)\n+{\n+\tTAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);\n+}\n+\n+/* Insert a device into a predefined position in PCI bus */\n+void\n+rte_pci_insert_device(struct rte_pci_device *exist_pci_dev,\n+\t\t      struct rte_pci_device *new_pci_dev)\n+{\n+\tTAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);\n+}\n+\n+/* Remove a device from PCI bus */\n+void\n+rte_pci_remove_device(struct rte_pci_device *pci_dev)\n+{\n+\tTAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);\n+}\n+\n+static struct rte_device *\n+pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,\n+\t\tconst void *data)\n+{\n+\tstruct rte_pci_device *dev;\n+\n+\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n+\t\tif (start && &dev->device == start) {\n+\t\t\tstart = NULL; /* starting point found */\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (cmp(&dev->device, data) == 0)\n+\t\t\treturn &dev->device;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int\n+pci_plug(struct rte_device *dev)\n+{\n+\treturn pci_probe_all_drivers(RTE_DEV_TO_PCI(dev));\n+}\n+\n+static int\n+pci_unplug(struct rte_device *dev)\n+{\n+\tstruct rte_pci_device *pdev;\n+\tint ret;\n+\n+\tpdev = RTE_DEV_TO_PCI(dev);\n+\tret = rte_pci_detach_dev(pdev);\n+\trte_pci_remove_device(pdev);\n+\tfree(pdev);\n+\treturn ret;\n+}\n+\n+struct rte_pci_bus rte_pci_bus = {\n+\t.bus = {\n+\t\t.scan = rte_pci_scan,\n+\t\t.probe = rte_pci_probe,\n+\t\t.find_device = pci_find_device,\n+\t\t.plug = pci_plug,\n+\t\t.unplug = pci_unplug,\n+\t\t.parse = pci_parse,\n+\t},\n+\t.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),\n+\t.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),\n+};\n+\n+RTE_REGISTER_BUS(pci, rte_pci_bus.bus);\ndiff --git a/drivers/bus/pci/rte_pci_common_uio.c b/drivers/bus/pci/rte_pci_common_uio.c\nnew file mode 100644\nindex 0000000..4365660\n--- /dev/null\n+++ b/drivers/bus/pci/rte_pci_common_uio.c\n@@ -0,0 +1,234 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. 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+\n+#include <fcntl.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <sys/mman.h>\n+\n+#include <rte_eal.h>\n+#include <rte_pci.h>\n+#include <rte_tailq.h>\n+#include <rte_log.h>\n+#include <rte_malloc.h>\n+\n+#include \"private.h\"\n+\n+static struct rte_tailq_elem rte_uio_tailq = {\n+\t.name = \"UIO_RESOURCE_LIST\",\n+};\n+EAL_REGISTER_TAILQ(rte_uio_tailq)\n+\n+static int\n+pci_uio_map_secondary(struct rte_pci_device *dev)\n+{\n+\tint fd, i, j;\n+\tstruct mapped_pci_resource *uio_res;\n+\tstruct mapped_pci_res_list *uio_res_list =\n+\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n+\n+\tTAILQ_FOREACH(uio_res, uio_res_list, next) {\n+\n+\t\t/* skip this element if it doesn't match our PCI address */\n+\t\tif (rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))\n+\t\t\tcontinue;\n+\n+\t\tfor (i = 0; i != uio_res->nb_maps; i++) {\n+\t\t\t/*\n+\t\t\t * open devname, to mmap it\n+\t\t\t */\n+\t\t\tfd = open(uio_res->maps[i].path, O_RDWR);\n+\t\t\tif (fd < 0) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n+\t\t\t\t\tuio_res->maps[i].path, strerror(errno));\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\tvoid *mapaddr = pci_map_resource(uio_res->maps[i].addr,\n+\t\t\t\t\tfd, (off_t)uio_res->maps[i].offset,\n+\t\t\t\t\t(size_t)uio_res->maps[i].size, 0);\n+\t\t\t/* fd is not needed in slave process, close it */\n+\t\t\tclose(fd);\n+\t\t\tif (mapaddr != uio_res->maps[i].addr) {\n+\t\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\t\"Cannot mmap device resource file %s to address: %p\\n\",\n+\t\t\t\t\tuio_res->maps[i].path,\n+\t\t\t\t\tuio_res->maps[i].addr);\n+\t\t\t\tif (mapaddr != MAP_FAILED) {\n+\t\t\t\t\t/* unmap addrs correctly mapped */\n+\t\t\t\t\tfor (j = 0; j < i; j++)\n+\t\t\t\t\t\tpci_unmap_resource(\n+\t\t\t\t\t\t\tuio_res->maps[j].addr,\n+\t\t\t\t\t\t\t(size_t)uio_res->maps[j].size);\n+\t\t\t\t\t/* unmap addr wrongly mapped */\n+\t\t\t\t\tpci_unmap_resource(mapaddr,\n+\t\t\t\t\t\t(size_t)uio_res->maps[i].size);\n+\t\t\t\t}\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\n+\tRTE_LOG(ERR, EAL, \"Cannot find resource for device\\n\");\n+\treturn 1;\n+}\n+\n+/* map the PCI resource of a PCI device in virtual memory */\n+int\n+pci_uio_map_resource(struct rte_pci_device *dev)\n+{\n+\tint i, map_idx = 0, ret;\n+\tuint64_t phaddr;\n+\tstruct mapped_pci_resource *uio_res = NULL;\n+\tstruct mapped_pci_res_list *uio_res_list =\n+\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n+\n+\tdev->intr_handle.fd = -1;\n+\tdev->intr_handle.uio_cfg_fd = -1;\n+\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+\n+\t/* secondary processes - use already recorded details */\n+\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n+\t\treturn pci_uio_map_secondary(dev);\n+\n+\t/* allocate uio resource */\n+\tret = pci_uio_alloc_resource(dev, &uio_res);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Map all BARs */\n+\tfor (i = 0; i != PCI_MAX_RESOURCE; i++) {\n+\t\t/* skip empty BAR */\n+\t\tphaddr = dev->mem_resource[i].phys_addr;\n+\t\tif (phaddr == 0)\n+\t\t\tcontinue;\n+\n+\t\tret = pci_uio_map_resource_by_index(dev, i,\n+\t\t\t\tuio_res, map_idx);\n+\t\tif (ret)\n+\t\t\tgoto error;\n+\n+\t\tmap_idx++;\n+\t}\n+\n+\tuio_res->nb_maps = map_idx;\n+\n+\tTAILQ_INSERT_TAIL(uio_res_list, uio_res, next);\n+\n+\treturn 0;\n+error:\n+\tfor (i = 0; i < map_idx; i++) {\n+\t\tpci_unmap_resource(uio_res->maps[i].addr,\n+\t\t\t\t(size_t)uio_res->maps[i].size);\n+\t\trte_free(uio_res->maps[i].path);\n+\t}\n+\tpci_uio_free_resource(dev, uio_res);\n+\treturn -1;\n+}\n+\n+static void\n+pci_uio_unmap(struct mapped_pci_resource *uio_res)\n+{\n+\tint i;\n+\n+\tif (uio_res == NULL)\n+\t\treturn;\n+\n+\tfor (i = 0; i != uio_res->nb_maps; i++) {\n+\t\tpci_unmap_resource(uio_res->maps[i].addr,\n+\t\t\t\t(size_t)uio_res->maps[i].size);\n+\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n+\t\t\trte_free(uio_res->maps[i].path);\n+\t}\n+}\n+\n+static struct mapped_pci_resource *\n+pci_uio_find_resource(struct rte_pci_device *dev)\n+{\n+\tstruct mapped_pci_resource *uio_res;\n+\tstruct mapped_pci_res_list *uio_res_list =\n+\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n+\n+\tif (dev == NULL)\n+\t\treturn NULL;\n+\n+\tTAILQ_FOREACH(uio_res, uio_res_list, next) {\n+\n+\t\t/* skip this element if it doesn't match our PCI address */\n+\t\tif (!rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))\n+\t\t\treturn uio_res;\n+\t}\n+\treturn NULL;\n+}\n+\n+/* unmap the PCI resource of a PCI device in virtual memory */\n+void\n+pci_uio_unmap_resource(struct rte_pci_device *dev)\n+{\n+\tstruct mapped_pci_resource *uio_res;\n+\tstruct mapped_pci_res_list *uio_res_list =\n+\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n+\n+\tif (dev == NULL)\n+\t\treturn;\n+\n+\t/* find an entry for the device */\n+\tuio_res = pci_uio_find_resource(dev);\n+\tif (uio_res == NULL)\n+\t\treturn;\n+\n+\t/* secondary processes - just free maps */\n+\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n+\t\treturn pci_uio_unmap(uio_res);\n+\n+\tTAILQ_REMOVE(uio_res_list, uio_res, next);\n+\n+\t/* unmap all resources */\n+\tpci_uio_unmap(uio_res);\n+\n+\t/* free uio resource */\n+\trte_free(uio_res);\n+\n+\t/* close fd if in primary process */\n+\tclose(dev->intr_handle.fd);\n+\tif (dev->intr_handle.uio_cfg_fd >= 0) {\n+\t\tclose(dev->intr_handle.uio_cfg_fd);\n+\t\tdev->intr_handle.uio_cfg_fd = -1;\n+\t}\n+\n+\tdev->intr_handle.fd = -1;\n+\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n+}\ndiff --git a/lib/Makefile b/lib/Makefile\nindex 86caba1..147be60 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -33,6 +33,8 @@ include $(RTE_SDK)/mk/rte.vars.mk\n \n DIRS-y += librte_compat\n DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal\n+DIRS-$(CONFIG_RTE_LIBRTE_PCI) += librte_pci\n+DEPDIRS-librte_pci := librte_eal\n DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring\n DEPDIRS-librte_ring := librte_eal\n DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool\ndiff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile\nindex 005019e..e5273f7 100644\n--- a/lib/librte_eal/bsdapp/eal/Makefile\n+++ b/lib/librte_eal/bsdapp/eal/Makefile\n@@ -55,7 +55,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_memory.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_hugepage_info.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_thread.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_pci.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_debug.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_lcore.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_timer.c\n@@ -69,8 +68,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_vdev.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_pci_uio.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_tailqs.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_errno.c\ndiff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c\ndeleted file mode 100644\nindex 04eacdc..0000000\n--- a/lib/librte_eal/bsdapp/eal/eal_pci.c\n+++ /dev/null\n@@ -1,670 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#include <ctype.h>\n-#include <stdio.h>\n-#include <stdlib.h>\n-#include <string.h>\n-#include <stdarg.h>\n-#include <unistd.h>\n-#include <inttypes.h>\n-#include <sys/types.h>\n-#include <sys/stat.h>\n-#include <fcntl.h>\n-#include <errno.h>\n-#include <dirent.h>\n-#include <limits.h>\n-#include <sys/queue.h>\n-#include <sys/mman.h>\n-#include <sys/ioctl.h>\n-#include <sys/pciio.h>\n-#include <dev/pci/pcireg.h>\n-\n-#if defined(RTE_ARCH_X86)\n-#include <machine/cpufunc.h>\n-#endif\n-\n-#include <rte_interrupts.h>\n-#include <rte_log.h>\n-#include <rte_pci.h>\n-#include <rte_common.h>\n-#include <rte_launch.h>\n-#include <rte_memory.h>\n-#include <rte_memzone.h>\n-#include <rte_eal.h>\n-#include <rte_eal_memconfig.h>\n-#include <rte_per_lcore.h>\n-#include <rte_lcore.h>\n-#include <rte_malloc.h>\n-#include <rte_string_fns.h>\n-#include <rte_debug.h>\n-#include <rte_devargs.h>\n-\n-#include \"eal_filesystem.h\"\n-#include \"eal_private.h\"\n-\n-/**\n- * @file\n- * PCI probing under linux\n- *\n- * This code is used to simulate a PCI probe by parsing information in\n- * sysfs. Moreover, when a registered driver matches a device, the\n- * kernel driver currently using it is unloaded and replaced by\n- * igb_uio module, which is a very minimal userland driver for Intel\n- * network card, only providing access to PCI BAR to applications, and\n- * enabling bus master.\n- */\n-\n-extern struct rte_pci_bus rte_pci_bus;\n-\n-/* Map pci device */\n-int\n-rte_pci_map_device(struct rte_pci_device *dev)\n-{\n-\tint ret = -1;\n-\n-\t/* try mapping the NIC resources */\n-\tswitch (dev->kdrv) {\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\t/* map resources for devices that use uio */\n-\t\tret = pci_uio_map_resource(dev);\n-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n-\t\tret = 1;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n-}\n-\n-/* Unmap pci device */\n-void\n-rte_pci_unmap_device(struct rte_pci_device *dev)\n-{\n-\t/* try unmapping the NIC resources */\n-\tswitch (dev->kdrv) {\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\t/* unmap resources for devices that use uio */\n-\t\tpci_uio_unmap_resource(dev);\n-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n-\t\tbreak;\n-\t}\n-}\n-\n-void\n-pci_uio_free_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource *uio_res)\n-{\n-\trte_free(uio_res);\n-\n-\tif (dev->intr_handle.fd) {\n-\t\tclose(dev->intr_handle.fd);\n-\t\tdev->intr_handle.fd = -1;\n-\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-\t}\n-}\n-\n-int\n-pci_uio_alloc_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource **uio_res)\n-{\n-\tchar devname[PATH_MAX]; /* contains the /dev/uioX */\n-\tstruct rte_pci_addr *loc;\n-\n-\tloc = &dev->addr;\n-\n-\tsnprintf(devname, sizeof(devname), \"/dev/uio@pci:%u:%u:%u\",\n-\t\t\tdev->addr.bus, dev->addr.devid, dev->addr.function);\n-\n-\tif (access(devname, O_RDWR) < 0) {\n-\t\tRTE_LOG(WARNING, EAL, \"  \"PCI_PRI_FMT\" not managed by UIO driver, \"\n-\t\t\t\t\"skipping\\n\", loc->domain, loc->bus, loc->devid, loc->function);\n-\t\treturn 1;\n-\t}\n-\n-\t/* save fd if in primary process */\n-\tdev->intr_handle.fd = open(devname, O_RDWR);\n-\tif (dev->intr_handle.fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\tdevname, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n-\n-\t/* allocate the mapping details for secondary processes*/\n-\t*uio_res = rte_zmalloc(\"UIO_RES\", sizeof(**uio_res), 0);\n-\tif (*uio_res == NULL) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tsnprintf((*uio_res)->path, sizeof((*uio_res)->path), \"%s\", devname);\n-\tmemcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));\n-\n-\treturn 0;\n-\n-error:\n-\tpci_uio_free_resource(dev, *uio_res);\n-\treturn -1;\n-}\n-\n-int\n-pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n-\t\tstruct mapped_pci_resource *uio_res, int map_idx)\n-{\n-\tint fd;\n-\tchar *devname;\n-\tvoid *mapaddr;\n-\tuint64_t offset;\n-\tuint64_t pagesz;\n-\tstruct pci_map *maps;\n-\n-\tmaps = uio_res->maps;\n-\tdevname = uio_res->path;\n-\tpagesz = sysconf(_SC_PAGESIZE);\n-\n-\t/* allocate memory to keep path */\n-\tmaps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0);\n-\tif (maps[map_idx].path == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot allocate memory for path: %s\\n\",\n-\t\t\t\tstrerror(errno));\n-\t\treturn -1;\n-\t}\n-\n-\t/*\n-\t * open resource file, to mmap it\n-\t */\n-\tfd = open(devname, O_RDWR);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\t\tdevname, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\t/* if matching map is found, then use it */\n-\toffset = res_idx * pagesz;\n-\tmapaddr = pci_map_resource(NULL, fd, (off_t)offset,\n-\t\t\t(size_t)dev->mem_resource[res_idx].len, 0);\n-\tclose(fd);\n-\tif (mapaddr == MAP_FAILED)\n-\t\tgoto error;\n-\n-\tmaps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;\n-\tmaps[map_idx].size = dev->mem_resource[res_idx].len;\n-\tmaps[map_idx].addr = mapaddr;\n-\tmaps[map_idx].offset = offset;\n-\tstrcpy(maps[map_idx].path, devname);\n-\tdev->mem_resource[res_idx].addr = mapaddr;\n-\n-\treturn 0;\n-\n-error:\n-\trte_free(maps[map_idx].path);\n-\treturn -1;\n-}\n-\n-static int\n-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)\n-{\n-\tstruct rte_pci_device *dev;\n-\tstruct pci_bar_io bar;\n-\tunsigned i, max;\n-\n-\tdev = malloc(sizeof(*dev));\n-\tif (dev == NULL) {\n-\t\treturn -1;\n-\t}\n-\n-\tmemset(dev, 0, sizeof(*dev));\n-\tdev->addr.domain = conf->pc_sel.pc_domain;\n-\tdev->addr.bus = conf->pc_sel.pc_bus;\n-\tdev->addr.devid = conf->pc_sel.pc_dev;\n-\tdev->addr.function = conf->pc_sel.pc_func;\n-\n-\t/* get vendor id */\n-\tdev->id.vendor_id = conf->pc_vendor;\n-\n-\t/* get device id */\n-\tdev->id.device_id = conf->pc_device;\n-\n-\t/* get subsystem_vendor id */\n-\tdev->id.subsystem_vendor_id = conf->pc_subvendor;\n-\n-\t/* get subsystem_device id */\n-\tdev->id.subsystem_device_id = conf->pc_subdevice;\n-\n-\t/* get class id */\n-\tdev->id.class_id = (conf->pc_class << 16) |\n-\t\t\t   (conf->pc_subclass << 8) |\n-\t\t\t   (conf->pc_progif);\n-\n-\t/* TODO: get max_vfs */\n-\tdev->max_vfs = 0;\n-\n-\t/* FreeBSD has no NUMA support (yet) */\n-\tdev->device.numa_node = 0;\n-\n-\tpci_name_set(dev);\n-\n-\t/* FreeBSD has only one pass through driver */\n-\tdev->kdrv = RTE_KDRV_NIC_UIO;\n-\n-\t/* parse resources */\n-\tswitch (conf->pc_hdr & PCIM_HDRTYPE) {\n-\tcase PCIM_HDRTYPE_NORMAL:\n-\t\tmax = PCIR_MAX_BAR_0;\n-\t\tbreak;\n-\tcase PCIM_HDRTYPE_BRIDGE:\n-\t\tmax = PCIR_MAX_BAR_1;\n-\t\tbreak;\n-\tcase PCIM_HDRTYPE_CARDBUS:\n-\t\tmax = PCIR_MAX_BAR_2;\n-\t\tbreak;\n-\tdefault:\n-\t\tgoto skipdev;\n-\t}\n-\n-\tfor (i = 0; i <= max; i++) {\n-\t\tbar.pbi_sel = conf->pc_sel;\n-\t\tbar.pbi_reg = PCIR_BAR(i);\n-\t\tif (ioctl(dev_pci_fd, PCIOCGETBAR, &bar) < 0)\n-\t\t\tcontinue;\n-\n-\t\tdev->mem_resource[i].len = bar.pbi_length;\n-\t\tif (PCI_BAR_IO(bar.pbi_base)) {\n-\t\t\tdev->mem_resource[i].addr = (void *)(bar.pbi_base & ~((uint64_t)0xf));\n-\t\t\tcontinue;\n-\t\t}\n-\t\tdev->mem_resource[i].phys_addr = bar.pbi_base & ~((uint64_t)0xf);\n-\t}\n-\n-\t/* device is valid, add in list (sorted) */\n-\tif (TAILQ_EMPTY(&rte_pci_bus.device_list)) {\n-\t\trte_pci_add_device(dev);\n-\t}\n-\telse {\n-\t\tstruct rte_pci_device *dev2 = NULL;\n-\t\tint ret;\n-\n-\t\tTAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {\n-\t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n-\t\t\tif (ret > 0)\n-\t\t\t\tcontinue;\n-\t\t\telse if (ret < 0) {\n-\t\t\t\trte_pci_insert_device(dev2, dev);\n-\t\t\t} else { /* already registered */\n-\t\t\t\tdev2->kdrv = dev->kdrv;\n-\t\t\t\tdev2->max_vfs = dev->max_vfs;\n-\t\t\t\tpci_name_set(dev2);\n-\t\t\t\tmemmove(dev2->mem_resource,\n-\t\t\t\t\tdev->mem_resource,\n-\t\t\t\t\tsizeof(dev->mem_resource));\n-\t\t\t\tfree(dev);\n-\t\t\t}\n-\t\t\treturn 0;\n-\t\t}\n-\t\trte_pci_add_device(dev);\n-\t}\n-\n-\treturn 0;\n-\n-skipdev:\n-\tfree(dev);\n-\treturn 0;\n-}\n-\n-/*\n- * Scan the content of the PCI bus, and add the devices in the devices\n- * list. Call pci_scan_one() for each pci entry found.\n- */\n-int\n-rte_pci_scan(void)\n-{\n-\tint fd;\n-\tunsigned dev_count = 0;\n-\tstruct pci_conf matches[16];\n-\tstruct pci_conf_io conf_io = {\n-\t\t\t.pat_buf_len = 0,\n-\t\t\t.num_patterns = 0,\n-\t\t\t.patterns = NULL,\n-\t\t\t.match_buf_len = sizeof(matches),\n-\t\t\t.matches = &matches[0],\n-\t};\n-\n-\t/* for debug purposes, PCI can be disabled */\n-\tif (internal_config.no_pci)\n-\t\treturn 0;\n-\n-\tfd = open(\"/dev/pci\", O_RDONLY);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tdo {\n-\t\tunsigned i;\n-\t\tif (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"%s(): error with ioctl on /dev/pci: %s\\n\",\n-\t\t\t\t\t__func__, strerror(errno));\n-\t\t\tgoto error;\n-\t\t}\n-\n-\t\tfor (i = 0; i < conf_io.num_matches; i++)\n-\t\t\tif (pci_scan_one(fd, &matches[i]) < 0)\n-\t\t\t\tgoto error;\n-\n-\t\tdev_count += conf_io.num_matches;\n-\t} while(conf_io.status == PCI_GETCONF_MORE_DEVS);\n-\n-\tclose(fd);\n-\n-\tRTE_LOG(DEBUG, EAL, \"PCI scan found %u devices\\n\", dev_count);\n-\treturn 0;\n-\n-error:\n-\tif (fd >= 0)\n-\t\tclose(fd);\n-\treturn -1;\n-}\n-\n-int\n-pci_update_device(const struct rte_pci_addr *addr)\n-{\n-\tint fd;\n-\tstruct pci_conf matches[2];\n-\tstruct pci_match_conf match = {\n-\t\t.pc_sel = {\n-\t\t\t.pc_domain = addr->domain,\n-\t\t\t.pc_bus = addr->bus,\n-\t\t\t.pc_dev = addr->devid,\n-\t\t\t.pc_func = addr->function,\n-\t\t},\n-\t};\n-\tstruct pci_conf_io conf_io = {\n-\t\t.pat_buf_len = 0,\n-\t\t.num_patterns = 1,\n-\t\t.patterns = &match,\n-\t\t.match_buf_len = sizeof(matches),\n-\t\t.matches = &matches[0],\n-\t};\n-\n-\tfd = open(\"/dev/pci\", O_RDONLY);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tif (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error with ioctl on /dev/pci: %s\\n\",\n-\t\t\t\t__func__, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\tif (conf_io.num_matches != 1)\n-\t\tgoto error;\n-\n-\tif (pci_scan_one(fd, &matches[0]) < 0)\n-\t\tgoto error;\n-\n-\tclose(fd);\n-\n-\treturn 0;\n-\n-error:\n-\tif (fd >= 0)\n-\t\tclose(fd);\n-\treturn -1;\n-}\n-\n-/* Read PCI config space. */\n-int rte_pci_read_config(const struct rte_pci_device *dev,\n-\t\tvoid *buf, size_t len, off_t offset)\n-{\n-\tint fd = -1;\n-\tint size;\n-\tstruct pci_io pi = {\n-\t\t.pi_sel = {\n-\t\t\t.pc_domain = dev->addr.domain,\n-\t\t\t.pc_bus = dev->addr.bus,\n-\t\t\t.pc_dev = dev->addr.devid,\n-\t\t\t.pc_func = dev->addr.function,\n-\t\t},\n-\t\t.pi_reg = offset,\n-\t};\n-\n-\tfd = open(\"/dev/pci\", O_RDWR);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\twhile (len > 0) {\n-\t\tsize = (len >= 4) ? 4 : ((len >= 2) ? 2 : 1);\n-\t\tpi.pi_width = size;\n-\n-\t\tif (ioctl(fd, PCIOCREAD, &pi) < 0)\n-\t\t\tgoto error;\n-\t\tmemcpy(buf, &pi.pi_data, size);\n-\n-\t\tbuf = (char *)buf + size;\n-\t\tpi.pi_reg += size;\n-\t\tlen -= size;\n-\t}\n-\tclose(fd);\n-\n-\treturn 0;\n-\n- error:\n-\tif (fd >= 0)\n-\t\tclose(fd);\n-\treturn -1;\n-}\n-\n-/* Write PCI config space. */\n-int rte_pci_write_config(const struct rte_pci_device *dev,\n-\t\tconst void *buf, size_t len, off_t offset)\n-{\n-\tint fd = -1;\n-\n-\tstruct pci_io pi = {\n-\t\t.pi_sel = {\n-\t\t\t.pc_domain = dev->addr.domain,\n-\t\t\t.pc_bus = dev->addr.bus,\n-\t\t\t.pc_dev = dev->addr.devid,\n-\t\t\t.pc_func = dev->addr.function,\n-\t\t},\n-\t\t.pi_reg = offset,\n-\t\t.pi_data = *(const uint32_t *)buf,\n-\t\t.pi_width = len,\n-\t};\n-\n-\tif (len == 3 || len > sizeof(pi.pi_data)) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): invalid pci read length\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tmemcpy(&pi.pi_data, buf, len);\n-\n-\tfd = open(\"/dev/pci\", O_RDWR);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): error opening /dev/pci\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tif (ioctl(fd, PCIOCWRITE, &pi) < 0)\n-\t\tgoto error;\n-\n-\tclose(fd);\n-\treturn 0;\n-\n- error:\n-\tif (fd >= 0)\n-\t\tclose(fd);\n-\treturn -1;\n-}\n-\n-int\n-rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\tstruct rte_pci_ioport *p)\n-{\n-\tint ret;\n-\n-\tswitch (dev->kdrv) {\n-#if defined(RTE_ARCH_X86)\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\tif ((uintptr_t) dev->mem_resource[bar].addr <= UINT16_MAX) {\n-\t\t\tp->base = (uintptr_t)dev->mem_resource[bar].addr;\n-\t\t\tret = 0;\n-\t\t} else\n-\t\t\tret = -1;\n-\t\tbreak;\n-#endif\n-\tdefault:\n-\t\tret = -1;\n-\t\tbreak;\n-\t}\n-\n-\tif (!ret)\n-\t\tp->dev = dev;\n-\n-\treturn ret;\n-}\n-\n-static void\n-pci_uio_ioport_read(struct rte_pci_ioport *p,\n-\t\tvoid *data, size_t len, off_t offset)\n-{\n-#if defined(RTE_ARCH_X86)\n-\tuint8_t *d;\n-\tint size;\n-\tunsigned short reg = p->base + offset;\n-\n-\tfor (d = data; len > 0; d += size, reg += size, len -= size) {\n-\t\tif (len >= 4) {\n-\t\t\tsize = 4;\n-\t\t\t*(uint32_t *)d = inl(reg);\n-\t\t} else if (len >= 2) {\n-\t\t\tsize = 2;\n-\t\t\t*(uint16_t *)d = inw(reg);\n-\t\t} else {\n-\t\t\tsize = 1;\n-\t\t\t*d = inb(reg);\n-\t\t}\n-\t}\n-#else\n-\tRTE_SET_USED(p);\n-\tRTE_SET_USED(data);\n-\tRTE_SET_USED(len);\n-\tRTE_SET_USED(offset);\n-#endif\n-}\n-\n-void\n-rte_pci_ioport_read(struct rte_pci_ioport *p,\n-\t\tvoid *data, size_t len, off_t offset)\n-{\n-\tswitch (p->dev->kdrv) {\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\tpci_uio_ioport_read(p, data, len, offset);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n-static void\n-pci_uio_ioport_write(struct rte_pci_ioport *p,\n-\t\tconst void *data, size_t len, off_t offset)\n-{\n-#if defined(RTE_ARCH_X86)\n-\tconst uint8_t *s;\n-\tint size;\n-\tunsigned short reg = p->base + offset;\n-\n-\tfor (s = data; len > 0; s += size, reg += size, len -= size) {\n-\t\tif (len >= 4) {\n-\t\t\tsize = 4;\n-\t\t\toutl(reg, *(const uint32_t *)s);\n-\t\t} else if (len >= 2) {\n-\t\t\tsize = 2;\n-\t\t\toutw(reg, *(const uint16_t *)s);\n-\t\t} else {\n-\t\t\tsize = 1;\n-\t\t\toutb(reg, *s);\n-\t\t}\n-\t}\n-#else\n-\tRTE_SET_USED(p);\n-\tRTE_SET_USED(data);\n-\tRTE_SET_USED(len);\n-\tRTE_SET_USED(offset);\n-#endif\n-}\n-\n-void\n-rte_pci_ioport_write(struct rte_pci_ioport *p,\n-\t\tconst void *data, size_t len, off_t offset)\n-{\n-\tswitch (p->dev->kdrv) {\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\tpci_uio_ioport_write(p, data, len, offset);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n-int\n-rte_pci_ioport_unmap(struct rte_pci_ioport *p)\n-{\n-\tint ret;\n-\n-\tswitch (p->dev->kdrv) {\n-#if defined(RTE_ARCH_X86)\n-\tcase RTE_KDRV_NIC_UIO:\n-\t\tret = 0;\n-\t\tbreak;\n-#endif\n-\tdefault:\n-\t\tret = -1;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n-}\ndiff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\nindex cff7d18..3ed3283 100644\n--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n@@ -169,21 +169,6 @@ DPDK_17.05 {\n \trte_log_set_global_level;\n \trte_log_set_level;\n \trte_log_set_level_regexp;\n-\trte_pci_detach;\n-\trte_pci_dump;\n-\trte_pci_ioport_map;\n-\trte_pci_ioport_read;\n-\trte_pci_ioport_unmap;\n-\trte_pci_ioport_write;\n-\trte_pci_map_device;\n-\trte_pci_probe;\n-\trte_pci_probe_one;\n-\trte_pci_read_config;\n-\trte_pci_register;\n-\trte_pci_scan;\n-\trte_pci_unmap_device;\n-\trte_pci_unregister;\n-\trte_pci_write_config;\n \trte_vdev_init;\n \trte_vdev_register;\n \trte_vdev_uninit;\ndiff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile\nindex e8fd67a..ac8d3bb 100644\n--- a/lib/librte_eal/common/Makefile\n+++ b/lib/librte_eal/common/Makefile\n@@ -33,7 +33,7 @@ include $(RTE_SDK)/mk/rte.vars.mk\n \n INC := rte_branch_prediction.h rte_common.h\n INC += rte_debug.h rte_eal.h rte_errno.h rte_launch.h rte_lcore.h\n-INC += rte_log.h rte_memory.h rte_memzone.h rte_pci.h\n+INC += rte_log.h rte_memory.h rte_memzone.h\n INC += rte_per_lcore.h rte_random.h\n INC += rte_tailq.h rte_interrupts.h rte_alarm.h\n INC += rte_string_fns.h rte_version.h\ndiff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c\ndeleted file mode 100644\nindex 52fd38c..0000000\n--- a/lib/librte_eal/common/eal_common_pci.c\n+++ /dev/null\n@@ -1,580 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n- *   Copyright 2013-2014 6WIND S.A.\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-\n-#include <string.h>\n-#include <inttypes.h>\n-#include <stdint.h>\n-#include <stdlib.h>\n-#include <stdio.h>\n-#include <sys/queue.h>\n-#include <sys/mman.h>\n-\n-#include <rte_errno.h>\n-#include <rte_interrupts.h>\n-#include <rte_log.h>\n-#include <rte_bus.h>\n-#include <rte_pci.h>\n-#include <rte_per_lcore.h>\n-#include <rte_memory.h>\n-#include <rte_memzone.h>\n-#include <rte_eal.h>\n-#include <rte_string_fns.h>\n-#include <rte_common.h>\n-#include <rte_devargs.h>\n-\n-#include \"eal_private.h\"\n-\n-extern struct rte_pci_bus rte_pci_bus;\n-\n-#define SYSFS_PCI_DEVICES \"/sys/bus/pci/devices\"\n-\n-const char *pci_get_sysfs_path(void)\n-{\n-\tconst char *path = NULL;\n-\n-\tpath = getenv(\"SYSFS_PCI_DEVICES\");\n-\tif (path == NULL)\n-\t\treturn SYSFS_PCI_DEVICES;\n-\n-\treturn path;\n-}\n-\n-static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)\n-{\n-\tstruct rte_devargs *devargs;\n-\tstruct rte_pci_addr addr;\n-\tstruct rte_bus *pbus;\n-\n-\tpbus = rte_bus_find_by_name(\"pci\");\n-\tTAILQ_FOREACH(devargs, &devargs_list, next) {\n-\t\tif (devargs->bus != pbus)\n-\t\t\tcontinue;\n-\t\tdevargs->bus->parse(devargs->name, &addr);\n-\t\tif (!rte_eal_compare_pci_addr(&dev->addr, &addr))\n-\t\t\treturn devargs;\n-\t}\n-\treturn NULL;\n-}\n-\n-void\n-pci_name_set(struct rte_pci_device *dev)\n-{\n-\tstruct rte_devargs *devargs;\n-\n-\t/* Each device has its internal, canonical name set. */\n-\trte_pci_device_name(&dev->addr,\n-\t\t\tdev->name, sizeof(dev->name));\n-\tdevargs = pci_devargs_lookup(dev);\n-\tdev->device.devargs = devargs;\n-\t/* In blacklist mode, if the device is not blacklisted, no\n-\t * rte_devargs exists for it.\n-\t */\n-\tif (devargs != NULL)\n-\t\t/* If an rte_devargs exists, the generic rte_device uses the\n-\t\t * given name as its namea\n-\t\t */\n-\t\tdev->device.name = dev->device.devargs->name;\n-\telse\n-\t\t/* Otherwise, it uses the internal, canonical form. */\n-\t\tdev->device.name = dev->name;\n-}\n-\n-/* map a particular resource from a file */\n-void *\n-pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size,\n-\t\t int additional_flags)\n-{\n-\tvoid *mapaddr;\n-\n-\t/* Map the PCI memory resource of device */\n-\tmapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,\n-\t\t\tMAP_SHARED | additional_flags, fd, offset);\n-\tif (mapaddr == MAP_FAILED) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\\n\",\n-\t\t\t__func__, fd, requested_addr,\n-\t\t\t(unsigned long)size, (unsigned long)offset,\n-\t\t\tstrerror(errno), mapaddr);\n-\t} else\n-\t\tRTE_LOG(DEBUG, EAL, \"  PCI memory mapped at %p\\n\", mapaddr);\n-\n-\treturn mapaddr;\n-}\n-\n-/* unmap a particular resource */\n-void\n-pci_unmap_resource(void *requested_addr, size_t size)\n-{\n-\tif (requested_addr == NULL)\n-\t\treturn;\n-\n-\t/* Unmap the PCI memory resource of device */\n-\tif (munmap(requested_addr, size)) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot munmap(%p, 0x%lx): %s\\n\",\n-\t\t\t__func__, requested_addr, (unsigned long)size,\n-\t\t\tstrerror(errno));\n-\t} else\n-\t\tRTE_LOG(DEBUG, EAL, \"  PCI memory unmapped at %p\\n\",\n-\t\t\t\trequested_addr);\n-}\n-\n-/*\n- * Match the PCI Driver and Device using the ID Table\n- *\n- * @param pci_drv\n- *\tPCI driver from which ID table would be extracted\n- * @param pci_dev\n- *\tPCI device to match against the driver\n- * @return\n- *\t1 for successful match\n- *\t0 for unsuccessful match\n- */\n-static int\n-rte_pci_match(const struct rte_pci_driver *pci_drv,\n-\t      const struct rte_pci_device *pci_dev)\n-{\n-\tconst struct rte_pci_id *id_table;\n-\n-\tfor (id_table = pci_drv->id_table; id_table->vendor_id != 0;\n-\t     id_table++) {\n-\t\t/* check if device's identifiers match the driver's ones */\n-\t\tif (id_table->vendor_id != pci_dev->id.vendor_id &&\n-\t\t\t\tid_table->vendor_id != PCI_ANY_ID)\n-\t\t\tcontinue;\n-\t\tif (id_table->device_id != pci_dev->id.device_id &&\n-\t\t\t\tid_table->device_id != PCI_ANY_ID)\n-\t\t\tcontinue;\n-\t\tif (id_table->subsystem_vendor_id !=\n-\t\t    pci_dev->id.subsystem_vendor_id &&\n-\t\t    id_table->subsystem_vendor_id != PCI_ANY_ID)\n-\t\t\tcontinue;\n-\t\tif (id_table->subsystem_device_id !=\n-\t\t    pci_dev->id.subsystem_device_id &&\n-\t\t    id_table->subsystem_device_id != PCI_ANY_ID)\n-\t\t\tcontinue;\n-\t\tif (id_table->class_id != pci_dev->id.class_id &&\n-\t\t\t\tid_table->class_id != RTE_CLASS_ANY_ID)\n-\t\t\tcontinue;\n-\n-\t\treturn 1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/*\n- * If vendor/device ID match, call the probe() function of the\n- * driver.\n- */\n-static int\n-rte_pci_probe_one_driver(struct rte_pci_driver *dr,\n-\t\t\t struct rte_pci_device *dev)\n-{\n-\tint ret;\n-\tstruct rte_pci_addr *loc;\n-\n-\tif ((dr == NULL) || (dev == NULL))\n-\t\treturn -EINVAL;\n-\n-\tloc = &dev->addr;\n-\n-\t/* The device is not blacklisted; Check if driver supports it */\n-\tif (!rte_pci_match(dr, dev))\n-\t\t/* Match of device and driver failed */\n-\t\treturn 1;\n-\n-\tRTE_LOG(INFO, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n-\t\t\tloc->domain, loc->bus, loc->devid, loc->function,\n-\t\t\tdev->device.numa_node);\n-\n-\t/* no initialization when blacklisted, return without error */\n-\tif (dev->device.devargs != NULL &&\n-\t\tdev->device.devargs->policy ==\n-\t\t\tRTE_DEV_BLACKLISTED) {\n-\t\tRTE_LOG(INFO, EAL, \"  Device is blacklisted, not\"\n-\t\t\t\" initializing\\n\");\n-\t\treturn 1;\n-\t}\n-\n-\tif (dev->device.numa_node < 0) {\n-\t\tRTE_LOG(WARNING, EAL, \"  Invalid NUMA socket, default to 0\\n\");\n-\t\tdev->device.numa_node = 0;\n-\t}\n-\n-\tRTE_LOG(INFO, EAL, \"  probe driver: %x:%x %s\\n\", dev->id.vendor_id,\n-\t\tdev->id.device_id, dr->driver.name);\n-\n-\tif (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {\n-\t\t/* map resources for devices that use igb_uio */\n-\t\tret = rte_pci_map_device(dev);\n-\t\tif (ret != 0)\n-\t\t\treturn ret;\n-\t}\n-\n-\t/* reference driver structure */\n-\tdev->driver = dr;\n-\tdev->device.driver = &dr->driver;\n-\n-\t/* call the driver probe() function */\n-\tret = dr->probe(dr, dev);\n-\tif (ret) {\n-\t\tdev->driver = NULL;\n-\t\tdev->device.driver = NULL;\n-\t\tif ((dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) &&\n-\t\t\t/* Don't unmap if device is unsupported and\n-\t\t\t * driver needs mapped resources.\n-\t\t\t */\n-\t\t\t!(ret > 0 &&\n-\t\t\t\t(dr->drv_flags & RTE_PCI_DRV_KEEP_MAPPED_RES)))\n-\t\t\trte_pci_unmap_device(dev);\n-\t}\n-\n-\treturn ret;\n-}\n-\n-/*\n- * If vendor/device ID match, call the remove() function of the\n- * driver.\n- */\n-static int\n-rte_pci_detach_dev(struct rte_pci_device *dev)\n-{\n-\tstruct rte_pci_addr *loc;\n-\tstruct rte_pci_driver *dr;\n-\n-\tif (dev == NULL)\n-\t\treturn -EINVAL;\n-\n-\tdr = dev->driver;\n-\tloc = &dev->addr;\n-\n-\tRTE_LOG(DEBUG, EAL, \"PCI device \"PCI_PRI_FMT\" on NUMA socket %i\\n\",\n-\t\t\tloc->domain, loc->bus, loc->devid,\n-\t\t\tloc->function, dev->device.numa_node);\n-\n-\tRTE_LOG(DEBUG, EAL, \"  remove driver: %x:%x %s\\n\", dev->id.vendor_id,\n-\t\t\tdev->id.device_id, dr->driver.name);\n-\n-\tif (dr->remove && (dr->remove(dev) < 0))\n-\t\treturn -1;\t/* negative value is an error */\n-\n-\t/* clear driver structure */\n-\tdev->driver = NULL;\n-\n-\tif (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)\n-\t\t/* unmap resources for devices that use igb_uio */\n-\t\trte_pci_unmap_device(dev);\n-\n-\treturn 0;\n-}\n-\n-/*\n- * If vendor/device ID match, call the probe() function of all\n- * registered driver for the given device. Return -1 if initialization\n- * failed, return 1 if no driver is found for this device.\n- */\n-static int\n-pci_probe_all_drivers(struct rte_pci_device *dev)\n-{\n-\tstruct rte_pci_driver *dr = NULL;\n-\tint rc = 0;\n-\n-\tif (dev == NULL)\n-\t\treturn -1;\n-\n-\t/* Check if a driver is already loaded */\n-\tif (dev->driver != NULL)\n-\t\treturn 0;\n-\n-\tFOREACH_DRIVER_ON_PCIBUS(dr) {\n-\t\trc = rte_pci_probe_one_driver(dr, dev);\n-\t\tif (rc < 0)\n-\t\t\t/* negative value is an error */\n-\t\t\treturn -1;\n-\t\tif (rc > 0)\n-\t\t\t/* positive value means driver doesn't support it */\n-\t\t\tcontinue;\n-\t\treturn 0;\n-\t}\n-\treturn 1;\n-}\n-\n-/*\n- * Find the pci device specified by pci address, then invoke probe function of\n- * the driver of the device.\n- */\n-int\n-rte_pci_probe_one(const struct rte_pci_addr *addr)\n-{\n-\tstruct rte_pci_device *dev = NULL;\n-\n-\tint ret = 0;\n-\n-\tif (addr == NULL)\n-\t\treturn -1;\n-\n-\t/* update current pci device in global list, kernel bindings might have\n-\t * changed since last time we looked at it.\n-\t */\n-\tif (pci_update_device(addr) < 0)\n-\t\tgoto err_return;\n-\n-\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n-\t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n-\t\t\tcontinue;\n-\n-\t\tret = pci_probe_all_drivers(dev);\n-\t\tif (ret)\n-\t\t\tgoto err_return;\n-\t\treturn 0;\n-\t}\n-\treturn -1;\n-\n-err_return:\n-\tRTE_LOG(WARNING, EAL,\n-\t\t\"Requested device \" PCI_PRI_FMT \" cannot be used\\n\",\n-\t\taddr->domain, addr->bus, addr->devid, addr->function);\n-\treturn -1;\n-}\n-\n-/*\n- * Detach device specified by its pci address.\n- */\n-int\n-rte_pci_detach(const struct rte_pci_addr *addr)\n-{\n-\tstruct rte_pci_device *dev = NULL;\n-\tint ret = 0;\n-\n-\tif (addr == NULL)\n-\t\treturn -1;\n-\n-\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n-\t\tif (rte_eal_compare_pci_addr(&dev->addr, addr))\n-\t\t\tcontinue;\n-\n-\t\tret = rte_pci_detach_dev(dev);\n-\t\tif (ret < 0)\n-\t\t\t/* negative value is an error */\n-\t\t\tgoto err_return;\n-\t\tif (ret > 0)\n-\t\t\t/* positive value means driver doesn't support it */\n-\t\t\tcontinue;\n-\n-\t\trte_pci_remove_device(dev);\n-\t\tfree(dev);\n-\t\treturn 0;\n-\t}\n-\treturn -1;\n-\n-err_return:\n-\tRTE_LOG(WARNING, EAL, \"Requested device \" PCI_PRI_FMT\n-\t\t\t\" cannot be used\\n\", dev->addr.domain, dev->addr.bus,\n-\t\t\tdev->addr.devid, dev->addr.function);\n-\treturn -1;\n-}\n-\n-/*\n- * Scan the content of the PCI bus, and call the probe() function for\n- * all registered drivers that have a matching entry in its id_table\n- * for discovered devices.\n- */\n-int\n-rte_pci_probe(void)\n-{\n-\tstruct rte_pci_device *dev = NULL;\n-\tsize_t probed = 0, failed = 0;\n-\tstruct rte_devargs *devargs;\n-\tint probe_all = 0;\n-\tint ret = 0;\n-\n-\tif (rte_pci_bus.bus.conf.scan_mode != RTE_BUS_SCAN_WHITELIST)\n-\t\tprobe_all = 1;\n-\n-\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n-\t\tprobed++;\n-\n-\t\tdevargs = dev->device.devargs;\n-\t\t/* probe all or only whitelisted devices */\n-\t\tif (probe_all)\n-\t\t\tret = pci_probe_all_drivers(dev);\n-\t\telse if (devargs != NULL &&\n-\t\t\tdevargs->policy == RTE_DEV_WHITELISTED)\n-\t\t\tret = pci_probe_all_drivers(dev);\n-\t\tif (ret < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Requested device \" PCI_PRI_FMT\n-\t\t\t\t \" cannot be used\\n\", dev->addr.domain, dev->addr.bus,\n-\t\t\t\t dev->addr.devid, dev->addr.function);\n-\t\t\trte_errno = errno;\n-\t\t\tfailed++;\n-\t\t\tret = 0;\n-\t\t}\n-\t}\n-\n-\treturn (probed && probed == failed) ? -1 : 0;\n-}\n-\n-/* dump one device */\n-static int\n-pci_dump_one_device(FILE *f, struct rte_pci_device *dev)\n-{\n-\tint i;\n-\n-\tfprintf(f, PCI_PRI_FMT, dev->addr.domain, dev->addr.bus,\n-\t       dev->addr.devid, dev->addr.function);\n-\tfprintf(f, \" - vendor:%x device:%x\\n\", dev->id.vendor_id,\n-\t       dev->id.device_id);\n-\n-\tfor (i = 0; i != sizeof(dev->mem_resource) /\n-\t\tsizeof(dev->mem_resource[0]); i++) {\n-\t\tfprintf(f, \"   %16.16\"PRIx64\" %16.16\"PRIx64\"\\n\",\n-\t\t\tdev->mem_resource[i].phys_addr,\n-\t\t\tdev->mem_resource[i].len);\n-\t}\n-\treturn 0;\n-}\n-\n-/* dump devices on the bus */\n-void\n-rte_pci_dump(FILE *f)\n-{\n-\tstruct rte_pci_device *dev = NULL;\n-\n-\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n-\t\tpci_dump_one_device(f, dev);\n-\t}\n-}\n-\n-static int\n-pci_parse(const char *name, void *addr)\n-{\n-\tstruct rte_pci_addr *out = addr;\n-\tstruct rte_pci_addr pci_addr;\n-\tbool parse;\n-\n-\tparse = (eal_parse_pci_BDF(name, &pci_addr) == 0 ||\n-\t\t eal_parse_pci_DomBDF(name, &pci_addr) == 0);\n-\tif (parse && addr != NULL)\n-\t\t*out = pci_addr;\n-\treturn parse == false;\n-}\n-\n-/* register a driver */\n-void\n-rte_pci_register(struct rte_pci_driver *driver)\n-{\n-\tTAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);\n-\tdriver->bus = &rte_pci_bus;\n-}\n-\n-/* unregister a driver */\n-void\n-rte_pci_unregister(struct rte_pci_driver *driver)\n-{\n-\tTAILQ_REMOVE(&rte_pci_bus.driver_list, driver, next);\n-\tdriver->bus = NULL;\n-}\n-\n-/* Add a device to PCI bus */\n-void\n-rte_pci_add_device(struct rte_pci_device *pci_dev)\n-{\n-\tTAILQ_INSERT_TAIL(&rte_pci_bus.device_list, pci_dev, next);\n-}\n-\n-/* Insert a device into a predefined position in PCI bus */\n-void\n-rte_pci_insert_device(struct rte_pci_device *exist_pci_dev,\n-\t\t      struct rte_pci_device *new_pci_dev)\n-{\n-\tTAILQ_INSERT_BEFORE(exist_pci_dev, new_pci_dev, next);\n-}\n-\n-/* Remove a device from PCI bus */\n-void\n-rte_pci_remove_device(struct rte_pci_device *pci_dev)\n-{\n-\tTAILQ_REMOVE(&rte_pci_bus.device_list, pci_dev, next);\n-}\n-\n-static struct rte_device *\n-pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,\n-\t\tconst void *data)\n-{\n-\tstruct rte_pci_device *dev;\n-\n-\tFOREACH_DEVICE_ON_PCIBUS(dev) {\n-\t\tif (start && &dev->device == start) {\n-\t\t\tstart = NULL; /* starting point found */\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (cmp(&dev->device, data) == 0)\n-\t\t\treturn &dev->device;\n-\t}\n-\n-\treturn NULL;\n-}\n-\n-static int\n-pci_plug(struct rte_device *dev)\n-{\n-\treturn pci_probe_all_drivers(RTE_DEV_TO_PCI(dev));\n-}\n-\n-static int\n-pci_unplug(struct rte_device *dev)\n-{\n-\tstruct rte_pci_device *pdev;\n-\tint ret;\n-\n-\tpdev = RTE_DEV_TO_PCI(dev);\n-\tret = rte_pci_detach_dev(pdev);\n-\trte_pci_remove_device(pdev);\n-\tfree(pdev);\n-\treturn ret;\n-}\n-\n-struct rte_pci_bus rte_pci_bus = {\n-\t.bus = {\n-\t\t.scan = rte_pci_scan,\n-\t\t.probe = rte_pci_probe,\n-\t\t.find_device = pci_find_device,\n-\t\t.plug = pci_plug,\n-\t\t.unplug = pci_unplug,\n-\t\t.parse = pci_parse,\n-\t},\n-\t.device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list),\n-\t.driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),\n-};\n-\n-RTE_REGISTER_BUS(pci, rte_pci_bus.bus);\ndiff --git a/lib/librte_eal/common/eal_common_pci_uio.c b/lib/librte_eal/common/eal_common_pci_uio.c\ndeleted file mode 100644\nindex 367a681..0000000\n--- a/lib/librte_eal/common/eal_common_pci_uio.c\n+++ /dev/null\n@@ -1,233 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2015 Intel Corporation. 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-\n-#include <fcntl.h>\n-#include <string.h>\n-#include <unistd.h>\n-#include <sys/types.h>\n-#include <sys/stat.h>\n-#include <sys/mman.h>\n-\n-#include <rte_eal.h>\n-#include <rte_tailq.h>\n-#include <rte_log.h>\n-#include <rte_malloc.h>\n-\n-#include \"eal_private.h\"\n-\n-static struct rte_tailq_elem rte_uio_tailq = {\n-\t.name = \"UIO_RESOURCE_LIST\",\n-};\n-EAL_REGISTER_TAILQ(rte_uio_tailq)\n-\n-static int\n-pci_uio_map_secondary(struct rte_pci_device *dev)\n-{\n-\tint fd, i, j;\n-\tstruct mapped_pci_resource *uio_res;\n-\tstruct mapped_pci_res_list *uio_res_list =\n-\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n-\n-\tTAILQ_FOREACH(uio_res, uio_res_list, next) {\n-\n-\t\t/* skip this element if it doesn't match our PCI address */\n-\t\tif (rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))\n-\t\t\tcontinue;\n-\n-\t\tfor (i = 0; i != uio_res->nb_maps; i++) {\n-\t\t\t/*\n-\t\t\t * open devname, to mmap it\n-\t\t\t */\n-\t\t\tfd = open(uio_res->maps[i].path, O_RDWR);\n-\t\t\tif (fd < 0) {\n-\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\t\t\tuio_res->maps[i].path, strerror(errno));\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\tvoid *mapaddr = pci_map_resource(uio_res->maps[i].addr,\n-\t\t\t\t\tfd, (off_t)uio_res->maps[i].offset,\n-\t\t\t\t\t(size_t)uio_res->maps[i].size, 0);\n-\t\t\t/* fd is not needed in slave process, close it */\n-\t\t\tclose(fd);\n-\t\t\tif (mapaddr != uio_res->maps[i].addr) {\n-\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\"Cannot mmap device resource file %s to address: %p\\n\",\n-\t\t\t\t\tuio_res->maps[i].path,\n-\t\t\t\t\tuio_res->maps[i].addr);\n-\t\t\t\tif (mapaddr != MAP_FAILED) {\n-\t\t\t\t\t/* unmap addrs correctly mapped */\n-\t\t\t\t\tfor (j = 0; j < i; j++)\n-\t\t\t\t\t\tpci_unmap_resource(\n-\t\t\t\t\t\t\tuio_res->maps[j].addr,\n-\t\t\t\t\t\t\t(size_t)uio_res->maps[j].size);\n-\t\t\t\t\t/* unmap addr wrongly mapped */\n-\t\t\t\t\tpci_unmap_resource(mapaddr,\n-\t\t\t\t\t\t(size_t)uio_res->maps[i].size);\n-\t\t\t\t}\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\t\t}\n-\t\treturn 0;\n-\t}\n-\n-\tRTE_LOG(ERR, EAL, \"Cannot find resource for device\\n\");\n-\treturn 1;\n-}\n-\n-/* map the PCI resource of a PCI device in virtual memory */\n-int\n-pci_uio_map_resource(struct rte_pci_device *dev)\n-{\n-\tint i, map_idx = 0, ret;\n-\tuint64_t phaddr;\n-\tstruct mapped_pci_resource *uio_res = NULL;\n-\tstruct mapped_pci_res_list *uio_res_list =\n-\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n-\n-\tdev->intr_handle.fd = -1;\n-\tdev->intr_handle.uio_cfg_fd = -1;\n-\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-\n-\t/* secondary processes - use already recorded details */\n-\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n-\t\treturn pci_uio_map_secondary(dev);\n-\n-\t/* allocate uio resource */\n-\tret = pci_uio_alloc_resource(dev, &uio_res);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\t/* Map all BARs */\n-\tfor (i = 0; i != PCI_MAX_RESOURCE; i++) {\n-\t\t/* skip empty BAR */\n-\t\tphaddr = dev->mem_resource[i].phys_addr;\n-\t\tif (phaddr == 0)\n-\t\t\tcontinue;\n-\n-\t\tret = pci_uio_map_resource_by_index(dev, i,\n-\t\t\t\tuio_res, map_idx);\n-\t\tif (ret)\n-\t\t\tgoto error;\n-\n-\t\tmap_idx++;\n-\t}\n-\n-\tuio_res->nb_maps = map_idx;\n-\n-\tTAILQ_INSERT_TAIL(uio_res_list, uio_res, next);\n-\n-\treturn 0;\n-error:\n-\tfor (i = 0; i < map_idx; i++) {\n-\t\tpci_unmap_resource(uio_res->maps[i].addr,\n-\t\t\t\t(size_t)uio_res->maps[i].size);\n-\t\trte_free(uio_res->maps[i].path);\n-\t}\n-\tpci_uio_free_resource(dev, uio_res);\n-\treturn -1;\n-}\n-\n-static void\n-pci_uio_unmap(struct mapped_pci_resource *uio_res)\n-{\n-\tint i;\n-\n-\tif (uio_res == NULL)\n-\t\treturn;\n-\n-\tfor (i = 0; i != uio_res->nb_maps; i++) {\n-\t\tpci_unmap_resource(uio_res->maps[i].addr,\n-\t\t\t\t(size_t)uio_res->maps[i].size);\n-\t\tif (rte_eal_process_type() == RTE_PROC_PRIMARY)\n-\t\t\trte_free(uio_res->maps[i].path);\n-\t}\n-}\n-\n-static struct mapped_pci_resource *\n-pci_uio_find_resource(struct rte_pci_device *dev)\n-{\n-\tstruct mapped_pci_resource *uio_res;\n-\tstruct mapped_pci_res_list *uio_res_list =\n-\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n-\n-\tif (dev == NULL)\n-\t\treturn NULL;\n-\n-\tTAILQ_FOREACH(uio_res, uio_res_list, next) {\n-\n-\t\t/* skip this element if it doesn't match our PCI address */\n-\t\tif (!rte_eal_compare_pci_addr(&uio_res->pci_addr, &dev->addr))\n-\t\t\treturn uio_res;\n-\t}\n-\treturn NULL;\n-}\n-\n-/* unmap the PCI resource of a PCI device in virtual memory */\n-void\n-pci_uio_unmap_resource(struct rte_pci_device *dev)\n-{\n-\tstruct mapped_pci_resource *uio_res;\n-\tstruct mapped_pci_res_list *uio_res_list =\n-\t\t\tRTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list);\n-\n-\tif (dev == NULL)\n-\t\treturn;\n-\n-\t/* find an entry for the device */\n-\tuio_res = pci_uio_find_resource(dev);\n-\tif (uio_res == NULL)\n-\t\treturn;\n-\n-\t/* secondary processes - just free maps */\n-\tif (rte_eal_process_type() != RTE_PROC_PRIMARY)\n-\t\treturn pci_uio_unmap(uio_res);\n-\n-\tTAILQ_REMOVE(uio_res_list, uio_res, next);\n-\n-\t/* unmap all resources */\n-\tpci_uio_unmap(uio_res);\n-\n-\t/* free uio resource */\n-\trte_free(uio_res);\n-\n-\t/* close fd if in primary process */\n-\tclose(dev->intr_handle.fd);\n-\tif (dev->intr_handle.uio_cfg_fd >= 0) {\n-\t\tclose(dev->intr_handle.uio_cfg_fd);\n-\t\tdev->intr_handle.uio_cfg_fd = -1;\n-\t}\n-\n-\tdev->intr_handle.fd = -1;\n-\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-}\ndiff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h\ndeleted file mode 100644\nindex 8b12339..0000000\n--- a/lib/librte_eal/common/include/rte_pci.h\n+++ /dev/null\n@@ -1,598 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n- *   Copyright 2013-2014 6WIND S.A.\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-\n-#ifndef _RTE_PCI_H_\n-#define _RTE_PCI_H_\n-\n-/**\n- * @file\n- *\n- * RTE PCI Interface\n- */\n-\n-#ifdef __cplusplus\n-extern \"C\" {\n-#endif\n-\n-#include <stdio.h>\n-#include <stdlib.h>\n-#include <limits.h>\n-#include <errno.h>\n-#include <sys/queue.h>\n-#include <stdint.h>\n-#include <inttypes.h>\n-\n-#include <rte_debug.h>\n-#include <rte_interrupts.h>\n-#include <rte_dev.h>\n-#include <rte_bus.h>\n-\n-/** Pathname of PCI devices directory. */\n-const char *pci_get_sysfs_path(void);\n-\n-/** Formatting string for PCI device identifier: Ex: 0000:00:01.0 */\n-#define PCI_PRI_FMT \"%.4\" PRIx16 \":%.2\" PRIx8 \":%.2\" PRIx8 \".%\" PRIx8\n-#define PCI_PRI_STR_SIZE sizeof(\"XXXXXXXX:XX:XX.X\")\n-\n-/** Short formatting string, without domain, for PCI device: Ex: 00:01.0 */\n-#define PCI_SHORT_PRI_FMT \"%.2\" PRIx8 \":%.2\" PRIx8 \".%\" PRIx8\n-\n-/** Nb. of values in PCI device identifier format string. */\n-#define PCI_FMT_NVAL 4\n-\n-/** Nb. of values in PCI resource format. */\n-#define PCI_RESOURCE_FMT_NVAL 3\n-\n-/** Maximum number of PCI resources. */\n-#define PCI_MAX_RESOURCE 6\n-\n-/* Forward declarations */\n-struct rte_pci_device;\n-struct rte_pci_driver;\n-\n-/** List of PCI devices */\n-TAILQ_HEAD(rte_pci_device_list, rte_pci_device);\n-/** List of PCI drivers */\n-TAILQ_HEAD(rte_pci_driver_list, rte_pci_driver);\n-\n-/* PCI Bus iterators */\n-#define FOREACH_DEVICE_ON_PCIBUS(p)\t\\\n-\t\tTAILQ_FOREACH(p, &(rte_pci_bus.device_list), next)\n-\n-#define FOREACH_DRIVER_ON_PCIBUS(p)\t\\\n-\t\tTAILQ_FOREACH(p, &(rte_pci_bus.driver_list), next)\n-\n-/**\n- * A structure describing an ID for a PCI driver. Each driver provides a\n- * table of these IDs for each device that it supports.\n- */\n-struct rte_pci_id {\n-\tuint32_t class_id;            /**< Class ID (class, subclass, pi) or RTE_CLASS_ANY_ID. */\n-\tuint16_t vendor_id;           /**< Vendor ID or PCI_ANY_ID. */\n-\tuint16_t device_id;           /**< Device ID or PCI_ANY_ID. */\n-\tuint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */\n-\tuint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */\n-};\n-\n-/**\n- * A structure describing the location of a PCI device.\n- */\n-struct rte_pci_addr {\n-\tuint32_t domain;                /**< Device domain */\n-\tuint8_t bus;                    /**< Device bus */\n-\tuint8_t devid;                  /**< Device ID */\n-\tuint8_t function;               /**< Device function. */\n-};\n-\n-struct rte_devargs;\n-\n-/**\n- * A structure describing a PCI device.\n- */\n-struct rte_pci_device {\n-\tTAILQ_ENTRY(rte_pci_device) next;       /**< Next probed PCI device. */\n-\tstruct rte_device device;               /**< Inherit core device */\n-\tstruct rte_pci_addr addr;               /**< PCI location. */\n-\tstruct rte_pci_id id;                   /**< PCI ID. */\n-\tstruct rte_mem_resource mem_resource[PCI_MAX_RESOURCE];\n-\t\t\t\t\t\t/**< PCI Memory Resource */\n-\tstruct rte_intr_handle intr_handle;     /**< Interrupt handle */\n-\tstruct rte_pci_driver *driver;          /**< Associated driver */\n-\tuint16_t max_vfs;                       /**< sriov enable if not zero */\n-\tenum rte_kernel_driver kdrv;            /**< Kernel driver passthrough */\n-\tchar name[PCI_PRI_STR_SIZE+1];          /**< PCI location (ASCII) */\n-};\n-\n-/**\n- * @internal\n- * Helper macro for drivers that need to convert to struct rte_pci_device.\n- */\n-#define RTE_DEV_TO_PCI(ptr) container_of(ptr, struct rte_pci_device, device)\n-\n-/** Any PCI device identifier (vendor, device, ...) */\n-#define PCI_ANY_ID (0xffff)\n-#define RTE_CLASS_ANY_ID (0xffffff)\n-\n-#ifdef __cplusplus\n-/** C++ macro used to help building up tables of device IDs */\n-#define RTE_PCI_DEVICE(vend, dev) \\\n-\tRTE_CLASS_ANY_ID,         \\\n-\t(vend),                   \\\n-\t(dev),                    \\\n-\tPCI_ANY_ID,               \\\n-\tPCI_ANY_ID\n-#else\n-/** Macro used to help building up tables of device IDs */\n-#define RTE_PCI_DEVICE(vend, dev)          \\\n-\t.class_id = RTE_CLASS_ANY_ID,      \\\n-\t.vendor_id = (vend),               \\\n-\t.device_id = (dev),                \\\n-\t.subsystem_vendor_id = PCI_ANY_ID, \\\n-\t.subsystem_device_id = PCI_ANY_ID\n-#endif\n-\n-/**\n- * Initialisation function for the driver called during PCI probing.\n- */\n-typedef int (pci_probe_t)(struct rte_pci_driver *, struct rte_pci_device *);\n-\n-/**\n- * Uninitialisation function for the driver called during hotplugging.\n- */\n-typedef int (pci_remove_t)(struct rte_pci_device *);\n-\n-/**\n- * A structure describing a PCI driver.\n- */\n-struct rte_pci_driver {\n-\tTAILQ_ENTRY(rte_pci_driver) next;       /**< Next in list. */\n-\tstruct rte_driver driver;               /**< Inherit core driver. */\n-\tstruct rte_pci_bus *bus;                /**< PCI bus reference. */\n-\tpci_probe_t *probe;                     /**< Device Probe function. */\n-\tpci_remove_t *remove;                   /**< Device Remove function. */\n-\tconst struct rte_pci_id *id_table;\t/**< ID table, NULL terminated. */\n-\tuint32_t drv_flags;                     /**< Flags contolling handling of device. */\n-};\n-\n-/**\n- * Structure describing the PCI bus\n- */\n-struct rte_pci_bus {\n-\tstruct rte_bus bus;               /**< Inherit the generic class */\n-\tstruct rte_pci_device_list device_list;  /**< List of PCI devices */\n-\tstruct rte_pci_driver_list driver_list;  /**< List of PCI drivers */\n-};\n-\n-/** Device needs PCI BAR mapping (done with either IGB_UIO or VFIO) */\n-#define RTE_PCI_DRV_NEED_MAPPING 0x0001\n-/** Device driver supports link state interrupt */\n-#define RTE_PCI_DRV_INTR_LSC\t0x0008\n-/** Device driver supports device removal interrupt */\n-#define RTE_PCI_DRV_INTR_RMV 0x0010\n-/** Device driver needs to keep mapped resources if unsupported dev detected */\n-#define RTE_PCI_DRV_KEEP_MAPPED_RES 0x0020\n-\n-/**\n- * A structure describing a PCI mapping.\n- */\n-struct pci_map {\n-\tvoid *addr;\n-\tchar *path;\n-\tuint64_t offset;\n-\tuint64_t size;\n-\tuint64_t phaddr;\n-};\n-\n-/**\n- * A structure describing a mapped PCI resource.\n- * For multi-process we need to reproduce all PCI mappings in secondary\n- * processes, so save them in a tailq.\n- */\n-struct mapped_pci_resource {\n-\tTAILQ_ENTRY(mapped_pci_resource) next;\n-\n-\tstruct rte_pci_addr pci_addr;\n-\tchar path[PATH_MAX];\n-\tint nb_maps;\n-\tstruct pci_map maps[PCI_MAX_RESOURCE];\n-};\n-\n-/** mapped pci device list */\n-TAILQ_HEAD(mapped_pci_res_list, mapped_pci_resource);\n-\n-/**< Internal use only - Macro used by pci addr parsing functions **/\n-#define GET_PCIADDR_FIELD(in, fd, lim, dlm)                   \\\n-do {                                                               \\\n-\tunsigned long val;                                      \\\n-\tchar *end;                                              \\\n-\terrno = 0;                                              \\\n-\tval = strtoul((in), &end, 16);                          \\\n-\tif (errno != 0 || end[0] != (dlm) || val > (lim))       \\\n-\t\treturn -EINVAL;                                 \\\n-\t(fd) = (typeof (fd))val;                                \\\n-\t(in) = end + 1;                                         \\\n-} while(0)\n-\n-/**\n- * Utility function to produce a PCI Bus-Device-Function value\n- * given a string representation. Assumes that the BDF is provided without\n- * a domain prefix (i.e. domain returned is always 0)\n- *\n- * @param input\n- *\tThe input string to be parsed. Should have the format XX:XX.X\n- * @param dev_addr\n- *\tThe PCI Bus-Device-Function address to be returned. Domain will always be\n- *\treturned as 0\n- * @return\n- *  0 on success, negative on error.\n- */\n-static inline int\n-eal_parse_pci_BDF(const char *input, struct rte_pci_addr *dev_addr)\n-{\n-\tdev_addr->domain = 0;\n-\tGET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':');\n-\tGET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.');\n-\tGET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0);\n-\treturn 0;\n-}\n-\n-/**\n- * Utility function to produce a PCI Bus-Device-Function value\n- * given a string representation. Assumes that the BDF is provided including\n- * a domain prefix.\n- *\n- * @param input\n- *\tThe input string to be parsed. Should have the format XXXX:XX:XX.X\n- * @param dev_addr\n- *\tThe PCI Bus-Device-Function address to be returned\n- * @return\n- *  0 on success, negative on error.\n- */\n-static inline int\n-eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr)\n-{\n-\tGET_PCIADDR_FIELD(input, dev_addr->domain, UINT16_MAX, ':');\n-\tGET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':');\n-\tGET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.');\n-\tGET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0);\n-\treturn 0;\n-}\n-#undef GET_PCIADDR_FIELD\n-\n-/**\n- * Utility function to write a pci device name, this device name can later be\n- * used to retrieve the corresponding rte_pci_addr using eal_parse_pci_*\n- * BDF helpers.\n- *\n- * @param addr\n- *\tThe PCI Bus-Device-Function address\n- * @param output\n- *\tThe output buffer string\n- * @param size\n- *\tThe output buffer size\n- */\n-static inline void\n-rte_pci_device_name(const struct rte_pci_addr *addr,\n-\t\tchar *output, size_t size)\n-{\n-\tRTE_VERIFY(size >= PCI_PRI_STR_SIZE);\n-\tRTE_VERIFY(snprintf(output, size, PCI_PRI_FMT,\n-\t\t\t    addr->domain, addr->bus,\n-\t\t\t    addr->devid, addr->function) >= 0);\n-}\n-\n-/* Compare two PCI device addresses. */\n-/**\n- * Utility function to compare two PCI device addresses.\n- *\n- * @param addr\n- *\tThe PCI Bus-Device-Function address to compare\n- * @param addr2\n- *\tThe PCI Bus-Device-Function address to compare\n- * @return\n- *\t0 on equal PCI address.\n- *\tPositive on addr is greater than addr2.\n- *\tNegative on addr is less than addr2, or error.\n- */\n-static inline int\n-rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,\n-\t\t\t const struct rte_pci_addr *addr2)\n-{\n-\tuint64_t dev_addr, dev_addr2;\n-\n-\tif ((addr == NULL) || (addr2 == NULL))\n-\t\treturn -1;\n-\n-\tdev_addr = ((uint64_t)addr->domain << 24) |\n-\t\t(addr->bus << 16) | (addr->devid << 8) | addr->function;\n-\tdev_addr2 = ((uint64_t)addr2->domain << 24) |\n-\t\t(addr2->bus << 16) | (addr2->devid << 8) | addr2->function;\n-\n-\tif (dev_addr > dev_addr2)\n-\t\treturn 1;\n-\telse if (dev_addr < dev_addr2)\n-\t\treturn -1;\n-\telse\n-\t\treturn 0;\n-}\n-\n-/**\n- * Scan the content of the PCI bus, and the devices in the devices\n- * list\n- *\n- * @return\n- *  0 on success, negative on error\n- */\n-int rte_pci_scan(void);\n-\n-/**\n- * Probe the PCI bus\n- *\n- * @return\n- *   - 0 on success.\n- *   - !0 on error.\n- */\n-int\n-rte_pci_probe(void);\n-\n-/**\n- * Map the PCI device resources in user space virtual memory address\n- *\n- * Note that driver should not call this function when flag\n- * RTE_PCI_DRV_NEED_MAPPING is set, as EAL will do that for\n- * you when it's on.\n- *\n- * @param dev\n- *   A pointer to a rte_pci_device structure describing the device\n- *   to use\n- *\n- * @return\n- *   0 on success, negative on error and positive if no driver\n- *   is found for the device.\n- */\n-int rte_pci_map_device(struct rte_pci_device *dev);\n-\n-/**\n- * Unmap this device\n- *\n- * @param dev\n- *   A pointer to a rte_pci_device structure describing the device\n- *   to use\n- */\n-void rte_pci_unmap_device(struct rte_pci_device *dev);\n-\n-/**\n- * @internal\n- * Map a particular resource from a file.\n- *\n- * @param requested_addr\n- *      The starting address for the new mapping range.\n- * @param fd\n- *      The file descriptor.\n- * @param offset\n- *      The offset for the mapping range.\n- * @param size\n- *      The size for the mapping range.\n- * @param additional_flags\n- *      The additional flags for the mapping range.\n- * @return\n- *   - On success, the function returns a pointer to the mapped area.\n- *   - On error, the value MAP_FAILED is returned.\n- */\n-void *pci_map_resource(void *requested_addr, int fd, off_t offset,\n-\t\tsize_t size, int additional_flags);\n-\n-/**\n- * @internal\n- * Unmap a particular resource.\n- *\n- * @param requested_addr\n- *      The address for the unmapping range.\n- * @param size\n- *      The size for the unmapping range.\n- */\n-void pci_unmap_resource(void *requested_addr, size_t size);\n-\n-/**\n- * Probe the single PCI device.\n- *\n- * Scan the content of the PCI bus, and find the pci device specified by pci\n- * address, then call the probe() function for registered driver that has a\n- * matching entry in its id_table for discovered device.\n- *\n- * @param addr\n- *\tThe PCI Bus-Device-Function address to probe.\n- * @return\n- *   - 0 on success.\n- *   - Negative on error.\n- */\n-int rte_pci_probe_one(const struct rte_pci_addr *addr);\n-\n-/**\n- * Close the single PCI device.\n- *\n- * Scan the content of the PCI bus, and find the pci device specified by pci\n- * address, then call the remove() function for registered driver that has a\n- * matching entry in its id_table for discovered device.\n- *\n- * @param addr\n- *\tThe PCI Bus-Device-Function address to close.\n- * @return\n- *   - 0 on success.\n- *   - Negative on error.\n- */\n-int rte_pci_detach(const struct rte_pci_addr *addr);\n-\n-/**\n- * Dump the content of the PCI bus.\n- *\n- * @param f\n- *   A pointer to a file for output\n- */\n-void rte_pci_dump(FILE *f);\n-\n-/**\n- * Register a PCI driver.\n- *\n- * @param driver\n- *   A pointer to a rte_pci_driver structure describing the driver\n- *   to be registered.\n- */\n-void rte_pci_register(struct rte_pci_driver *driver);\n-\n-/** Helper for PCI device registration from driver (eth, crypto) instance */\n-#define RTE_PMD_REGISTER_PCI(nm, pci_drv) \\\n-RTE_INIT(pciinitfn_ ##nm); \\\n-static void pciinitfn_ ##nm(void) \\\n-{\\\n-\t(pci_drv).driver.name = RTE_STR(nm);\\\n-\trte_pci_register(&pci_drv); \\\n-} \\\n-RTE_PMD_EXPORT_NAME(nm, __COUNTER__)\n-\n-/**\n- * Unregister a PCI driver.\n- *\n- * @param driver\n- *   A pointer to a rte_pci_driver structure describing the driver\n- *   to be unregistered.\n- */\n-void rte_pci_unregister(struct rte_pci_driver *driver);\n-\n-/**\n- * Read PCI config space.\n- *\n- * @param device\n- *   A pointer to a rte_pci_device structure describing the device\n- *   to use\n- * @param buf\n- *   A data buffer where the bytes should be read into\n- * @param len\n- *   The length of the data buffer.\n- * @param offset\n- *   The offset into PCI config space\n- */\n-int rte_pci_read_config(const struct rte_pci_device *device,\n-\t\tvoid *buf, size_t len, off_t offset);\n-\n-/**\n- * Write PCI config space.\n- *\n- * @param device\n- *   A pointer to a rte_pci_device structure describing the device\n- *   to use\n- * @param buf\n- *   A data buffer containing the bytes should be written\n- * @param len\n- *   The length of the data buffer.\n- * @param offset\n- *   The offset into PCI config space\n- */\n-int rte_pci_write_config(const struct rte_pci_device *device,\n-\t\tconst void *buf, size_t len, off_t offset);\n-\n-/**\n- * A structure used to access io resources for a pci device.\n- * rte_pci_ioport is arch, os, driver specific, and should not be used outside\n- * of pci ioport api.\n- */\n-struct rte_pci_ioport {\n-\tstruct rte_pci_device *dev;\n-\tuint64_t base;\n-\tuint64_t len; /* only filled for memory mapped ports */\n-};\n-\n-/**\n- * Initialize a rte_pci_ioport object for a pci device io resource.\n- *\n- * This object is then used to gain access to those io resources (see below).\n- *\n- * @param dev\n- *   A pointer to a rte_pci_device structure describing the device\n- *   to use.\n- * @param bar\n- *   Index of the io pci resource we want to access.\n- * @param p\n- *   The rte_pci_ioport object to be initialized.\n- * @return\n- *  0 on success, negative on error.\n- */\n-int rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\tstruct rte_pci_ioport *p);\n-\n-/**\n- * Release any resources used in a rte_pci_ioport object.\n- *\n- * @param p\n- *   The rte_pci_ioport object to be uninitialized.\n- * @return\n- *  0 on success, negative on error.\n- */\n-int rte_pci_ioport_unmap(struct rte_pci_ioport *p);\n-\n-/**\n- * Read from a io pci resource.\n- *\n- * @param p\n- *   The rte_pci_ioport object from which we want to read.\n- * @param data\n- *   A data buffer where the bytes should be read into\n- * @param len\n- *   The length of the data buffer.\n- * @param offset\n- *   The offset into the pci io resource.\n- */\n-void rte_pci_ioport_read(struct rte_pci_ioport *p,\n-\t\tvoid *data, size_t len, off_t offset);\n-\n-/**\n- * Write to a io pci resource.\n- *\n- * @param p\n- *   The rte_pci_ioport object to which we want to write.\n- * @param data\n- *   A data buffer where the bytes should be read into\n- * @param len\n- *   The length of the data buffer.\n- * @param offset\n- *   The offset into the pci io resource.\n- */\n-void rte_pci_ioport_write(struct rte_pci_ioport *p,\n-\t\tconst void *data, size_t len, off_t offset);\n-\n-#ifdef __cplusplus\n-}\n-#endif\n-\n-#endif /* _RTE_PCI_H_ */\ndiff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile\nindex 90bca4d..4abc886 100644\n--- a/lib/librte_eal/linuxapp/eal/Makefile\n+++ b/lib/librte_eal/linuxapp/eal/Makefile\n@@ -64,10 +64,6 @@ endif\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_mp_sync.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_uio.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_pci_vfio.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_debug.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c\n@@ -81,8 +77,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_vdev.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci.c\n-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_pci_uio.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_tailqs.c\n SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_errno.c\n@@ -109,16 +103,12 @@ CFLAGS_eal_common_cpuflags.o := $(CPUFLAGS_LIST)\n \n CFLAGS_eal.o := -D_GNU_SOURCE\n CFLAGS_eal_interrupts.o := -D_GNU_SOURCE\n-CFLAGS_eal_vfio_mp_sync.o := -D_GNU_SOURCE\n CFLAGS_eal_timer.o := -D_GNU_SOURCE\n CFLAGS_eal_lcore.o := -D_GNU_SOURCE\n CFLAGS_eal_thread.o := -D_GNU_SOURCE\n CFLAGS_eal_log.o := -D_GNU_SOURCE\n CFLAGS_eal_common_log.o := -D_GNU_SOURCE\n CFLAGS_eal_hugepage_info.o := -D_GNU_SOURCE\n-CFLAGS_eal_pci.o := -D_GNU_SOURCE\n-CFLAGS_eal_pci_uio.o := -D_GNU_SOURCE\n-CFLAGS_eal_pci_vfio.o := -D_GNU_SOURCE\n CFLAGS_eal_common_whitelist.o := -D_GNU_SOURCE\n CFLAGS_eal_common_options.o := -D_GNU_SOURCE\n CFLAGS_eal_common_thread.o := -D_GNU_SOURCE\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\ndeleted file mode 100644\nindex 8951ce7..0000000\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ /dev/null\n@@ -1,722 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#include <string.h>\n-#include <dirent.h>\n-\n-#include <rte_log.h>\n-#include <rte_bus.h>\n-#include <rte_pci.h>\n-#include <rte_eal_memconfig.h>\n-#include <rte_malloc.h>\n-#include <rte_devargs.h>\n-#include <rte_memcpy.h>\n-\n-#include \"eal_filesystem.h\"\n-#include \"eal_private.h\"\n-#include \"eal_pci_init.h\"\n-\n-/**\n- * @file\n- * PCI probing under linux\n- *\n- * This code is used to simulate a PCI probe by parsing information in sysfs.\n- * When a registered device matches a driver, it is then initialized with\n- * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it).\n- */\n-\n-extern struct rte_pci_bus rte_pci_bus;\n-\n-static int\n-pci_get_kernel_driver_by_path(const char *filename, char *dri_name)\n-{\n-\tint count;\n-\tchar path[PATH_MAX];\n-\tchar *name;\n-\n-\tif (!filename || !dri_name)\n-\t\treturn -1;\n-\n-\tcount = readlink(filename, path, PATH_MAX);\n-\tif (count >= PATH_MAX)\n-\t\treturn -1;\n-\n-\t/* For device does not have a driver */\n-\tif (count < 0)\n-\t\treturn 1;\n-\n-\tpath[count] = '\\0';\n-\n-\tname = strrchr(path, '/');\n-\tif (name) {\n-\t\tstrncpy(dri_name, name + 1, strlen(name + 1) + 1);\n-\t\treturn 0;\n-\t}\n-\n-\treturn -1;\n-}\n-\n-/* Map pci device */\n-int\n-rte_pci_map_device(struct rte_pci_device *dev)\n-{\n-\tint ret = -1;\n-\n-\t/* try mapping the NIC resources using VFIO if it exists */\n-\tswitch (dev->kdrv) {\n-\tcase RTE_KDRV_VFIO:\n-#ifdef VFIO_PRESENT\n-\t\tif (pci_vfio_is_enabled())\n-\t\t\tret = pci_vfio_map_resource(dev);\n-#endif\n-\t\tbreak;\n-\tcase RTE_KDRV_IGB_UIO:\n-\tcase RTE_KDRV_UIO_GENERIC:\n-\t\tif (rte_eal_using_phys_addrs()) {\n-\t\t\t/* map resources for devices that use uio */\n-\t\t\tret = pci_uio_map_resource(dev);\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n-\t\tret = 1;\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n-}\n-\n-/* Unmap pci device */\n-void\n-rte_pci_unmap_device(struct rte_pci_device *dev)\n-{\n-\t/* try unmapping the NIC resources using VFIO if it exists */\n-\tswitch (dev->kdrv) {\n-\tcase RTE_KDRV_VFIO:\n-#ifdef VFIO_PRESENT\n-\t\tif (pci_vfio_is_enabled())\n-\t\t\tpci_vfio_unmap_resource(dev);\n-#endif\n-\t\tbreak;\n-\tcase RTE_KDRV_IGB_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-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\"  Not managed by a supported kernel driver, skipped\\n\");\n-\t\tbreak;\n-\t}\n-}\n-\n-void *\n-pci_find_max_end_va(void)\n-{\n-\tconst struct rte_memseg *seg = rte_eal_get_physmem_layout();\n-\tconst struct rte_memseg *last = seg;\n-\tunsigned i = 0;\n-\n-\tfor (i = 0; i < RTE_MAX_MEMSEG; i++, seg++) {\n-\t\tif (seg->addr == NULL)\n-\t\t\tbreak;\n-\n-\t\tif (seg->addr > last->addr)\n-\t\t\tlast = seg;\n-\n-\t}\n-\treturn RTE_PTR_ADD(last->addr, last->len);\n-}\n-\n-/* parse one line of the \"resource\" sysfs file (note that the 'line'\n- * string is modified)\n- */\n-int\n-pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,\n-\tuint64_t *end_addr, uint64_t *flags)\n-{\n-\tunion pci_resource_info {\n-\t\tstruct {\n-\t\t\tchar *phys_addr;\n-\t\t\tchar *end_addr;\n-\t\t\tchar *flags;\n-\t\t};\n-\t\tchar *ptrs[PCI_RESOURCE_FMT_NVAL];\n-\t} res_info;\n-\n-\tif (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"%s(): bad resource format\\n\", __func__);\n-\t\treturn -1;\n-\t}\n-\terrno = 0;\n-\t*phys_addr = strtoull(res_info.phys_addr, NULL, 16);\n-\t*end_addr = strtoull(res_info.end_addr, NULL, 16);\n-\t*flags = strtoull(res_info.flags, NULL, 16);\n-\tif (errno != 0) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"%s(): bad resource format\\n\", __func__);\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* parse the \"resource\" sysfs file */\n-static int\n-pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)\n-{\n-\tFILE *f;\n-\tchar buf[BUFSIZ];\n-\tint i;\n-\tuint64_t phys_addr, end_addr, flags;\n-\n-\tf = fopen(filename, \"r\");\n-\tif (f == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open sysfs resource\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\tfor (i = 0; i<PCI_MAX_RESOURCE; i++) {\n-\n-\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n-\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"%s(): cannot read resource\\n\", __func__);\n-\t\t\tgoto error;\n-\t\t}\n-\t\tif (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,\n-\t\t\t\t&end_addr, &flags) < 0)\n-\t\t\tgoto error;\n-\n-\t\tif (flags & IORESOURCE_MEM) {\n-\t\t\tdev->mem_resource[i].phys_addr = phys_addr;\n-\t\t\tdev->mem_resource[i].len = end_addr - phys_addr + 1;\n-\t\t\t/* not mapped for now */\n-\t\t\tdev->mem_resource[i].addr = NULL;\n-\t\t}\n-\t}\n-\tfclose(f);\n-\treturn 0;\n-\n-error:\n-\tfclose(f);\n-\treturn -1;\n-}\n-\n-/* Scan one pci sysfs entry, and fill the devices list from it. */\n-static int\n-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)\n-{\n-\tchar filename[PATH_MAX];\n-\tunsigned long tmp;\n-\tstruct rte_pci_device *dev;\n-\tchar driver[PATH_MAX];\n-\tint ret;\n-\n-\tdev = malloc(sizeof(*dev));\n-\tif (dev == NULL)\n-\t\treturn -1;\n-\n-\tmemset(dev, 0, sizeof(*dev));\n-\tdev->addr = *addr;\n-\n-\t/* get vendor id */\n-\tsnprintf(filename, sizeof(filename), \"%s/vendor\", dirname);\n-\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\tdev->id.vendor_id = (uint16_t)tmp;\n-\n-\t/* get device id */\n-\tsnprintf(filename, sizeof(filename), \"%s/device\", dirname);\n-\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\tdev->id.device_id = (uint16_t)tmp;\n-\n-\t/* get subsystem_vendor id */\n-\tsnprintf(filename, sizeof(filename), \"%s/subsystem_vendor\",\n-\t\t dirname);\n-\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\tdev->id.subsystem_vendor_id = (uint16_t)tmp;\n-\n-\t/* get subsystem_device id */\n-\tsnprintf(filename, sizeof(filename), \"%s/subsystem_device\",\n-\t\t dirname);\n-\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\tdev->id.subsystem_device_id = (uint16_t)tmp;\n-\n-\t/* get class_id */\n-\tsnprintf(filename, sizeof(filename), \"%s/class\",\n-\t\t dirname);\n-\tif (eal_parse_sysfs_value(filename, &tmp) < 0) {\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\t/* the least 24 bits are valid: class, subclass, program interface */\n-\tdev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;\n-\n-\t/* get max_vfs */\n-\tdev->max_vfs = 0;\n-\tsnprintf(filename, sizeof(filename), \"%s/max_vfs\", dirname);\n-\tif (!access(filename, F_OK) &&\n-\t    eal_parse_sysfs_value(filename, &tmp) == 0)\n-\t\tdev->max_vfs = (uint16_t)tmp;\n-\telse {\n-\t\t/* for non igb_uio driver, need kernel version >= 3.8 */\n-\t\tsnprintf(filename, sizeof(filename),\n-\t\t\t \"%s/sriov_numvfs\", dirname);\n-\t\tif (!access(filename, F_OK) &&\n-\t\t    eal_parse_sysfs_value(filename, &tmp) == 0)\n-\t\t\tdev->max_vfs = (uint16_t)tmp;\n-\t}\n-\n-\t/* get numa node, default to 0 if not present */\n-\tsnprintf(filename, sizeof(filename), \"%s/numa_node\",\n-\t\t dirname);\n-\n-\tif (access(filename, F_OK) != -1) {\n-\t\tif (eal_parse_sysfs_value(filename, &tmp) == 0)\n-\t\t\tdev->device.numa_node = tmp;\n-\t\telse\n-\t\t\tdev->device.numa_node = -1;\n-\t} else {\n-\t\tdev->device.numa_node = 0;\n-\t}\n-\n-\tpci_name_set(dev);\n-\n-\t/* parse resources */\n-\tsnprintf(filename, sizeof(filename), \"%s/resource\", dirname);\n-\tif (pci_parse_sysfs_resource(filename, dev) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse resource\\n\", __func__);\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\n-\t/* parse driver */\n-\tsnprintf(filename, sizeof(filename), \"%s/driver\", dirname);\n-\tret = pci_get_kernel_driver_by_path(filename, driver);\n-\tif (ret < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Fail to get kernel driver\\n\");\n-\t\tfree(dev);\n-\t\treturn -1;\n-\t}\n-\n-\tif (!ret) {\n-\t\tif (!strcmp(driver, \"vfio-pci\"))\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, \"uio_pci_generic\"))\n-\t\t\tdev->kdrv = RTE_KDRV_UIO_GENERIC;\n-\t\telse\n-\t\t\tdev->kdrv = RTE_KDRV_UNKNOWN;\n-\t} else\n-\t\tdev->kdrv = RTE_KDRV_NONE;\n-\n-\t/* device is valid, add in list (sorted) */\n-\tif (TAILQ_EMPTY(&rte_pci_bus.device_list)) {\n-\t\trte_pci_add_device(dev);\n-\t} else {\n-\t\tstruct rte_pci_device *dev2;\n-\t\tint ret;\n-\n-\t\tTAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {\n-\t\t\tret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);\n-\t\t\tif (ret > 0)\n-\t\t\t\tcontinue;\n-\n-\t\t\tif (ret < 0) {\n-\t\t\t\trte_pci_insert_device(dev2, dev);\n-\t\t\t} else { /* already registered */\n-\t\t\t\tdev2->kdrv = dev->kdrv;\n-\t\t\t\tdev2->max_vfs = dev->max_vfs;\n-\t\t\t\tpci_name_set(dev2);\n-\t\t\t\tmemmove(dev2->mem_resource, dev->mem_resource,\n-\t\t\t\t\tsizeof(dev->mem_resource));\n-\t\t\t\tfree(dev);\n-\t\t\t}\n-\t\t\treturn 0;\n-\t\t}\n-\n-\t\trte_pci_add_device(dev);\n-\t}\n-\n-\treturn 0;\n-}\n-\n-int\n-pci_update_device(const struct rte_pci_addr *addr)\n-{\n-\tchar filename[PATH_MAX];\n-\n-\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT,\n-\t\t pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,\n-\t\t addr->function);\n-\n-\treturn pci_scan_one(filename, addr);\n-}\n-\n-/*\n- * split up a pci address into its constituent parts.\n- */\n-static int\n-parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)\n-{\n-\t/* first split on ':' */\n-\tunion splitaddr {\n-\t\tstruct {\n-\t\t\tchar *domain;\n-\t\t\tchar *bus;\n-\t\t\tchar *devid;\n-\t\t\tchar *function;\n-\t\t};\n-\t\tchar *str[PCI_FMT_NVAL]; /* last element-separator is \".\" not \":\" */\n-\t} splitaddr;\n-\n-\tchar *buf_copy = strndup(buf, bufsize);\n-\tif (buf_copy == NULL)\n-\t\treturn -1;\n-\n-\tif (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')\n-\t\t\t!= PCI_FMT_NVAL - 1)\n-\t\tgoto error;\n-\t/* final split is on '.' between devid and function */\n-\tsplitaddr.function = strchr(splitaddr.devid,'.');\n-\tif (splitaddr.function == NULL)\n-\t\tgoto error;\n-\t*splitaddr.function++ = '\\0';\n-\n-\t/* now convert to int values */\n-\terrno = 0;\n-\taddr->domain = strtoul(splitaddr.domain, NULL, 16);\n-\taddr->bus = strtoul(splitaddr.bus, NULL, 16);\n-\taddr->devid = strtoul(splitaddr.devid, NULL, 16);\n-\taddr->function = strtoul(splitaddr.function, NULL, 10);\n-\tif (errno != 0)\n-\t\tgoto error;\n-\n-\tfree(buf_copy); /* free the copy made with strdup */\n-\treturn 0;\n-error:\n-\tfree(buf_copy);\n-\treturn -1;\n-}\n-\n-/*\n- * Scan the content of the PCI bus, and the devices in the devices\n- * list\n- */\n-int\n-rte_pci_scan(void)\n-{\n-\tstruct dirent *e;\n-\tDIR *dir;\n-\tchar dirname[PATH_MAX];\n-\tstruct rte_pci_addr addr;\n-\n-\t/* for debug purposes, PCI can be disabled */\n-\tif (internal_config.no_pci)\n-\t\treturn 0;\n-\n-\tdir = opendir(pci_get_sysfs_path());\n-\tif (dir == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): opendir failed: %s\\n\",\n-\t\t\t__func__, strerror(errno));\n-\t\treturn -1;\n-\t}\n-\n-\twhile ((e = readdir(dir)) != NULL) {\n-\t\tif (e->d_name[0] == '.')\n-\t\t\tcontinue;\n-\n-\t\tif (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)\n-\t\t\tcontinue;\n-\n-\t\tsnprintf(dirname, sizeof(dirname), \"%s/%s\",\n-\t\t\t\tpci_get_sysfs_path(), e->d_name);\n-\n-\t\tif (pci_scan_one(dirname, &addr) < 0)\n-\t\t\tgoto error;\n-\t}\n-\tclosedir(dir);\n-\treturn 0;\n-\n-error:\n-\tclosedir(dir);\n-\treturn -1;\n-}\n-\n-/* Read PCI config space. */\n-int rte_pci_read_config(const struct rte_pci_device *device,\n-\t\tvoid *buf, size_t len, off_t offset)\n-{\n-\tconst struct rte_intr_handle *intr_handle = &device->intr_handle;\n-\n-\tswitch (intr_handle->type) {\n-\tcase RTE_INTR_HANDLE_UIO:\n-\tcase RTE_INTR_HANDLE_UIO_INTX:\n-\t\treturn pci_uio_read_config(intr_handle, buf, len, offset);\n-\n-#ifdef VFIO_PRESENT\n-\tcase RTE_INTR_HANDLE_VFIO_MSIX:\n-\tcase RTE_INTR_HANDLE_VFIO_MSI:\n-\tcase RTE_INTR_HANDLE_VFIO_LEGACY:\n-\t\treturn pci_vfio_read_config(intr_handle, buf, len, offset);\n-#endif\n-\tdefault:\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Unknown handle type of fd %d\\n\",\n-\t\t\t\t\tintr_handle->fd);\n-\t\treturn -1;\n-\t}\n-}\n-\n-/* Write PCI config space. */\n-int rte_pci_write_config(const struct rte_pci_device *device,\n-\t\tconst void *buf, size_t len, off_t offset)\n-{\n-\tconst struct rte_intr_handle *intr_handle = &device->intr_handle;\n-\n-\tswitch (intr_handle->type) {\n-\tcase RTE_INTR_HANDLE_UIO:\n-\tcase RTE_INTR_HANDLE_UIO_INTX:\n-\t\treturn pci_uio_write_config(intr_handle, buf, len, offset);\n-\n-#ifdef VFIO_PRESENT\n-\tcase RTE_INTR_HANDLE_VFIO_MSIX:\n-\tcase RTE_INTR_HANDLE_VFIO_MSI:\n-\tcase RTE_INTR_HANDLE_VFIO_LEGACY:\n-\t\treturn pci_vfio_write_config(intr_handle, buf, len, offset);\n-#endif\n-\tdefault:\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Unknown handle type of fd %d\\n\",\n-\t\t\t\t\tintr_handle->fd);\n-\t\treturn -1;\n-\t}\n-}\n-\n-#if defined(RTE_ARCH_X86)\n-static int\n-pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,\n-\t\tstruct rte_pci_ioport *p)\n-{\n-\tuint16_t start, end;\n-\tFILE *fp;\n-\tchar *line = NULL;\n-\tchar pci_id[16];\n-\tint found = 0;\n-\tsize_t linesz;\n-\n-\tsnprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT,\n-\t\t dev->addr.domain, dev->addr.bus,\n-\t\t dev->addr.devid, dev->addr.function);\n-\n-\tfp = fopen(\"/proc/ioports\", \"r\");\n-\tif (fp == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): can't open ioports\\n\", __func__);\n-\t\treturn -1;\n-\t}\n-\n-\twhile (getdelim(&line, &linesz, '\\n', fp) > 0) {\n-\t\tchar *ptr = line;\n-\t\tchar *left;\n-\t\tint n;\n-\n-\t\tn = strcspn(ptr, \":\");\n-\t\tptr[n] = 0;\n-\t\tleft = &ptr[n + 1];\n-\n-\t\twhile (*left && isspace(*left))\n-\t\t\tleft++;\n-\n-\t\tif (!strncmp(left, pci_id, strlen(pci_id))) {\n-\t\t\tfound = 1;\n-\n-\t\t\twhile (*ptr && isspace(*ptr))\n-\t\t\t\tptr++;\n-\n-\t\t\tsscanf(ptr, \"%04hx-%04hx\", &start, &end);\n-\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\n-\tfree(line);\n-\tfclose(fp);\n-\n-\tif (!found)\n-\t\treturn -1;\n-\n-\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-\tp->base = start;\n-\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%x\\n\", start);\n-\n-\treturn 0;\n-}\n-#endif\n-\n-int\n-rte_pci_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\tstruct rte_pci_ioport *p)\n-{\n-\tint ret = -1;\n-\n-\tswitch (dev->kdrv) {\n-#ifdef VFIO_PRESENT\n-\tcase RTE_KDRV_VFIO:\n-\t\tif (pci_vfio_is_enabled())\n-\t\t\tret = pci_vfio_ioport_map(dev, bar, p);\n-\t\tbreak;\n-#endif\n-\tcase RTE_KDRV_IGB_UIO:\n-\t\tret = pci_uio_ioport_map(dev, bar, p);\n-\t\tbreak;\n-\tcase RTE_KDRV_UIO_GENERIC:\n-#if defined(RTE_ARCH_X86)\n-\t\tret = pci_ioport_map(dev, bar, p);\n-#else\n-\t\tret = pci_uio_ioport_map(dev, bar, p);\n-#endif\n-\t\tbreak;\n-\tcase RTE_KDRV_NONE:\n-#if defined(RTE_ARCH_X86)\n-\t\tret = pci_ioport_map(dev, bar, p);\n-#endif\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\n-\tif (!ret)\n-\t\tp->dev = dev;\n-\n-\treturn ret;\n-}\n-\n-void\n-rte_pci_ioport_read(struct rte_pci_ioport *p,\n-\t\tvoid *data, size_t len, off_t offset)\n-{\n-\tswitch (p->dev->kdrv) {\n-#ifdef VFIO_PRESENT\n-\tcase RTE_KDRV_VFIO:\n-\t\tpci_vfio_ioport_read(p, data, len, offset);\n-\t\tbreak;\n-#endif\n-\tcase RTE_KDRV_IGB_UIO:\n-\t\tpci_uio_ioport_read(p, data, len, offset);\n-\t\tbreak;\n-\tcase RTE_KDRV_UIO_GENERIC:\n-\t\tpci_uio_ioport_read(p, data, len, offset);\n-\t\tbreak;\n-\tcase RTE_KDRV_NONE:\n-#if defined(RTE_ARCH_X86)\n-\t\tpci_uio_ioport_read(p, data, len, offset);\n-#endif\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n-void\n-rte_pci_ioport_write(struct rte_pci_ioport *p,\n-\t\tconst void *data, size_t len, off_t offset)\n-{\n-\tswitch (p->dev->kdrv) {\n-#ifdef VFIO_PRESENT\n-\tcase RTE_KDRV_VFIO:\n-\t\tpci_vfio_ioport_write(p, data, len, offset);\n-\t\tbreak;\n-#endif\n-\tcase RTE_KDRV_IGB_UIO:\n-\t\tpci_uio_ioport_write(p, data, len, offset);\n-\t\tbreak;\n-\tcase RTE_KDRV_UIO_GENERIC:\n-\t\tpci_uio_ioport_write(p, data, len, offset);\n-\t\tbreak;\n-\tcase RTE_KDRV_NONE:\n-#if defined(RTE_ARCH_X86)\n-\t\tpci_uio_ioport_write(p, data, len, offset);\n-#endif\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n-int\n-rte_pci_ioport_unmap(struct rte_pci_ioport *p)\n-{\n-\tint ret = -1;\n-\n-\tswitch (p->dev->kdrv) {\n-#ifdef VFIO_PRESENT\n-\tcase RTE_KDRV_VFIO:\n-\t\tif (pci_vfio_is_enabled())\n-\t\t\tret = pci_vfio_ioport_unmap(p);\n-\t\tbreak;\n-#endif\n-\tcase RTE_KDRV_IGB_UIO:\n-\t\tret = pci_uio_ioport_unmap(p);\n-\t\tbreak;\n-\tcase RTE_KDRV_UIO_GENERIC:\n-#if defined(RTE_ARCH_X86)\n-\t\tret = 0;\n-#else\n-\t\tret = pci_uio_ioport_unmap(p);\n-#endif\n-\t\tbreak;\n-\tcase RTE_KDRV_NONE:\n-#if defined(RTE_ARCH_X86)\n-\t\tret = 0;\n-#endif\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\n-\treturn ret;\n-}\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h\ndeleted file mode 100644\nindex ae2980d..0000000\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h\n+++ /dev/null\n@@ -1,97 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#ifndef EAL_PCI_INIT_H_\n-#define EAL_PCI_INIT_H_\n-\n-#include \"eal_vfio.h\"\n-\n-/** IO resource type: */\n-#define IORESOURCE_IO         0x00000100\n-#define IORESOURCE_MEM        0x00000200\n-\n-/*\n- * Helper function to map PCI resources right after hugepages in virtual memory\n- */\n-extern void *pci_map_addr;\n-void *pci_find_max_end_va(void);\n-\n-/* parse one line of the \"resource\" sysfs file (note that the 'line'\n- * string is modified)\n- */\n-int pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,\n-\tuint64_t *end_addr, uint64_t *flags);\n-\n-int pci_uio_alloc_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource **uio_res);\n-void pci_uio_free_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource *uio_res);\n-int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n-\t\tstruct mapped_pci_resource *uio_res, int map_idx);\n-\n-int pci_uio_read_config(const struct rte_intr_handle *intr_handle,\n-\t\t\tvoid *buf, size_t len, off_t offs);\n-int pci_uio_write_config(const struct rte_intr_handle *intr_handle,\n-\t\t\t const void *buf, size_t len, off_t offs);\n-\n-int pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\t       struct rte_pci_ioport *p);\n-void pci_uio_ioport_read(struct rte_pci_ioport *p,\n-\t\t\t void *data, size_t len, off_t offset);\n-void pci_uio_ioport_write(struct rte_pci_ioport *p,\n-\t\t\t  const void *data, size_t len, off_t offset);\n-int pci_uio_ioport_unmap(struct rte_pci_ioport *p);\n-\n-#ifdef VFIO_PRESENT\n-\n-/* access config space */\n-int pci_vfio_read_config(const struct rte_intr_handle *intr_handle,\n-\t\t\t void *buf, size_t len, off_t offs);\n-int pci_vfio_write_config(const struct rte_intr_handle *intr_handle,\n-\t\t\t  const void *buf, size_t len, off_t offs);\n-\n-int pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\t        struct rte_pci_ioport *p);\n-void pci_vfio_ioport_read(struct rte_pci_ioport *p,\n-\t\t\t  void *data, size_t len, off_t offset);\n-void pci_vfio_ioport_write(struct rte_pci_ioport *p,\n-\t\t\t   const void *data, size_t len, off_t offset);\n-int pci_vfio_ioport_unmap(struct rte_pci_ioport *p);\n-\n-/* map/unmap VFIO resource prototype */\n-int pci_vfio_map_resource(struct rte_pci_device *dev);\n-int pci_vfio_unmap_resource(struct rte_pci_device *dev);\n-\n-#endif\n-\n-#endif /* EAL_PCI_INIT_H_ */\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\ndeleted file mode 100644\nindex fa10329..0000000\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n+++ /dev/null\n@@ -1,567 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#include <string.h>\n-#include <unistd.h>\n-#include <fcntl.h>\n-#include <dirent.h>\n-#include <inttypes.h>\n-#include <sys/stat.h>\n-#include <sys/mman.h>\n-#include <sys/sysmacros.h>\n-#include <linux/pci_regs.h>\n-\n-#if defined(RTE_ARCH_X86)\n-#include <sys/io.h>\n-#endif\n-\n-#include <rte_log.h>\n-#include <rte_pci.h>\n-#include <rte_eal_memconfig.h>\n-#include <rte_common.h>\n-#include <rte_malloc.h>\n-\n-#include \"eal_filesystem.h\"\n-#include \"eal_pci_init.h\"\n-\n-void *pci_map_addr = NULL;\n-\n-#define OFF_MAX              ((uint64_t)(off_t)-1)\n-\n-int\n-pci_uio_read_config(const struct rte_intr_handle *intr_handle,\n-\t\t    void *buf, size_t len, off_t offset)\n-{\n-\treturn pread(intr_handle->uio_cfg_fd, buf, len, offset);\n-}\n-\n-int\n-pci_uio_write_config(const struct rte_intr_handle *intr_handle,\n-\t\t     const void *buf, size_t len, off_t offset)\n-{\n-\treturn pwrite(intr_handle->uio_cfg_fd, buf, len, offset);\n-}\n-\n-static int\n-pci_uio_set_bus_master(int dev_fd)\n-{\n-\tuint16_t reg;\n-\tint ret;\n-\n-\tret = pread(dev_fd, &reg, sizeof(reg), PCI_COMMAND);\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Cannot read command from PCI config space!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\t/* return if bus mastering is already on */\n-\tif (reg & PCI_COMMAND_MASTER)\n-\t\treturn 0;\n-\n-\treg |= PCI_COMMAND_MASTER;\n-\n-\tret = pwrite(dev_fd, &reg, sizeof(reg), PCI_COMMAND);\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Cannot write command to PCI config space!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static int\n-pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)\n-{\n-\tFILE *f;\n-\tchar filename[PATH_MAX];\n-\tint ret;\n-\tunsigned major, minor;\n-\tdev_t dev;\n-\n-\t/* get the name of the sysfs file that contains the major and minor\n-\t * of the uio device and read its content */\n-\tsnprintf(filename, sizeof(filename), \"%s/dev\", sysfs_uio_path);\n-\n-\tf = fopen(filename, \"r\");\n-\tif (f == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot open sysfs to get major:minor\\n\",\n-\t\t\t__func__);\n-\t\treturn -1;\n-\t}\n-\n-\tret = fscanf(f, \"%u:%u\", &major, &minor);\n-\tif (ret != 2) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse sysfs to get major:minor\\n\",\n-\t\t\t__func__);\n-\t\tfclose(f);\n-\t\treturn -1;\n-\t}\n-\tfclose(f);\n-\n-\t/* create the char device \"mknod /dev/uioX c major minor\" */\n-\tsnprintf(filename, sizeof(filename), \"/dev/uio%u\", uio_num);\n-\tdev = makedev(major, minor);\n-\tret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);\n-\tif (ret != 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): mknod() failed %s\\n\",\n-\t\t\t__func__, strerror(errno));\n-\t\treturn -1;\n-\t}\n-\n-\treturn ret;\n-}\n-\n-/*\n- * Return the uioX char device used for a pci device. On success, return\n- * the UIO number and fill dstbuf string with the path of the device in\n- * sysfs. On error, return a negative value. In this case dstbuf is\n- * invalid.\n- */\n-static int\n-pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,\n-\t\t\t   unsigned int buflen, int create)\n-{\n-\tstruct rte_pci_addr *loc = &dev->addr;\n-\tunsigned int uio_num;\n-\tstruct dirent *e;\n-\tDIR *dir;\n-\tchar dirname[PATH_MAX];\n-\n-\t/* depending on kernel version, uio can be located in uio/uioX\n-\t * or uio:uioX */\n-\n-\tsnprintf(dirname, sizeof(dirname),\n-\t\t\t\"%s/\" PCI_PRI_FMT \"/uio\", pci_get_sysfs_path(),\n-\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n-\n-\tdir = opendir(dirname);\n-\tif (dir == NULL) {\n-\t\t/* retry with the parent directory */\n-\t\tsnprintf(dirname, sizeof(dirname),\n-\t\t\t\t\"%s/\" PCI_PRI_FMT, pci_get_sysfs_path(),\n-\t\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n-\t\tdir = opendir(dirname);\n-\n-\t\tif (dir == NULL) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Cannot opendir %s\\n\", dirname);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n-\n-\t/* take the first file starting with \"uio\" */\n-\twhile ((e = readdir(dir)) != NULL) {\n-\t\t/* format could be uio%d ...*/\n-\t\tint shortprefix_len = sizeof(\"uio\") - 1;\n-\t\t/* ... or uio:uio%d */\n-\t\tint longprefix_len = sizeof(\"uio:uio\") - 1;\n-\t\tchar *endptr;\n-\n-\t\tif (strncmp(e->d_name, \"uio\", 3) != 0)\n-\t\t\tcontinue;\n-\n-\t\t/* first try uio%d */\n-\t\terrno = 0;\n-\t\tuio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);\n-\t\tif (errno == 0 && endptr != (e->d_name + shortprefix_len)) {\n-\t\t\tsnprintf(dstbuf, buflen, \"%s/uio%u\", dirname, uio_num);\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\t/* then try uio:uio%d */\n-\t\terrno = 0;\n-\t\tuio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);\n-\t\tif (errno == 0 && endptr != (e->d_name + longprefix_len)) {\n-\t\t\tsnprintf(dstbuf, buflen, \"%s/uio:uio%u\", dirname, uio_num);\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\tclosedir(dir);\n-\n-\t/* No uio resource found */\n-\tif (e == NULL)\n-\t\treturn -1;\n-\n-\t/* create uio device if we've been asked to */\n-\tif (internal_config.create_uio_dev && create &&\n-\t\t\tpci_mknod_uio_dev(dstbuf, uio_num) < 0)\n-\t\tRTE_LOG(WARNING, EAL, \"Cannot create /dev/uio%u\\n\", uio_num);\n-\n-\treturn uio_num;\n-}\n-\n-void\n-pci_uio_free_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource *uio_res)\n-{\n-\trte_free(uio_res);\n-\n-\tif (dev->intr_handle.uio_cfg_fd >= 0) {\n-\t\tclose(dev->intr_handle.uio_cfg_fd);\n-\t\tdev->intr_handle.uio_cfg_fd = -1;\n-\t}\n-\tif (dev->intr_handle.fd >= 0) {\n-\t\tclose(dev->intr_handle.fd);\n-\t\tdev->intr_handle.fd = -1;\n-\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-\t}\n-}\n-\n-int\n-pci_uio_alloc_resource(struct rte_pci_device *dev,\n-\t\tstruct mapped_pci_resource **uio_res)\n-{\n-\tchar dirname[PATH_MAX];\n-\tchar cfgname[PATH_MAX];\n-\tchar devname[PATH_MAX]; /* contains the /dev/uioX */\n-\tint uio_num;\n-\tstruct rte_pci_addr *loc;\n-\n-\tloc = &dev->addr;\n-\n-\t/* find uio resource */\n-\tuio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1);\n-\tif (uio_num < 0) {\n-\t\tRTE_LOG(WARNING, EAL, \"  \"PCI_PRI_FMT\" not managed by UIO driver, \"\n-\t\t\t\t\"skipping\\n\", loc->domain, loc->bus, loc->devid, loc->function);\n-\t\treturn 1;\n-\t}\n-\tsnprintf(devname, sizeof(devname), \"/dev/uio%u\", uio_num);\n-\n-\t/* save fd if in primary process */\n-\tdev->intr_handle.fd = open(devname, O_RDWR);\n-\tif (dev->intr_handle.fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\tdevname, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\tsnprintf(cfgname, sizeof(cfgname),\n-\t\t\t\"/sys/class/uio/uio%u/device/config\", uio_num);\n-\tdev->intr_handle.uio_cfg_fd = open(cfgname, O_RDWR);\n-\tif (dev->intr_handle.uio_cfg_fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\tcfgname, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\tif (dev->kdrv == RTE_KDRV_IGB_UIO)\n-\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n-\telse {\n-\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO_INTX;\n-\n-\t\t/* set bus master that is not done by uio_pci_generic */\n-\t\tif (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Cannot set up bus mastering!\\n\");\n-\t\t\tgoto error;\n-\t\t}\n-\t}\n-\n-\t/* allocate the mapping details for secondary processes*/\n-\t*uio_res = rte_zmalloc(\"UIO_RES\", sizeof(**uio_res), 0);\n-\tif (*uio_res == NULL) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n-\t\tgoto error;\n-\t}\n-\n-\tsnprintf((*uio_res)->path, sizeof((*uio_res)->path), \"%s\", devname);\n-\tmemcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));\n-\n-\treturn 0;\n-\n-error:\n-\tpci_uio_free_resource(dev, *uio_res);\n-\treturn -1;\n-}\n-\n-int\n-pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,\n-\t\tstruct mapped_pci_resource *uio_res, int map_idx)\n-{\n-\tint fd;\n-\tchar devname[PATH_MAX];\n-\tvoid *mapaddr;\n-\tstruct rte_pci_addr *loc;\n-\tstruct pci_map *maps;\n-\n-\tloc = &dev->addr;\n-\tmaps = uio_res->maps;\n-\n-\t/* update devname for mmap  */\n-\tsnprintf(devname, sizeof(devname),\n-\t\t\t\"%s/\" PCI_PRI_FMT \"/resource%d\",\n-\t\t\tpci_get_sysfs_path(),\n-\t\t\tloc->domain, loc->bus, loc->devid,\n-\t\t\tloc->function, res_idx);\n-\n-\t/* allocate memory to keep path */\n-\tmaps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0);\n-\tif (maps[map_idx].path == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot allocate memory for path: %s\\n\",\n-\t\t\t\tstrerror(errno));\n-\t\treturn -1;\n-\t}\n-\n-\t/*\n-\t * open resource file, to mmap it\n-\t */\n-\tfd = open(devname, O_RDWR);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\t\tdevname, strerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\t/* try mapping somewhere close to the end of hugepages */\n-\tif (pci_map_addr == NULL)\n-\t\tpci_map_addr = pci_find_max_end_va();\n-\n-\tmapaddr = pci_map_resource(pci_map_addr, fd, 0,\n-\t\t\t(size_t)dev->mem_resource[res_idx].len, 0);\n-\tclose(fd);\n-\tif (mapaddr == MAP_FAILED)\n-\t\tgoto error;\n-\n-\tpci_map_addr = RTE_PTR_ADD(mapaddr,\n-\t\t\t(size_t)dev->mem_resource[res_idx].len);\n-\n-\tmaps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;\n-\tmaps[map_idx].size = dev->mem_resource[res_idx].len;\n-\tmaps[map_idx].addr = mapaddr;\n-\tmaps[map_idx].offset = 0;\n-\tstrcpy(maps[map_idx].path, devname);\n-\tdev->mem_resource[res_idx].addr = mapaddr;\n-\n-\treturn 0;\n-\n-error:\n-\trte_free(maps[map_idx].path);\n-\treturn -1;\n-}\n-\n-#if defined(RTE_ARCH_X86)\n-int\n-pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\t   struct rte_pci_ioport *p)\n-{\n-\tchar dirname[PATH_MAX];\n-\tchar filename[PATH_MAX];\n-\tint uio_num;\n-\tunsigned long start;\n-\n-\tuio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0);\n-\tif (uio_num < 0)\n-\t\treturn -1;\n-\n-\t/* get portio start */\n-\tsnprintf(filename, sizeof(filename),\n-\t\t \"%s/portio/port%d/start\", dirname, bar);\n-\tif (eal_parse_sysfs_value(filename, &start) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"%s(): cannot parse portio start\\n\",\n-\t\t\t__func__);\n-\t\treturn -1;\n-\t}\n-\t/* ensure we don't get anything funny here, read/write will cast to\n-\t * uin16_t */\n-\tif (start > UINT16_MAX)\n-\t\treturn -1;\n-\n-\t/* FIXME only for primary process ? */\n-\tif (dev->intr_handle.type == RTE_INTR_HANDLE_UNKNOWN) {\n-\n-\t\tsnprintf(filename, sizeof(filename), \"/dev/uio%u\", uio_num);\n-\t\tdev->intr_handle.fd = open(filename, O_RDWR);\n-\t\tif (dev->intr_handle.fd < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\",\n-\t\t\t\tfilename, strerror(errno));\n-\t\t\treturn -1;\n-\t\t}\n-\t\tdev->intr_handle.type = RTE_INTR_HANDLE_UIO;\n-\t}\n-\n-\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%lx\\n\", start);\n-\n-\tp->base = start;\n-\tp->len = 0;\n-\treturn 0;\n-}\n-#else\n-int\n-pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\t   struct rte_pci_ioport *p)\n-{\n-\tFILE *f;\n-\tchar buf[BUFSIZ];\n-\tchar filename[PATH_MAX];\n-\tuint64_t phys_addr, end_addr, flags;\n-\tint fd, i;\n-\tvoid *addr;\n-\n-\t/* open and read addresses of the corresponding resource in sysfs */\n-\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT \"/resource\",\n-\t\tpci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,\n-\t\tdev->addr.devid, dev->addr.function);\n-\tf = fopen(filename, \"r\");\n-\tif (f == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open sysfs resource: %s\\n\",\n-\t\t\tstrerror(errno));\n-\t\treturn -1;\n-\t}\n-\tfor (i = 0; i < bar + 1; i++) {\n-\t\tif (fgets(buf, sizeof(buf), f) == NULL) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Cannot read sysfs resource\\n\");\n-\t\t\tgoto error;\n-\t\t}\n-\t}\n-\tif (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,\n-\t\t\t&end_addr, &flags) < 0)\n-\t\tgoto error;\n-\tif ((flags & IORESOURCE_IO) == 0) {\n-\t\tRTE_LOG(ERR, EAL, \"BAR %d is not an IO resource\\n\", bar);\n-\t\tgoto error;\n-\t}\n-\tsnprintf(filename, sizeof(filename), \"%s/\" PCI_PRI_FMT \"/resource%d\",\n-\t\tpci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,\n-\t\tdev->addr.devid, dev->addr.function, bar);\n-\n-\t/* mmap the pci resource */\n-\tfd = open(filename, O_RDWR);\n-\tif (fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot open %s: %s\\n\", filename,\n-\t\t\tstrerror(errno));\n-\t\tgoto error;\n-\t}\n-\taddr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,\n-\t\tMAP_SHARED, fd, 0);\n-\tclose(fd);\n-\tif (addr == MAP_FAILED) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot mmap IO port resource: %s\\n\",\n-\t\t\tstrerror(errno));\n-\t\tgoto error;\n-\t}\n-\n-\t/* strangely, the base address is mmap addr + phys_addr */\n-\tp->base = (uintptr_t)addr + phys_addr;\n-\tp->len = end_addr + 1;\n-\tRTE_LOG(DEBUG, EAL, \"PCI Port IO found start=0x%\"PRIx64\"\\n\", p->base);\n-\tfclose(f);\n-\n-\treturn 0;\n-\n-error:\n-\tfclose(f);\n-\treturn -1;\n-}\n-#endif\n-\n-void\n-pci_uio_ioport_read(struct rte_pci_ioport *p,\n-\t\t    void *data, size_t len, off_t offset)\n-{\n-\tuint8_t *d;\n-\tint size;\n-\tuintptr_t reg = p->base + offset;\n-\n-\tfor (d = data; len > 0; d += size, reg += size, len -= size) {\n-\t\tif (len >= 4) {\n-\t\t\tsize = 4;\n-#if defined(RTE_ARCH_X86)\n-\t\t\t*(uint32_t *)d = inl(reg);\n-#else\n-\t\t\t*(uint32_t *)d = *(volatile uint32_t *)reg;\n-#endif\n-\t\t} else if (len >= 2) {\n-\t\t\tsize = 2;\n-#if defined(RTE_ARCH_X86)\n-\t\t\t*(uint16_t *)d = inw(reg);\n-#else\n-\t\t\t*(uint16_t *)d = *(volatile uint16_t *)reg;\n-#endif\n-\t\t} else {\n-\t\t\tsize = 1;\n-#if defined(RTE_ARCH_X86)\n-\t\t\t*d = inb(reg);\n-#else\n-\t\t\t*d = *(volatile uint8_t *)reg;\n-#endif\n-\t\t}\n-\t}\n-}\n-\n-void\n-pci_uio_ioport_write(struct rte_pci_ioport *p,\n-\t\t     const void *data, size_t len, off_t offset)\n-{\n-\tconst uint8_t *s;\n-\tint size;\n-\tuintptr_t reg = p->base + offset;\n-\n-\tfor (s = data; len > 0; s += size, reg += size, len -= size) {\n-\t\tif (len >= 4) {\n-\t\t\tsize = 4;\n-#if defined(RTE_ARCH_X86)\n-\t\t\toutl_p(*(const uint32_t *)s, reg);\n-#else\n-\t\t\t*(volatile uint32_t *)reg = *(const uint32_t *)s;\n-#endif\n-\t\t} else if (len >= 2) {\n-\t\t\tsize = 2;\n-#if defined(RTE_ARCH_X86)\n-\t\t\toutw_p(*(const uint16_t *)s, reg);\n-#else\n-\t\t\t*(volatile uint16_t *)reg = *(const uint16_t *)s;\n-#endif\n-\t\t} else {\n-\t\t\tsize = 1;\n-#if defined(RTE_ARCH_X86)\n-\t\t\toutb_p(*s, reg);\n-#else\n-\t\t\t*(volatile uint8_t *)reg = *s;\n-#endif\n-\t\t}\n-\t}\n-}\n-\n-int\n-pci_uio_ioport_unmap(struct rte_pci_ioport *p)\n-{\n-#if defined(RTE_ARCH_X86)\n-\tRTE_SET_USED(p);\n-\t/* FIXME close intr fd ? */\n-\treturn 0;\n-#else\n-\treturn munmap((void *)(uintptr_t)p->base, p->len);\n-#endif\n-}\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\ndeleted file mode 100644\nindex aa9d96e..0000000\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n+++ /dev/null\n@@ -1,674 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#include <string.h>\n-#include <fcntl.h>\n-#include <linux/pci_regs.h>\n-#include <sys/eventfd.h>\n-#include <sys/socket.h>\n-#include <sys/ioctl.h>\n-#include <sys/mman.h>\n-#include <stdbool.h>\n-\n-#include <rte_log.h>\n-#include <rte_pci.h>\n-#include <rte_eal_memconfig.h>\n-#include <rte_malloc.h>\n-\n-#include \"eal_filesystem.h\"\n-#include \"eal_pci_init.h\"\n-#include \"eal_vfio.h\"\n-#include \"eal_private.h\"\n-\n-/**\n- * @file\n- * PCI probing under linux (VFIO version)\n- *\n- * This code tries to determine if the PCI device is bound to VFIO driver,\n- * and initialize it (map BARs, set up interrupts) if that's the case.\n- *\n- * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to \"y\".\n- */\n-\n-#ifdef VFIO_PRESENT\n-\n-#define PAGE_SIZE   (sysconf(_SC_PAGESIZE))\n-#define PAGE_MASK   (~(PAGE_SIZE - 1))\n-\n-static struct rte_tailq_elem rte_vfio_tailq = {\n-\t.name = \"VFIO_RESOURCE_LIST\",\n-};\n-EAL_REGISTER_TAILQ(rte_vfio_tailq)\n-\n-int\n-pci_vfio_read_config(const struct rte_intr_handle *intr_handle,\n-\t\t    void *buf, size_t len, off_t offs)\n-{\n-\treturn pread64(intr_handle->vfio_dev_fd, buf, len,\n-\t       VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);\n-}\n-\n-int\n-pci_vfio_write_config(const struct rte_intr_handle *intr_handle,\n-\t\t    const void *buf, size_t len, off_t offs)\n-{\n-\treturn pwrite64(intr_handle->vfio_dev_fd, buf, len,\n-\t       VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);\n-}\n-\n-/* get PCI BAR number where MSI-X interrupts are */\n-static int\n-pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset,\n-\t\t      uint32_t *msix_table_size)\n-{\n-\tint ret;\n-\tuint32_t reg;\n-\tuint16_t flags;\n-\tuint8_t cap_id, cap_offset;\n-\n-\t/* read PCI capability pointer from config space */\n-\tret = pread64(fd, &reg, sizeof(reg),\n-\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\tPCI_CAPABILITY_LIST);\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot read capability pointer from PCI \"\n-\t\t\t\t\"config space!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\t/* we need first byte */\n-\tcap_offset = reg & 0xFF;\n-\n-\twhile (cap_offset) {\n-\n-\t\t/* read PCI capability ID */\n-\t\tret = pread64(fd, &reg, sizeof(reg),\n-\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\t\tcap_offset);\n-\t\tif (ret != sizeof(reg)) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Cannot read capability ID from PCI \"\n-\t\t\t\t\t\"config space!\\n\");\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\t/* we need first byte */\n-\t\tcap_id = reg & 0xFF;\n-\n-\t\t/* if we haven't reached MSI-X, check next capability */\n-\t\tif (cap_id != PCI_CAP_ID_MSIX) {\n-\t\t\tret = pread64(fd, &reg, sizeof(reg),\n-\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\t\t\tcap_offset);\n-\t\t\tif (ret != sizeof(reg)) {\n-\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read capability pointer from PCI \"\n-\t\t\t\t\t\t\"config space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\t/* we need second byte */\n-\t\t\tcap_offset = (reg & 0xFF00) >> 8;\n-\n-\t\t\tcontinue;\n-\t\t}\n-\t\t/* else, read table offset */\n-\t\telse {\n-\t\t\t/* table offset resides in the next 4 bytes */\n-\t\t\tret = pread64(fd, &reg, sizeof(reg),\n-\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\t\t\tcap_offset + 4);\n-\t\t\tif (ret != sizeof(reg)) {\n-\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read table offset from PCI config \"\n-\t\t\t\t\t\t\"space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\tret = pread64(fd, &flags, sizeof(flags),\n-\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\t\t\tcap_offset + 2);\n-\t\t\tif (ret != sizeof(flags)) {\n-\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read table flags from PCI config \"\n-\t\t\t\t\t\t\"space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\t*msix_bar = reg & RTE_PCI_MSIX_TABLE_BIR;\n-\t\t\t*msix_table_offset = reg & RTE_PCI_MSIX_TABLE_OFFSET;\n-\t\t\t*msix_table_size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE));\n-\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-/* set PCI bus mastering */\n-static int\n-pci_vfio_set_bus_master(int dev_fd, bool op)\n-{\n-\tuint16_t reg;\n-\tint ret;\n-\n-\tret = pread64(dev_fd, &reg, sizeof(reg),\n-\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\tPCI_COMMAND);\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot read command from PCI config space!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\tif (op)\n-\t\t/* set the master bit */\n-\t\treg |= PCI_COMMAND_MASTER;\n-\telse\n-\t\treg &= ~(PCI_COMMAND_MASTER);\n-\n-\tret = pwrite64(dev_fd, &reg, sizeof(reg),\n-\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n-\t\t\tPCI_COMMAND);\n-\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL, \"Cannot write command to PCI config space!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-/* set up interrupt support (but not enable interrupts) */\n-static int\n-pci_vfio_setup_interrupts(struct rte_pci_device *dev, int vfio_dev_fd)\n-{\n-\tint i, ret, intr_idx;\n-\n-\t/* default to invalid index */\n-\tintr_idx = VFIO_PCI_NUM_IRQS;\n-\n-\t/* get interrupt type from internal config (MSI-X by default, can be\n-\t * overridden from the command line\n-\t */\n-\tswitch (internal_config.vfio_intr_mode) {\n-\tcase RTE_INTR_MODE_MSIX:\n-\t\tintr_idx = VFIO_PCI_MSIX_IRQ_INDEX;\n-\t\tbreak;\n-\tcase RTE_INTR_MODE_MSI:\n-\t\tintr_idx = VFIO_PCI_MSI_IRQ_INDEX;\n-\t\tbreak;\n-\tcase RTE_INTR_MODE_LEGACY:\n-\t\tintr_idx = VFIO_PCI_INTX_IRQ_INDEX;\n-\t\tbreak;\n-\t/* don't do anything if we want to automatically determine interrupt type */\n-\tcase RTE_INTR_MODE_NONE:\n-\t\tbreak;\n-\tdefault:\n-\t\tRTE_LOG(ERR, EAL, \"  unknown default interrupt type!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\t/* start from MSI-X interrupt type */\n-\tfor (i = VFIO_PCI_MSIX_IRQ_INDEX; i >= 0; i--) {\n-\t\tstruct vfio_irq_info irq = { .argsz = sizeof(irq) };\n-\t\tint fd = -1;\n-\n-\t\t/* skip interrupt modes we don't want */\n-\t\tif (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE &&\n-\t\t\t\ti != intr_idx)\n-\t\t\tcontinue;\n-\n-\t\tirq.index = i;\n-\n-\t\tret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);\n-\t\tif (ret < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  cannot get IRQ info, \"\n-\t\t\t\t\t\"error %i (%s)\\n\", errno, strerror(errno));\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\t/* if this vector cannot be used with eventfd, fail if we explicitly\n-\t\t * specified interrupt type, otherwise continue */\n-\t\tif ((irq.flags & VFIO_IRQ_INFO_EVENTFD) == 0) {\n-\t\t\tif (internal_config.vfio_intr_mode != RTE_INTR_MODE_NONE) {\n-\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\t\"  interrupt vector does not support eventfd!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t} else\n-\t\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* set up an eventfd for interrupts */\n-\t\tfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);\n-\t\tif (fd < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  cannot set up eventfd, \"\n-\t\t\t\t\t\"error %i (%s)\\n\", errno, strerror(errno));\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\tdev->intr_handle.fd = fd;\n-\t\tdev->intr_handle.vfio_dev_fd = vfio_dev_fd;\n-\n-\t\tswitch (i) {\n-\t\tcase VFIO_PCI_MSIX_IRQ_INDEX:\n-\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_MSIX;\n-\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSIX;\n-\t\t\tbreak;\n-\t\tcase VFIO_PCI_MSI_IRQ_INDEX:\n-\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_MSI;\n-\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_MSI;\n-\t\t\tbreak;\n-\t\tcase VFIO_PCI_INTX_IRQ_INDEX:\n-\t\t\tinternal_config.vfio_intr_mode = RTE_INTR_MODE_LEGACY;\n-\t\t\tdev->intr_handle.type = RTE_INTR_HANDLE_VFIO_LEGACY;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tRTE_LOG(ERR, EAL, \"  unknown interrupt type!\\n\");\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\treturn 0;\n-\t}\n-\n-\t/* if we're here, we haven't found a suitable interrupt vector */\n-\treturn -1;\n-}\n-\n-/*\n- * map the PCI resources of a PCI device in virtual memory (VFIO version).\n- * primary and secondary processes follow almost exactly the same path\n- */\n-int\n-pci_vfio_map_resource(struct rte_pci_device *dev)\n-{\n-\tstruct vfio_device_info device_info = { .argsz = sizeof(device_info) };\n-\tchar pci_addr[PATH_MAX] = {0};\n-\tint vfio_dev_fd;\n-\tstruct rte_pci_addr *loc = &dev->addr;\n-\tint i, ret, msix_bar;\n-\tstruct mapped_pci_resource *vfio_res = NULL;\n-\tstruct mapped_pci_res_list *vfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);\n-\n-\tstruct pci_map *maps;\n-\tuint32_t msix_table_offset = 0;\n-\tuint32_t msix_table_size = 0;\n-\tuint32_t ioport_bar;\n-\n-\tdev->intr_handle.fd = -1;\n-\tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n-\n-\t/* store PCI address string */\n-\tsnprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,\n-\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n-\n-\tif ((ret = vfio_setup_device(pci_get_sysfs_path(), pci_addr,\n-\t\t\t\t\t&vfio_dev_fd, &device_info)))\n-\t\treturn ret;\n-\n-\t/* get MSI-X BAR, if any (we have to know where it is because we can't\n-\t * easily mmap it when using VFIO) */\n-\tmsix_bar = -1;\n-\tret = pci_vfio_get_msix_bar(vfio_dev_fd, &msix_bar,\n-\t\t\t\t    &msix_table_offset, &msix_table_size);\n-\tif (ret < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"  %s cannot get MSI-X BAR number!\\n\", pci_addr);\n-\t\tclose(vfio_dev_fd);\n-\t\treturn -1;\n-\t}\n-\n-\t/* if we're in a primary process, allocate vfio_res and get region info */\n-\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n-\t\tvfio_res = rte_zmalloc(\"VFIO_RES\", sizeof(*vfio_res), 0);\n-\t\tif (vfio_res == NULL) {\n-\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"%s(): cannot store uio mmap details\\n\", __func__);\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\treturn -1;\n-\t\t}\n-\t\tmemcpy(&vfio_res->pci_addr, &dev->addr, sizeof(vfio_res->pci_addr));\n-\n-\t\t/* get number of registers (up to BAR5) */\n-\t\tvfio_res->nb_maps = RTE_MIN((int) device_info.num_regions,\n-\t\t\t\tVFIO_PCI_BAR5_REGION_INDEX + 1);\n-\t} else {\n-\t\t/* if we're in a secondary process, just find our tailq entry */\n-\t\tTAILQ_FOREACH(vfio_res, vfio_res_list, next) {\n-\t\t\tif (rte_eal_compare_pci_addr(&vfio_res->pci_addr,\n-\t\t\t\t\t\t     &dev->addr))\n-\t\t\t\tcontinue;\n-\t\t\tbreak;\n-\t\t}\n-\t\t/* if we haven't found our tailq entry, something's wrong */\n-\t\tif (vfio_res == NULL) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot find TAILQ entry for PCI device!\\n\",\n-\t\t\t\t\tpci_addr);\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n-\n-\t/* map BARs */\n-\tmaps = vfio_res->maps;\n-\n-\tfor (i = 0; i < (int) vfio_res->nb_maps; i++) {\n-\t\tstruct vfio_region_info reg = { .argsz = sizeof(reg) };\n-\t\tvoid *bar_addr;\n-\t\tstruct memreg {\n-\t\t\tunsigned long offset, size;\n-\t\t} memreg[2] = {};\n-\n-\t\treg.index = i;\n-\n-\t\tret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, &reg);\n-\n-\t\tif (ret) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot get device region info \"\n-\t\t\t\t\t\"error %i (%s)\\n\", pci_addr, errno, strerror(errno));\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n-\t\t\t\trte_free(vfio_res);\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\t/* chk for io port region */\n-\t\tret = pread64(vfio_dev_fd, &ioport_bar, sizeof(ioport_bar),\n-\t\t\t      VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX)\n-\t\t\t      + PCI_BASE_ADDRESS_0 + i*4);\n-\n-\t\tif (ret != sizeof(ioport_bar)) {\n-\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"Cannot read command (%x) from config space!\\n\",\n-\t\t\t\tPCI_BASE_ADDRESS_0 + i*4);\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\tif (ioport_bar & PCI_BASE_ADDRESS_SPACE_IO) {\n-\t\t\tRTE_LOG(INFO, EAL,\n-\t\t\t\t\"Ignore mapping IO port bar(%d) addr: %x\\n\",\n-\t\t\t\t i, ioport_bar);\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* skip non-mmapable BARs */\n-\t\tif ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0)\n-\t\t\tcontinue;\n-\n-\t\tif (i == msix_bar) {\n-\t\t\t/*\n-\t\t\t * VFIO will not let us map the MSI-X table,\n-\t\t\t * but we can map around it.\n-\t\t\t */\n-\t\t\tuint32_t table_start = msix_table_offset;\n-\t\t\tuint32_t table_end = table_start + msix_table_size;\n-\t\t\ttable_end = (table_end + ~PAGE_MASK) & PAGE_MASK;\n-\t\t\ttable_start &= PAGE_MASK;\n-\n-\t\t\tif (table_start == 0 && table_end >= reg.size) {\n-\t\t\t\t/* Cannot map this BAR */\n-\t\t\t\tRTE_LOG(DEBUG, EAL, \"Skipping BAR %d\\n\", i);\n-\t\t\t\tcontinue;\n-\t\t\t} else {\n-\t\t\t\tmemreg[0].offset = reg.offset;\n-\t\t\t\tmemreg[0].size = table_start;\n-\t\t\t\tmemreg[1].offset = reg.offset + table_end;\n-\t\t\t\tmemreg[1].size = reg.size - table_end;\n-\n-\t\t\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\t\t\"Trying to map BAR %d that contains the MSI-X \"\n-\t\t\t\t\t\"table. Trying offsets: \"\n-\t\t\t\t\t\"0x%04lx:0x%04lx, 0x%04lx:0x%04lx\\n\", i,\n-\t\t\t\t\tmemreg[0].offset, memreg[0].size,\n-\t\t\t\t\tmemreg[1].offset, memreg[1].size);\n-\t\t\t}\n-\t\t} else {\n-\t\t\tmemreg[0].offset = reg.offset;\n-\t\t\tmemreg[0].size = reg.size;\n-\t\t}\n-\n-\t\t/* try to figure out an address */\n-\t\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n-\t\t\t/* try mapping somewhere close to the end of hugepages */\n-\t\t\tif (pci_map_addr == NULL)\n-\t\t\t\tpci_map_addr = pci_find_max_end_va();\n-\n-\t\t\tbar_addr = pci_map_addr;\n-\t\t\tpci_map_addr = RTE_PTR_ADD(bar_addr, (size_t) reg.size);\n-\t\t} else {\n-\t\t\tbar_addr = maps[i].addr;\n-\t\t}\n-\n-\t\t/* reserve the address using an inaccessible mapping */\n-\t\tbar_addr = mmap(bar_addr, reg.size, 0, MAP_PRIVATE |\n-\t\t\t\tMAP_ANONYMOUS, -1, 0);\n-\t\tif (bar_addr != MAP_FAILED) {\n-\t\t\tvoid *map_addr = NULL;\n-\t\t\tif (memreg[0].size) {\n-\t\t\t\t/* actual map of first part */\n-\t\t\t\tmap_addr = pci_map_resource(bar_addr, vfio_dev_fd,\n-\t\t\t\t\t\t\t    memreg[0].offset,\n-\t\t\t\t\t\t\t    memreg[0].size,\n-\t\t\t\t\t\t\t    MAP_FIXED);\n-\t\t\t}\n-\n-\t\t\t/* if there's a second part, try to map it */\n-\t\t\tif (map_addr != MAP_FAILED\n-\t\t\t    && memreg[1].offset && memreg[1].size) {\n-\t\t\t\tvoid *second_addr = RTE_PTR_ADD(bar_addr,\n-\t\t\t\t\t\t\t\tmemreg[1].offset -\n-\t\t\t\t\t\t\t\t(uintptr_t)reg.offset);\n-\t\t\t\tmap_addr = pci_map_resource(second_addr,\n-\t\t\t\t\t\t\t    vfio_dev_fd, memreg[1].offset,\n-\t\t\t\t\t\t\t    memreg[1].size,\n-\t\t\t\t\t\t\t    MAP_FIXED);\n-\t\t\t}\n-\n-\t\t\tif (map_addr == MAP_FAILED || !map_addr) {\n-\t\t\t\tmunmap(bar_addr, reg.size);\n-\t\t\t\tbar_addr = MAP_FAILED;\n-\t\t\t}\n-\t\t}\n-\n-\t\tif (bar_addr == MAP_FAILED ||\n-\t\t\t\t(internal_config.process_type == RTE_PROC_SECONDARY &&\n-\t\t\t\t\t\tbar_addr != maps[i].addr)) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  %s mapping BAR%i failed: %s\\n\", pci_addr, i,\n-\t\t\t\t\tstrerror(errno));\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n-\t\t\t\trte_free(vfio_res);\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\tmaps[i].addr = bar_addr;\n-\t\tmaps[i].offset = reg.offset;\n-\t\tmaps[i].size = reg.size;\n-\t\tmaps[i].path = NULL; /* vfio doesn't have per-resource paths */\n-\t\tdev->mem_resource[i].addr = bar_addr;\n-\t}\n-\n-\t/* if secondary process, do not set up interrupts */\n-\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n-\t\tif (pci_vfio_setup_interrupts(dev, vfio_dev_fd) != 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  %s error setting up interrupts!\\n\", pci_addr);\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\trte_free(vfio_res);\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\t/* set bus mastering for the device */\n-\t\tif (pci_vfio_set_bus_master(vfio_dev_fd, true)) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  %s cannot set up bus mastering!\\n\", pci_addr);\n-\t\t\tclose(vfio_dev_fd);\n-\t\t\trte_free(vfio_res);\n-\t\t\treturn -1;\n-\t\t}\n-\n-\t\t/* Reset the device */\n-\t\tioctl(vfio_dev_fd, VFIO_DEVICE_RESET);\n-\t}\n-\n-\tif (internal_config.process_type == RTE_PROC_PRIMARY)\n-\t\tTAILQ_INSERT_TAIL(vfio_res_list, vfio_res, next);\n-\n-\treturn 0;\n-}\n-\n-int\n-pci_vfio_unmap_resource(struct rte_pci_device *dev)\n-{\n-\tchar pci_addr[PATH_MAX] = {0};\n-\tstruct rte_pci_addr *loc = &dev->addr;\n-\tint i, ret;\n-\tstruct mapped_pci_resource *vfio_res = NULL;\n-\tstruct mapped_pci_res_list *vfio_res_list;\n-\n-\tstruct pci_map *maps;\n-\n-\t/* store PCI address string */\n-\tsnprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,\n-\t\t\tloc->domain, loc->bus, loc->devid, loc->function);\n-\n-\n-\tif (close(dev->intr_handle.fd) < 0) {\n-\t\tRTE_LOG(INFO, EAL, \"Error when closing eventfd file descriptor for %s\\n\",\n-\t\t\tpci_addr);\n-\t\treturn -1;\n-\t}\n-\n-\tif (pci_vfio_set_bus_master(dev->intr_handle.vfio_dev_fd, false)) {\n-\t\tRTE_LOG(ERR, EAL, \"  %s cannot unset bus mastering for PCI device!\\n\",\n-\t\t\t\tpci_addr);\n-\t\treturn -1;\n-\t}\n-\n-\tret = vfio_release_device(pci_get_sysfs_path(), pci_addr,\n-\t\t\t\t  dev->intr_handle.vfio_dev_fd);\n-\tif (ret < 0) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"%s(): cannot release device\\n\", __func__);\n-\t\treturn ret;\n-\t}\n-\n-\tvfio_res_list = RTE_TAILQ_CAST(rte_vfio_tailq.head, mapped_pci_res_list);\n-\t/* Get vfio_res */\n-\tTAILQ_FOREACH(vfio_res, vfio_res_list, next) {\n-\t\tif (memcmp(&vfio_res->pci_addr, &dev->addr, sizeof(dev->addr)))\n-\t\t\tcontinue;\n-\t\tbreak;\n-\t}\n-\t/* if we haven't found our tailq entry, something's wrong */\n-\tif (vfio_res == NULL) {\n-\t\tRTE_LOG(ERR, EAL, \"  %s cannot find TAILQ entry for PCI device!\\n\",\n-\t\t\t\tpci_addr);\n-\t\treturn -1;\n-\t}\n-\n-\t/* unmap BARs */\n-\tmaps = vfio_res->maps;\n-\n-\tRTE_LOG(INFO, EAL, \"Releasing pci mapped resource for %s\\n\",\n-\t\tpci_addr);\n-\tfor (i = 0; i < (int) vfio_res->nb_maps; i++) {\n-\n-\t\t/*\n-\t\t * We do not need to be aware of MSI-X table BAR mappings as\n-\t\t * when mapping. Just using current maps array is enough\n-\t\t */\n-\t\tif (maps[i].addr) {\n-\t\t\tRTE_LOG(INFO, EAL, \"Calling pci_unmap_resource for %s at %p\\n\",\n-\t\t\t\tpci_addr, maps[i].addr);\n-\t\t\tpci_unmap_resource(maps[i].addr, maps[i].size);\n-\t\t}\n-\t}\n-\n-\tTAILQ_REMOVE(vfio_res_list, vfio_res, next);\n-\n-\treturn 0;\n-}\n-\n-int\n-pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,\n-\t\t    struct rte_pci_ioport *p)\n-{\n-\tif (bar < VFIO_PCI_BAR0_REGION_INDEX ||\n-\t    bar > VFIO_PCI_BAR5_REGION_INDEX) {\n-\t\tRTE_LOG(ERR, EAL, \"invalid bar (%d)!\\n\", bar);\n-\t\treturn -1;\n-\t}\n-\n-\tp->dev = dev;\n-\tp->base = VFIO_GET_REGION_ADDR(bar);\n-\treturn 0;\n-}\n-\n-void\n-pci_vfio_ioport_read(struct rte_pci_ioport *p,\n-\t\t     void *data, size_t len, off_t offset)\n-{\n-\tconst struct rte_intr_handle *intr_handle = &p->dev->intr_handle;\n-\n-\tif (pread64(intr_handle->vfio_dev_fd, data,\n-\t\t    len, p->base + offset) <= 0)\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Can't read from PCI bar (%\" PRIu64 \") : offset (%x)\\n\",\n-\t\t\tVFIO_GET_REGION_IDX(p->base), (int)offset);\n-}\n-\n-void\n-pci_vfio_ioport_write(struct rte_pci_ioport *p,\n-\t\t      const void *data, size_t len, off_t offset)\n-{\n-\tconst struct rte_intr_handle *intr_handle = &p->dev->intr_handle;\n-\n-\tif (pwrite64(intr_handle->vfio_dev_fd, data,\n-\t\t     len, p->base + offset) <= 0)\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Can't write to PCI bar (%\" PRIu64 \") : offset (%x)\\n\",\n-\t\t\tVFIO_GET_REGION_IDX(p->base), (int)offset);\n-}\n-\n-int\n-pci_vfio_ioport_unmap(struct rte_pci_ioport *p)\n-{\n-\tRTE_SET_USED(p);\n-\treturn -1;\n-}\n-\n-int\n-pci_vfio_enable(void)\n-{\n-\treturn vfio_enable(\"vfio_pci\");\n-}\n-\n-int\n-pci_vfio_is_enabled(void)\n-{\n-\treturn vfio_is_enabled(\"vfio_pci\");\n-}\n-#endif\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c b/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c\ndeleted file mode 100644\nindex 7e8095c..0000000\n--- a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c\n+++ /dev/null\n@@ -1,424 +0,0 @@\n-/*-\n- *   BSD LICENSE\n- *\n- *   Copyright(c) 2010-2014 Intel Corporation. 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-\n-#include <string.h>\n-#include <fcntl.h>\n-#include <sys/socket.h>\n-#include <pthread.h>\n-\n-/* sys/un.h with __USE_MISC uses strlen, which is unsafe */\n-#ifdef __USE_MISC\n-#define REMOVED_USE_MISC\n-#undef __USE_MISC\n-#endif\n-#include <sys/un.h>\n-/* make sure we redefine __USE_MISC only if it was previously undefined */\n-#ifdef REMOVED_USE_MISC\n-#define __USE_MISC\n-#undef REMOVED_USE_MISC\n-#endif\n-\n-#include <rte_log.h>\n-#include <rte_pci.h>\n-#include <rte_eal_memconfig.h>\n-#include <rte_malloc.h>\n-\n-#include \"eal_filesystem.h\"\n-#include \"eal_pci_init.h\"\n-#include \"eal_thread.h\"\n-\n-/**\n- * @file\n- * VFIO socket for communication between primary and secondary processes.\n- *\n- * This file is only compiled if CONFIG_RTE_EAL_VFIO is set to \"y\".\n- */\n-\n-#ifdef VFIO_PRESENT\n-\n-#define SOCKET_PATH_FMT \"%s/.%s_mp_socket\"\n-#define CMSGLEN (CMSG_LEN(sizeof(int)))\n-#define FD_TO_CMSGHDR(fd, chdr) \\\n-\t\tdo {\\\n-\t\t\t(chdr).cmsg_len = CMSGLEN;\\\n-\t\t\t(chdr).cmsg_level = SOL_SOCKET;\\\n-\t\t\t(chdr).cmsg_type = SCM_RIGHTS;\\\n-\t\t\tmemcpy((chdr).__cmsg_data, &(fd), sizeof(fd));\\\n-\t\t} while (0)\n-#define CMSGHDR_TO_FD(chdr, fd) \\\n-\t\t\tmemcpy(&(fd), (chdr).__cmsg_data, sizeof(fd))\n-\n-static pthread_t socket_thread;\n-static int mp_socket_fd;\n-\n-\n-/* get socket path (/var/run if root, $HOME otherwise) */\n-static void\n-get_socket_path(char *buffer, int bufsz)\n-{\n-\tconst char *dir = \"/var/run\";\n-\tconst char *home_dir = getenv(\"HOME\");\n-\n-\tif (getuid() != 0 && home_dir != NULL)\n-\t\tdir = home_dir;\n-\n-\t/* use current prefix as file path */\n-\tsnprintf(buffer, bufsz, SOCKET_PATH_FMT, dir,\n-\t\t\tinternal_config.hugefile_prefix);\n-}\n-\n-\n-\n-/*\n- * data flow for socket comm protocol:\n- * 1. client sends SOCKET_REQ_CONTAINER or SOCKET_REQ_GROUP\n- * 1a. in case of SOCKET_REQ_GROUP, client also then sends group number\n- * 2. server receives message\n- * 2a. in case of invalid group, SOCKET_ERR is sent back to client\n- * 2b. in case of unbound group, SOCKET_NO_FD is sent back to client\n- * 2c. in case of valid group, SOCKET_OK is sent and immediately followed by fd\n- *\n- * in case of any error, socket is closed.\n- */\n-\n-/* send a request, return -1 on error */\n-int\n-vfio_mp_sync_send_request(int socket, int req)\n-{\n-\tstruct msghdr hdr;\n-\tstruct iovec iov;\n-\tint buf;\n-\tint ret;\n-\n-\tmemset(&hdr, 0, sizeof(hdr));\n-\n-\tbuf = req;\n-\n-\thdr.msg_iov = &iov;\n-\thdr.msg_iovlen = 1;\n-\tiov.iov_base = (char *) &buf;\n-\tiov.iov_len = sizeof(buf);\n-\n-\tret = sendmsg(socket, &hdr, 0);\n-\tif (ret < 0)\n-\t\treturn -1;\n-\treturn 0;\n-}\n-\n-/* receive a request and return it */\n-int\n-vfio_mp_sync_receive_request(int socket)\n-{\n-\tint buf;\n-\tstruct msghdr hdr;\n-\tstruct iovec iov;\n-\tint ret, req;\n-\n-\tmemset(&hdr, 0, sizeof(hdr));\n-\n-\tbuf = SOCKET_ERR;\n-\n-\thdr.msg_iov = &iov;\n-\thdr.msg_iovlen = 1;\n-\tiov.iov_base = (char *) &buf;\n-\tiov.iov_len = sizeof(buf);\n-\n-\tret = recvmsg(socket, &hdr, 0);\n-\tif (ret < 0)\n-\t\treturn -1;\n-\n-\treq = buf;\n-\n-\treturn req;\n-}\n-\n-/* send OK in message, fd in control message */\n-int\n-vfio_mp_sync_send_fd(int socket, int fd)\n-{\n-\tint buf;\n-\tstruct msghdr hdr;\n-\tstruct cmsghdr *chdr;\n-\tchar chdr_buf[CMSGLEN];\n-\tstruct iovec iov;\n-\tint ret;\n-\n-\tchdr = (struct cmsghdr *) chdr_buf;\n-\tmemset(chdr, 0, sizeof(chdr_buf));\n-\tmemset(&hdr, 0, sizeof(hdr));\n-\n-\thdr.msg_iov = &iov;\n-\thdr.msg_iovlen = 1;\n-\tiov.iov_base = (char *) &buf;\n-\tiov.iov_len = sizeof(buf);\n-\thdr.msg_control = chdr;\n-\thdr.msg_controllen = CMSGLEN;\n-\n-\tbuf = SOCKET_OK;\n-\tFD_TO_CMSGHDR(fd, *chdr);\n-\n-\tret = sendmsg(socket, &hdr, 0);\n-\tif (ret < 0)\n-\t\treturn -1;\n-\treturn 0;\n-}\n-\n-/* receive OK in message, fd in control message */\n-int\n-vfio_mp_sync_receive_fd(int socket)\n-{\n-\tint buf;\n-\tstruct msghdr hdr;\n-\tstruct cmsghdr *chdr;\n-\tchar chdr_buf[CMSGLEN];\n-\tstruct iovec iov;\n-\tint ret, req, fd;\n-\n-\tbuf = SOCKET_ERR;\n-\n-\tchdr = (struct cmsghdr *) chdr_buf;\n-\tmemset(chdr, 0, sizeof(chdr_buf));\n-\tmemset(&hdr, 0, sizeof(hdr));\n-\n-\thdr.msg_iov = &iov;\n-\thdr.msg_iovlen = 1;\n-\tiov.iov_base = (char *) &buf;\n-\tiov.iov_len = sizeof(buf);\n-\thdr.msg_control = chdr;\n-\thdr.msg_controllen = CMSGLEN;\n-\n-\tret = recvmsg(socket, &hdr, 0);\n-\tif (ret < 0)\n-\t\treturn -1;\n-\n-\treq = buf;\n-\n-\tif (req != SOCKET_OK)\n-\t\treturn -1;\n-\n-\tCMSGHDR_TO_FD(*chdr, fd);\n-\n-\treturn fd;\n-}\n-\n-/* connect socket_fd in secondary process to the primary process's socket */\n-int\n-vfio_mp_sync_connect_to_primary(void)\n-{\n-\tstruct sockaddr_un addr;\n-\tsocklen_t sockaddr_len;\n-\tint socket_fd;\n-\n-\t/* set up a socket */\n-\tsocket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n-\tif (socket_fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Failed to create socket!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\tget_socket_path(addr.sun_path, sizeof(addr.sun_path));\n-\taddr.sun_family = AF_UNIX;\n-\n-\tsockaddr_len = sizeof(struct sockaddr_un);\n-\n-\tif (connect(socket_fd, (struct sockaddr *) &addr, sockaddr_len) == 0)\n-\t\treturn socket_fd;\n-\n-\t/* if connect failed */\n-\tclose(socket_fd);\n-\treturn -1;\n-}\n-\n-\n-\n-/*\n- * socket listening thread for primary process\n- */\n-static __attribute__((noreturn)) void *\n-vfio_mp_sync_thread(void __rte_unused * arg)\n-{\n-\tint ret, fd, vfio_data;\n-\n-\t/* wait for requests on the socket */\n-\tfor (;;) {\n-\t\tint conn_sock;\n-\t\tstruct sockaddr_un addr;\n-\t\tsocklen_t sockaddr_len = sizeof(addr);\n-\n-\t\t/* this is a blocking call */\n-\t\tconn_sock = accept(mp_socket_fd, (struct sockaddr *) &addr,\n-\t\t\t\t&sockaddr_len);\n-\n-\t\t/* just restart on error */\n-\t\tif (conn_sock == -1)\n-\t\t\tcontinue;\n-\n-\t\t/* set socket to linger after close */\n-\t\tstruct linger l;\n-\t\tl.l_onoff = 1;\n-\t\tl.l_linger = 60;\n-\n-\t\tif (setsockopt(conn_sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0)\n-\t\t\tRTE_LOG(WARNING, EAL, \"Cannot set SO_LINGER option \"\n-\t\t\t\t\t\"on listen socket (%s)\\n\", strerror(errno));\n-\n-\t\tret = vfio_mp_sync_receive_request(conn_sock);\n-\n-\t\tswitch (ret) {\n-\t\tcase SOCKET_REQ_CONTAINER:\n-\t\t\tfd = vfio_get_container_fd();\n-\t\t\tif (fd < 0)\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n-\t\t\telse\n-\t\t\t\tvfio_mp_sync_send_fd(conn_sock, fd);\n-\t\t\tclose(fd);\n-\t\t\tbreak;\n-\t\tcase SOCKET_REQ_GROUP:\n-\t\t\t/* wait for group number */\n-\t\t\tvfio_data = vfio_mp_sync_receive_request(conn_sock);\n-\t\t\tif (vfio_data < 0) {\n-\t\t\t\tclose(conn_sock);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tfd = vfio_get_group_fd(vfio_data);\n-\n-\t\t\tif (fd < 0)\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n-\t\t\t/* if VFIO group exists but isn't bound to VFIO driver */\n-\t\t\telse if (fd == 0)\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD);\n-\t\t\t/* if group exists and is bound to VFIO driver */\n-\t\t\telse {\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_OK);\n-\t\t\t\tvfio_mp_sync_send_fd(conn_sock, fd);\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase SOCKET_CLR_GROUP:\n-\t\t\t/* wait for group fd */\n-\t\t\tvfio_data = vfio_mp_sync_receive_request(conn_sock);\n-\t\t\tif (vfio_data < 0) {\n-\t\t\t\tclose(conn_sock);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\n-\t\t\tret = clear_group(vfio_data);\n-\n-\t\t\tif (ret < 0)\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_NO_FD);\n-\t\t\telse\n-\t\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_OK);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tvfio_mp_sync_send_request(conn_sock, SOCKET_ERR);\n-\t\t\tbreak;\n-\t\t}\n-\t\tclose(conn_sock);\n-\t}\n-}\n-\n-static int\n-vfio_mp_sync_socket_setup(void)\n-{\n-\tint ret, socket_fd;\n-\tstruct sockaddr_un addr;\n-\tsocklen_t sockaddr_len;\n-\n-\t/* set up a socket */\n-\tsocket_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);\n-\tif (socket_fd < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Failed to create socket!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\tget_socket_path(addr.sun_path, sizeof(addr.sun_path));\n-\taddr.sun_family = AF_UNIX;\n-\n-\tsockaddr_len = sizeof(struct sockaddr_un);\n-\n-\tunlink(addr.sun_path);\n-\n-\tret = bind(socket_fd, (struct sockaddr *) &addr, sockaddr_len);\n-\tif (ret) {\n-\t\tRTE_LOG(ERR, EAL, \"Failed to bind socket: %s!\\n\", strerror(errno));\n-\t\tclose(socket_fd);\n-\t\treturn -1;\n-\t}\n-\n-\tret = listen(socket_fd, 50);\n-\tif (ret) {\n-\t\tRTE_LOG(ERR, EAL, \"Failed to listen: %s!\\n\", strerror(errno));\n-\t\tclose(socket_fd);\n-\t\treturn -1;\n-\t}\n-\n-\t/* save the socket in local configuration */\n-\tmp_socket_fd = socket_fd;\n-\n-\treturn 0;\n-}\n-\n-/*\n- * set up a local socket and tell it to listen for incoming connections\n- */\n-int\n-vfio_mp_sync_setup(void)\n-{\n-\tint ret;\n-\tchar thread_name[RTE_MAX_THREAD_NAME_LEN];\n-\n-\tif (vfio_mp_sync_socket_setup() < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Failed to set up local socket!\\n\");\n-\t\treturn -1;\n-\t}\n-\n-\tret = pthread_create(&socket_thread, NULL,\n-\t\t\tvfio_mp_sync_thread, NULL);\n-\tif (ret) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Failed to create thread for communication with secondary processes!\\n\");\n-\t\tclose(mp_socket_fd);\n-\t\treturn -1;\n-\t}\n-\n-\t/* Set thread_name for aid in debugging. */\n-\tsnprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, \"vfio-sync\");\n-\tret = rte_thread_setname(socket_thread, thread_name);\n-\tif (ret)\n-\t\tRTE_LOG(DEBUG, EAL,\n-\t\t\t\"Failed to set thread name for secondary processes!\\n\");\n-\n-\treturn 0;\n-}\n-\n-#endif\ndiff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\nindex f866b70..0dc23bf 100644\n--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n@@ -174,21 +174,6 @@ DPDK_17.05 {\n \trte_log_set_global_level;\n \trte_log_set_level;\n \trte_log_set_level_regexp;\n-\trte_pci_detach;\n-\trte_pci_dump;\n-\trte_pci_ioport_map;\n-\trte_pci_ioport_read;\n-\trte_pci_ioport_unmap;\n-\trte_pci_ioport_write;\n-\trte_pci_map_device;\n-\trte_pci_probe;\n-\trte_pci_probe_one;\n-\trte_pci_read_config;\n-\trte_pci_register;\n-\trte_pci_scan;\n-\trte_pci_unmap_device;\n-\trte_pci_unregister;\n-\trte_pci_write_config;\n \trte_vdev_init;\n \trte_vdev_register;\n \trte_vdev_uninit;\ndiff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h\nindex 99cdd54..af7af0a 100644\n--- a/lib/librte_ether/rte_ethdev.h\n+++ b/lib/librte_ether/rte_ethdev.h\n@@ -1076,8 +1076,6 @@ TAILQ_HEAD(rte_eth_dev_cb_list, rte_eth_dev_callback);\n \t} \\\n } while (0)\n \n-#define RTE_ETH_DEV_TO_PCI(eth_dev)\tRTE_DEV_TO_PCI((eth_dev)->device)\n-\n /**\n  * l2 tunnel configuration.\n  */\ndiff --git a/lib/librte_pci/Makefile b/lib/librte_pci/Makefile\nnew file mode 100644\nindex 0000000..fc2fadb\n--- /dev/null\n+++ b/lib/librte_pci/Makefile\n@@ -0,0 +1,48 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2017 6WIND S.A.\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 6WIND 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+# library name\n+LIB = librte_pci.a\n+\n+CFLAGS := -I$(SRCDIR)/include -I$(SRCDIR) $(CFLAGS)\n+CFLAGS += $(WERROR_FLAGS) -O3\n+\n+EXPORT_MAP := rte_pci_version.map\n+\n+LIBABIVER := 1\n+\n+SRCS-$(CONFIG_RTE_LIBRTE_PCI) += rte_pci.c\n+\n+SYMLINK-$(CONFIG_RTE_LIBRTE_PCI)-include += include/rte_pci.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_pci/include/rte_pci.h b/lib/librte_pci/include/rte_pci.h\nnew file mode 100644\nindex 0000000..3858e80\n--- /dev/null\n+++ b/lib/librte_pci/include/rte_pci.h\n@@ -0,0 +1,279 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+ *   Copyright 2013-2014 6WIND S.A.\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+\n+#ifndef _RTE_PCI_H_\n+#define _RTE_PCI_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE PCI Library\n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <limits.h>\n+#include <errno.h>\n+#include <sys/queue.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+\n+#include <rte_debug.h>\n+#include <rte_interrupts.h>\n+\n+/** Formatting string for PCI device identifier: Ex: 0000:00:01.0 */\n+#define PCI_PRI_FMT \"%.4\" PRIx16 \":%.2\" PRIx8 \":%.2\" PRIx8 \".%\" PRIx8\n+#define PCI_PRI_STR_SIZE sizeof(\"XXXXXXXX:XX:XX.X\")\n+\n+/** Short formatting string, without domain, for PCI device: Ex: 00:01.0 */\n+#define PCI_SHORT_PRI_FMT \"%.2\" PRIx8 \":%.2\" PRIx8 \".%\" PRIx8\n+\n+/** Nb. of values in PCI device identifier format string. */\n+#define PCI_FMT_NVAL 4\n+\n+/** Nb. of values in PCI resource format. */\n+#define PCI_RESOURCE_FMT_NVAL 3\n+\n+/** Maximum number of PCI resources. */\n+#define PCI_MAX_RESOURCE 6\n+\n+/**\n+ * A structure describing an ID for a PCI driver. Each driver provides a\n+ * table of these IDs for each device that it supports.\n+ */\n+struct rte_pci_id {\n+\tuint32_t class_id;            /**< Class ID or RTE_CLASS_ANY_ID. */\n+\tuint16_t vendor_id;           /**< Vendor ID or PCI_ANY_ID. */\n+\tuint16_t device_id;           /**< Device ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */\n+};\n+\n+/**\n+ * A structure describing the location of a PCI device.\n+ */\n+struct rte_pci_addr {\n+\tuint32_t domain;                /**< Device domain */\n+\tuint8_t bus;                    /**< Device bus */\n+\tuint8_t devid;                  /**< Device ID */\n+\tuint8_t function;               /**< Device function. */\n+};\n+\n+/** Any PCI device identifier (vendor, device, ...) */\n+#define PCI_ANY_ID (0xffff)\n+#define RTE_CLASS_ANY_ID (0xffffff)\n+\n+/**\n+ * A structure describing a PCI mapping.\n+ */\n+struct pci_map {\n+\tvoid *addr;\n+\tchar *path;\n+\tuint64_t offset;\n+\tuint64_t size;\n+\tuint64_t phaddr;\n+};\n+\n+/**\n+ * A structure describing a mapped PCI resource.\n+ * For multi-process we need to reproduce all PCI mappings in secondary\n+ * processes, so save them in a tailq.\n+ */\n+struct mapped_pci_resource {\n+\tTAILQ_ENTRY(mapped_pci_resource) next;\n+\n+\tstruct rte_pci_addr pci_addr;\n+\tchar path[PATH_MAX];\n+\tint nb_maps;\n+\tstruct pci_map maps[PCI_MAX_RESOURCE];\n+};\n+\n+/** mapped pci device list */\n+TAILQ_HEAD(mapped_pci_res_list, mapped_pci_resource);\n+\n+/**< Internal use only - Macro used by pci addr parsing functions **/\n+#define GET_PCIADDR_FIELD(in, fd, lim, dlm)                   \\\n+do {                                                               \\\n+\tunsigned long val;                                      \\\n+\tchar *end;                                              \\\n+\terrno = 0;                                              \\\n+\tval = strtoul((in), &end, 16);                          \\\n+\tif (errno != 0 || end[0] != (dlm) || val > (lim))       \\\n+\t\treturn -EINVAL;                                 \\\n+\t(fd) = (typeof (fd))val;                                \\\n+\t(in) = end + 1;                                         \\\n+} while(0)\n+\n+/**\n+ * Utility function to produce a PCI Bus-Device-Function value\n+ * given a string representation. Assumes that the BDF is provided without\n+ * a domain prefix (i.e. domain returned is always 0)\n+ *\n+ * @param input\n+ *\tThe input string to be parsed. Should have the format XX:XX.X\n+ * @param dev_addr\n+ *\tThe PCI Bus-Device-Function address to be returned. Domain will always be\n+ *\treturned as 0\n+ * @return\n+ *  0 on success, negative on error.\n+ */\n+static inline int\n+eal_parse_pci_BDF(const char *input, struct rte_pci_addr *dev_addr)\n+{\n+\tdev_addr->domain = 0;\n+\tGET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':');\n+\tGET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.');\n+\tGET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0);\n+\treturn 0;\n+}\n+\n+/**\n+ * Utility function to produce a PCI Bus-Device-Function value\n+ * given a string representation. Assumes that the BDF is provided including\n+ * a domain prefix.\n+ *\n+ * @param input\n+ *\tThe input string to be parsed. Should have the format XXXX:XX:XX.X\n+ * @param dev_addr\n+ *\tThe PCI Bus-Device-Function address to be returned\n+ * @return\n+ *  0 on success, negative on error.\n+ */\n+static inline int\n+eal_parse_pci_DomBDF(const char *input, struct rte_pci_addr *dev_addr)\n+{\n+\tGET_PCIADDR_FIELD(input, dev_addr->domain, UINT16_MAX, ':');\n+\tGET_PCIADDR_FIELD(input, dev_addr->bus, UINT8_MAX, ':');\n+\tGET_PCIADDR_FIELD(input, dev_addr->devid, UINT8_MAX, '.');\n+\tGET_PCIADDR_FIELD(input, dev_addr->function, UINT8_MAX, 0);\n+\treturn 0;\n+}\n+#undef GET_PCIADDR_FIELD\n+\n+/**\n+ * Utility function to write a pci device name, this device name can later be\n+ * used to retrieve the corresponding rte_pci_addr using eal_parse_pci_*\n+ * BDF helpers.\n+ *\n+ * @param addr\n+ *\tThe PCI Bus-Device-Function address\n+ * @param output\n+ *\tThe output buffer string\n+ * @param size\n+ *\tThe output buffer size\n+ */\n+static inline void\n+rte_pci_device_name(const struct rte_pci_addr *addr,\n+\t\tchar *output, size_t size)\n+{\n+\tRTE_VERIFY(size >= PCI_PRI_STR_SIZE);\n+\tRTE_VERIFY(snprintf(output, size, PCI_PRI_FMT,\n+\t\t\t    addr->domain, addr->bus,\n+\t\t\t    addr->devid, addr->function) >= 0);\n+}\n+\n+/* Compare two PCI device addresses. */\n+/**\n+ * Utility function to compare two PCI device addresses.\n+ *\n+ * @param addr\n+ *\tThe PCI Bus-Device-Function address to compare\n+ * @param addr2\n+ *\tThe PCI Bus-Device-Function address to compare\n+ * @return\n+ *\t0 on equal PCI address.\n+ *\tPositive on addr is greater than addr2.\n+ *\tNegative on addr is less than addr2, or error.\n+ */\n+static inline int\n+rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,\n+\t\t\t const struct rte_pci_addr *addr2)\n+{\n+\tuint64_t dev_addr, dev_addr2;\n+\n+\tif ((addr == NULL) || (addr2 == NULL))\n+\t\treturn -1;\n+\n+\tdev_addr = ((uint64_t)addr->domain << 24) |\n+\t\t(addr->bus << 16) | (addr->devid << 8) | addr->function;\n+\tdev_addr2 = ((uint64_t)addr2->domain << 24) |\n+\t\t(addr2->bus << 16) | (addr2->devid << 8) | addr2->function;\n+\n+\tif (dev_addr > dev_addr2)\n+\t\treturn 1;\n+\telse if (dev_addr < dev_addr2)\n+\t\treturn -1;\n+\telse\n+\t\treturn 0;\n+}\n+\n+/**\n+ * Map a particular resource from a file.\n+ *\n+ * @param requested_addr\n+ *      The starting address for the new mapping range.\n+ * @param fd\n+ *      The file descriptor.\n+ * @param offset\n+ *      The offset for the mapping range.\n+ * @param size\n+ *      The size for the mapping range.\n+ * @param additional_flags\n+ *      The additional flags for the mapping range.\n+ * @return\n+ *   - On success, the function returns a pointer to the mapped area.\n+ *   - On error, the value MAP_FAILED is returned.\n+ */\n+void *pci_map_resource(void *requested_addr, int fd, off_t offset,\n+\t\tsize_t size, int additional_flags);\n+\n+/**\n+ * Unmap a particular resource.\n+ *\n+ * @param requested_addr\n+ *      The address for the unmapping range.\n+ * @param size\n+ *      The size for the unmapping range.\n+ */\n+void pci_unmap_resource(void *requested_addr, size_t size);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_PCI_H_ */\ndiff --git a/lib/librte_pci/rte_pci.c b/lib/librte_pci/rte_pci.c\nnew file mode 100644\nindex 0000000..9dfdd3f\n--- /dev/null\n+++ b/lib/librte_pci/rte_pci.c\n@@ -0,0 +1,92 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   Copyright 2013-2014 6WIND S.A.\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+\n+#include <string.h>\n+#include <inttypes.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <sys/queue.h>\n+#include <sys/mman.h>\n+\n+#include <rte_errno.h>\n+#include <rte_interrupts.h>\n+#include <rte_log.h>\n+#include <rte_bus.h>\n+#include <rte_per_lcore.h>\n+#include <rte_memory.h>\n+#include <rte_memzone.h>\n+#include <rte_eal.h>\n+#include <rte_string_fns.h>\n+#include <rte_common.h>\n+\n+#include \"rte_pci.h\"\n+\n+/* map a particular resource from a file */\n+void *\n+pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size,\n+\t\t int additional_flags)\n+{\n+\tvoid *mapaddr;\n+\n+\t/* Map the PCI memory resource of device */\n+\tmapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,\n+\t\t\tMAP_SHARED | additional_flags, fd, offset);\n+\tif (mapaddr == MAP_FAILED) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\\n\",\n+\t\t\t__func__, fd, requested_addr,\n+\t\t\t(unsigned long)size, (unsigned long)offset,\n+\t\t\tstrerror(errno), mapaddr);\n+\t} else\n+\t\tRTE_LOG(DEBUG, EAL, \"  PCI memory mapped at %p\\n\", mapaddr);\n+\n+\treturn mapaddr;\n+}\n+\n+/* unmap a particular resource */\n+void\n+pci_unmap_resource(void *requested_addr, size_t size)\n+{\n+\tif (requested_addr == NULL)\n+\t\treturn;\n+\n+\t/* Unmap the PCI memory resource of device */\n+\tif (munmap(requested_addr, size)) {\n+\t\tRTE_LOG(ERR, EAL, \"%s(): cannot munmap(%p, 0x%lx): %s\\n\",\n+\t\t\t__func__, requested_addr, (unsigned long)size,\n+\t\t\tstrerror(errno));\n+\t} else\n+\t\tRTE_LOG(DEBUG, EAL, \"  PCI memory unmapped at %p\\n\",\n+\t\t\t\trequested_addr);\n+}\ndiff --git a/lib/librte_pci/rte_pci_version.map b/lib/librte_pci/rte_pci_version.map\nnew file mode 100644\nindex 0000000..64dec54\n--- /dev/null\n+++ b/lib/librte_pci/rte_pci_version.map\n@@ -0,0 +1,8 @@\n+DPDK_17.11 {\n+\tglobal:\n+\n+\tpci_map_resource;\n+\tpci_unmap_resource;\n+\n+\tlocal: *;\n+};\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex c25fdd9..f93618f 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -96,6 +96,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EVENTDEV)       += -lrte_eventdev\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool\n _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING)   += -lrte_mempool_ring\n _LDLIBS-$(CONFIG_RTE_LIBRTE_RING)           += -lrte_ring\n+_LDLIBS-$(CONFIG_RTE_LIBRTE_PCI)            += -lrte_pci\n _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal\n _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline\n _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder\n@@ -104,6 +105,8 @@ ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)\n _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI)            += -lrte_kni\n endif\n \n+_LDLIBS-$(CONFIG_RTE_LIBRTE_PCI_BUS)        += -lrte_bus_pci\n+\n ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n)\n # plugins (link only if static libraries)\n \n",
    "prefixes": [
        "dpdk-dev",
        "v2",
        "05/14"
    ]
}