get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 10517,
    "url": "http://patches.dpdk.org/api/patches/10517/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1455542666-28895-4-git-send-email-david.marchand@6wind.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<1455542666-28895-4-git-send-email-david.marchand@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1455542666-28895-4-git-send-email-david.marchand@6wind.com",
    "date": "2016-02-15T13:24:25",
    "name": "[dpdk-dev,v3,3/4] eal: introduce pci ioport api",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "710f89a80918f02033d457d97a0f8d736f52fab6",
    "submitter": {
        "id": 3,
        "url": "http://patches.dpdk.org/api/people/3/?format=api",
        "name": "David Marchand",
        "email": "david.marchand@6wind.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1455542666-28895-4-git-send-email-david.marchand@6wind.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/10517/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/10517/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id E50689AF8;\n\tMon, 15 Feb 2016 14:24:43 +0100 (CET)",
            "from mail-wm0-f43.google.com (mail-wm0-f43.google.com\n\t[74.125.82.43]) by dpdk.org (Postfix) with ESMTP id 986319A88\n\tfor <dev@dpdk.org>; Mon, 15 Feb 2016 14:24:39 +0100 (CET)",
            "by mail-wm0-f43.google.com with SMTP id g62so58719551wme.1\n\tfor <dev@dpdk.org>; Mon, 15 Feb 2016 05:24:39 -0800 (PST)",
            "from gloops.dev.6wind.com (144.77.126.78.rev.sfr.net.\n\t[78.126.77.144]) by smtp.gmail.com with ESMTPSA id\n\tq75sm15784652wmd.6.2016.02.15.05.24.38\n\t(version=TLSv1/SSLv3 cipher=OTHER);\n\tMon, 15 Feb 2016 05:24:38 -0800 (PST)"
        ],
        "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\tbh=F42UFAAMT9v70/8MHkDChK5WUGab2UCaguVnRozfbLA=;\n\tb=vueFVT8Ea64r0GFuZTNQT0eGoKSeaQ8qbSVZggQsTI+uoU/+jRNcSGw3ykDECu2Kec\n\tBL/BfTBZupMyfFQhSX56kYHjYBsFy+Z3QOvQ6AN4CX5mh4Owwf0TvZTjXUQ89Pig+rV1\n\tUQin8SBOtEJZEXtP+TwCTBw6WOWg3VOyLibRLhgb5NOx2qmWrkrtT0f9v4zEt7lXUtR9\n\t2p6L1kR9mkit4dQBEr0F7jqWnB96Zf1uDrmamQyOEXRQP1ElVlP+nfsWcvdtMGB6qHhh\n\ttD4a9ZU/mZmFlb1bYvTCRBs966uRCedYa51He/zStsjx9+ZGgN0RMGCt6IOrDnDYteUk\n\t/pDg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=F42UFAAMT9v70/8MHkDChK5WUGab2UCaguVnRozfbLA=;\n\tb=kK0anwBT4IuQaTu9+P9s1nsvKGLQLvbJLm7D4kyVJZAewKYq2nXL3ly11KdBZNQMNF\n\tSeJYH4nNWUYu0rRDzHg5Rxa+PnGoT3yrwhbf62xEQ2IrLgtA6zZTIG/hGWf3KkcKWgEI\n\tMY5gKYoSidrTYDmaf/QR4FckQF6iNLE0P5OPKUJ/+fAIr8kDGVcmpKW/L+SzMDol5dfL\n\tdsIkt7FZXeDLSVL8ti3XiXNxkmyWSQqU6tUBgQFioxYluz0LSYjsCxhg1nTcemVolqQ4\n\tD8NI7Zi+tOQBS4Aay7tlrVsY+SMZNqcELb3CRfdnO+jo9xvpLelQ0ZtPZf6vOIt+CAf0\n\tkRpw==",
        "X-Gm-Message-State": "AG10YOSqMwd6j/OKZfEH3uIP2eWNWTZNF32WIdlhSp7hMYdgVl/lvGrh681sjwahtXX9VuHO",
        "X-Received": "by 10.28.213.142 with SMTP id m136mr13343100wmg.24.1455542679471;\n\tMon, 15 Feb 2016 05:24:39 -0800 (PST)",
        "From": "David Marchand <david.marchand@6wind.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 15 Feb 2016 14:24:25 +0100",
        "Message-Id": "<1455542666-28895-4-git-send-email-david.marchand@6wind.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1455542666-28895-1-git-send-email-david.marchand@6wind.com>",
        "References": "<1454831317-4542-1-git-send-email-david.marchand@6wind.com>\n\t<1455542666-28895-1-git-send-email-david.marchand@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH v3 3/4] eal: introduce pci ioport api",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Most of the code is inspired on virtio driver.\nrte_pci_ioport structure is filled at map time with anything needed for later\nread / write calls.\nAt the moment, offset field is used to store a x86 ioport (uint16_t) and will\nbe reused for other arches.\n\nTODO: check multi process, check intr_handle init/exit,\n\nSigned-off-by: David Marchand <david.marchand@6wind.com>\nTested-by: Santosh Shukla <sshukla@mvista.com>\n---\nChanges since v2:\n- removed remaining reference to rte_ioport_t\n\nChanges since v1:\n- dropped rte_ioport and removed the arch headers, if performance is an\n  issue, we will see how to enhance this in later patches\n- rte_pci_ioport object now reaches driver implementation (uio / vfio)\n- sanity checks are in uio map function, no reason to have those checks in\n  read/write functions\n\n---\n lib/librte_eal/bsdapp/eal/eal_pci.c             | 135 +++++++++++++++++++\n lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   4 +\n lib/librte_eal/common/include/rte_pci.h         |  65 +++++++++\n lib/librte_eal/linuxapp/eal/eal_pci.c           | 170 ++++++++++++++++++++++++\n lib/librte_eal/linuxapp/eal/eal_pci_init.h      |  16 +++\n lib/librte_eal/linuxapp/eal/eal_pci_uio.c       | 132 +++++++++++++++++-\n lib/librte_eal/linuxapp/eal/eal_pci_vfio.c      |  37 ++++++\n lib/librte_eal/linuxapp/eal/rte_eal_version.map |   4 +\n 8 files changed, 560 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c\nindex 95c32c1..58f2ec9 100644\n--- a/lib/librte_eal/bsdapp/eal/eal_pci.c\n+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c\n@@ -51,6 +51,11 @@\n #include <sys/pciio.h>\n #include <dev/pci/pcireg.h>\n \n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+#include <sys/types.h>\n+#include <machine/cpufunc.h>\n+#endif\n+\n #include <rte_interrupts.h>\n #include <rte_log.h>\n #include <rte_pci.h>\n@@ -479,6 +484,136 @@ int rte_eal_pci_write_config(const struct rte_pci_device *dev,\n \treturn -1;\n }\n \n+int\n+rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t       struct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (dev->kdrv) {\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\tcase RTE_KDRV_NIC_UIO:\n+\t\tif ((uintptr_t) dev->mem_resource[bar].addr <= UINT16_MAX) {\n+\t\t\tp->offset = (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\t    void *data, size_t len, off_t offset)\n+{\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\tuint8_t *d;\n+\tint size;\n+\tunsigned short reg = p->offset + 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_eal_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\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\t     const void *data, size_t len, off_t offset)\n+{\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\tconst uint8_t *s;\n+\tint size;\n+\tunsigned short reg = p->offset + 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(*(const uint32_t *)s, reg);\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+\t\t\toutw(*(const uint16_t *)s, reg);\n+\t\t} else {\n+\t\t\tsize = 1;\n+\t\t\toutb(*s, 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_eal_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\t\t const 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_eal_pci_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (p->dev->kdrv) {\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\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+}\n+\n /* Init the PCI EAL subsystem */\n int\n rte_eal_pci_init(void)\ndiff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\nindex d8ac7f7..65da300 100644\n--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map\n@@ -139,6 +139,10 @@ DPDK_2.2 {\n DPDK_2.3 {\n \tglobal:\n \n+\trte_eal_pci_ioport_map;\n+\trte_eal_pci_ioport_read;\n+\trte_eal_pci_ioport_unmap;\n+\trte_eal_pci_ioport_write;\n \trte_eal_pci_map_device;\n \trte_eal_pci_unmap_device;\n \trte_cpu_feature_table;\ndiff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h\nindex 1508ea9..2d2a4dd 100644\n--- a/lib/librte_eal/common/include/rte_pci.h\n+++ b/lib/librte_eal/common/include/rte_pci.h\n@@ -512,6 +512,71 @@ int rte_eal_pci_read_config(const struct rte_pci_device *device,\n int rte_eal_pci_write_config(const struct rte_pci_device *device,\n \t\t\t     const 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 offset;\n+};\n+\n+/**\n+ * Initialises a rte_pci_ioport object for a pci device io resource.\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_eal_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t\t   struct 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+ */\n+int rte_eal_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_eal_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\t\t     void *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_eal_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\t\t      const void *data, size_t len, off_t offset);\n+\n #ifdef RTE_PCI_CONFIG\n /**\n  * Set special config space registers for performance purpose.\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\nindex db947da..1b9de1e 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c\n@@ -621,6 +621,176 @@ int rte_eal_pci_write_config(const struct rte_pci_device *device,\n \t}\n }\n \n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+static int\n+pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused,\n+\t       struct 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->offset = 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_eal_pci_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t       struct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tret = -1;\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+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tret = pci_uio_ioport_map(dev, bar, p);\n+\t\tbreak;\n+\tdefault:\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\t\t/* special case for x86 ... */\n+\t\tret = pci_ioport_map(dev, bar, p);\n+#else\n+\t\tret = -1;\n+#endif\n+\t\tbreak;\n+\t}\n+\n+\tif (!ret)\n+\t\tp->dev = dev;\n+\n+\treturn ret;\n+}\n+\n+void\n+rte_eal_pci_ioport_read(struct rte_pci_ioport *p,\n+\t\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+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+\t\tbreak;\n+\tdefault:\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\t\t/* special case for x86 ... */\n+\t\tpci_uio_ioport_read(p, data, len, offset);\n+#endif\n+\t\tbreak;\n+\t}\n+}\n+\n+void\n+rte_eal_pci_ioport_write(struct rte_pci_ioport *p,\n+\t\t\t const 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+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+\t\tbreak;\n+\tdefault:\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\t\t/* special case for x86 ... */\n+\t\tpci_uio_ioport_write(p, data, len, offset);\n+#endif\n+\t\tbreak;\n+\t}\n+}\n+\n+int\n+rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tint ret;\n+\n+\tswitch (p->dev->kdrv) {\n+#ifdef VFIO_PRESENT\n+\tcase RTE_KDRV_VFIO:\n+\t\tret = -1;\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+\tcase RTE_KDRV_UIO_GENERIC:\n+\t\tret = pci_uio_ioport_unmap(p);\n+\t\tbreak;\n+\tdefault:\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\t\t/* special case for x86 ... nothing to do */\n+\t\tret = 0;\n+#else\n+\t\tret = -1;\n+#endif\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n /* Init the PCI EAL subsystem */\n int\n rte_eal_pci_init(void)\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h\nindex a17c708..7011753 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h\n@@ -54,6 +54,14 @@ int pci_uio_read_config(const struct rte_intr_handle *intr_handle,\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 #define VFIO_MAX_GROUPS 64\n@@ -68,6 +76,14 @@ int pci_vfio_read_config(const struct rte_intr_handle *intr_handle,\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 VFIO resource prototype */\n int pci_vfio_map_resource(struct rte_pci_device *dev);\n int pci_vfio_get_group_fd(int iommu_group_fd);\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\nindex ac50e13..f891dda 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n@@ -39,6 +39,10 @@\n #include <sys/mman.h>\n #include <linux/pci_regs.h>\n \n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\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@@ -145,7 +149,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)\n  */\n static int\n pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,\n-\t\t\t   unsigned int buflen)\n+\t\t\t   unsigned int buflen, int create)\n {\n \tstruct rte_pci_addr *loc = &dev->addr;\n \tunsigned int uio_num;\n@@ -208,7 +212,7 @@ pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,\n \t\treturn -1;\n \n \t/* create uio device if we've been asked to */\n-\tif (internal_config.create_uio_dev &&\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@@ -245,7 +249,7 @@ pci_uio_alloc_resource(struct rte_pci_device *dev,\n \tloc = &dev->addr;\n \n \t/* find uio resource */\n-\tuio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname));\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@@ -363,3 +367,125 @@ error:\n \trte_free(maps[map_idx].path);\n \treturn -1;\n }\n+\n+int\n+pci_uio_ioport_map(struct rte_pci_device *dev, int bar,\n+\t\t   struct rte_pci_ioport *p)\n+{\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\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->offset = start;\n+\treturn 0;\n+#else\n+\tRTE_SET_USED(dev);\n+\tRTE_SET_USED(bar);\n+\tRTE_SET_USED(p);\n+\treturn -1;\n+#endif\n+}\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+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\tuint8_t *d;\n+\tint size;\n+\tunsigned short reg = p->offset + 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+pci_uio_ioport_write(struct rte_pci_ioport *p,\n+\t\t     const void *data, size_t len, off_t offset)\n+{\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\tconst uint8_t *s;\n+\tint size;\n+\tunsigned short reg = p->offset + 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_p(*(const uint32_t *)s, reg);\n+\t\t} else if (len >= 2) {\n+\t\t\tsize = 2;\n+\t\t\toutw_p(*(const uint16_t *)s, reg);\n+\t\t} else {\n+\t\t\tsize = 1;\n+\t\t\toutb_p(*s, 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+int\n+pci_uio_ioport_unmap(struct rte_pci_ioport *p)\n+{\n+\tRTE_SET_USED(p);\n+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)\n+\t/* FIXME close intr fd ? */\n+\treturn 0;\n+#else\n+\treturn -1;\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\nindex a6c7e16..ffa2dd0 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n@@ -976,6 +976,43 @@ pci_vfio_map_resource(struct rte_pci_device *dev)\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+\tRTE_SET_USED(dev);\n+\tRTE_SET_USED(bar);\n+\tRTE_SET_USED(p);\n+\treturn -1;\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+\tRTE_SET_USED(p);\n+\tRTE_SET_USED(data);\n+\tRTE_SET_USED(len);\n+\tRTE_SET_USED(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+\tRTE_SET_USED(p);\n+\tRTE_SET_USED(data);\n+\tRTE_SET_USED(len);\n+\tRTE_SET_USED(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 \t/* initialize group list */\ndiff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\nindex 4c09c0b..dea260d 100644\n--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map\n@@ -142,6 +142,10 @@ DPDK_2.2 {\n DPDK_2.3 {\n \tglobal:\n \n+\trte_eal_pci_ioport_map;\n+\trte_eal_pci_ioport_read;\n+\trte_eal_pci_ioport_unmap;\n+\trte_eal_pci_ioport_write;\n \trte_eal_pci_map_device;\n \trte_eal_pci_unmap_device;\n \trte_cpu_feature_table;\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "3/4"
    ]
}