From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f47.google.com (mail-wm0-f47.google.com [74.125.82.47]) by dpdk.org (Postfix) with ESMTP id 2B55EC370 for ; Fri, 5 Feb 2016 18:55:55 +0100 (CET) Received: by mail-wm0-f47.google.com with SMTP id p63so37365593wmp.1 for ; Fri, 05 Feb 2016 09:55:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=l5EHBEQ99befM1gM1ZTS8r9kZMp0raMziff0Q+HNpo8=; b=lf7Iq+eqYBAvqofyPZRH5g7ABYiV0mHxPGRqcpxMJelHuaCSDJwD1mHKJPxdD5Lm8Q Re0831Yr/AB5zLcgbMfabe7EmN2ZoErzink88KYgEj8rygETiA0j8NQbnhKtcpnhzZIQ Vi4TvPDTZ5loO1xrUks4rIbDpPCR8fE4HbL1rWv2wpH/yCNSZWdGJRy6cElemYj67h1n comqFr4c+VhkmlXxElqlfBv7DUMatsmaHfC0I4LZCxmD/1AG4Px8gseiftecSDMdVB9+ eWgBUIIBVkYuJKXQhXuwYpcjfpGAxcJGZD5kOW6ao4VTiNPUUedeDU9h4SyMHDhItleL f2Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=l5EHBEQ99befM1gM1ZTS8r9kZMp0raMziff0Q+HNpo8=; b=hcEgz9gKJVjMoIa7Xi5mQI2N6Alx57vTxoFs4Z0NCWI6SSoxNpQYBVt6KuyYpQcqwJ m1DqOgos8K7jqHCwFMraVS7KZZbkb9rlQ7SUine2ieKjG/EkcdxYm3fnTWSt7D43UesJ HZxOYwFxwkAWQclwuqE1jXA/MYR+ItCyv55C/LLPUjSKn1GyBAJlZjOJYFzGTNdvAOTJ MyIV9IeyRSOMaImS9RsJaovZte72WH7fo2graOMGrRITeMIBAeX5/qm0BP5gmWmVjkuM n4Hp6LWnu6RKpxO33Jp3cpzYDhIdbtvvIxYW/JkCHqjJwCR75faoZ4Uy5ouTW/wFBZ/7 xOvA== X-Gm-Message-State: AG10YOReSq7KOW6RqxXQoOZqWTByMOQQe0TGybmZHk9IGVLD5YVv5Svv/VNQWhKCcAHRQuPQ X-Received: by 10.194.95.136 with SMTP id dk8mr16291076wjb.96.1454694954387; Fri, 05 Feb 2016 09:55:54 -0800 (PST) Received: from gloops.dev.6wind.com (144.77.126.78.rev.sfr.net. [78.126.77.144]) by smtp.gmail.com with ESMTPSA id gt7sm16942517wjc.1.2016.02.05.09.55.53 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 05 Feb 2016 09:55:53 -0800 (PST) From: David Marchand To: dev@dpdk.org Date: Fri, 5 Feb 2016 18:55:44 +0100 Message-Id: <1454694945-18040-4-git-send-email-david.marchand@6wind.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1454694945-18040-1-git-send-email-david.marchand@6wind.com> References: <1454694945-18040-1-git-send-email-david.marchand@6wind.com> Subject: [dpdk-dev] [PATCH 3/4] eal: introduce ioport api X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Feb 2016 17:55:55 -0000 Most of the code is inspired on virtio driver. rte_ioport_t is a arch-specific structure allocated at rte_pci_ioport_map and release at rte_pci_ioport_unmap. For x86, this is actually just a ioport number, handled by rte_ioport_xx api. Signed-off-by: David Marchand --- lib/librte_eal/bsdapp/eal/eal_pci.c | 76 ++++++++++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 + .../common/include/arch/arm/rte_ioport.h | 41 ++++++ .../common/include/arch/ppc_64/rte_ioport.h | 41 ++++++ .../common/include/arch/tile/rte_ioport.h | 41 ++++++ .../common/include/arch/x86/rte_ioport.h | 109 ++++++++++++++ lib/librte_eal/common/include/rte_pci.h | 68 +++++++++ lib/librte_eal/linuxapp/eal/eal_pci.c | 156 +++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_pci_init.h | 6 + lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 67 ++++++++- lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 17 +++ lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 + 12 files changed, 627 insertions(+), 3 deletions(-) create mode 100644 lib/librte_eal/common/include/arch/arm/rte_ioport.h create mode 100644 lib/librte_eal/common/include/arch/ppc_64/rte_ioport.h create mode 100644 lib/librte_eal/common/include/arch/tile/rte_ioport.h create mode 100644 lib/librte_eal/common/include/arch/x86/rte_ioport.h diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c index 95c32c1..29dd600 100644 --- a/lib/librte_eal/bsdapp/eal/eal_pci.c +++ b/lib/librte_eal/bsdapp/eal/eal_pci.c @@ -479,6 +479,82 @@ int rte_eal_pci_write_config(const struct rte_pci_device *dev, return -1; } +int +rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar, + struct rte_pci_ioport *p) +{ + int ret; + + switch (dev->kdrv) { +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + case RTE_KDRV_NIC_UIO: + p->ioport = + (rte_ioport_t)(uintptr_t)dev->mem_resource[bar].addr; + ret = 0; + break; +#endif + default: + ret = -1; + break; + } + + if (!ret) + p->dev = dev; + + return ret; +} + +int +rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p) +{ + int ret; + + switch (p->dev->kdrv) { +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + case RTE_KDRV_NIC_UIO: + ret = 0; + break; +#endif + default: + ret = -1; + break; + } + + return ret; +} + +void +rte_eal_pci_ioport_read(struct rte_pci_ioport *p, + void *data, size_t len, off_t offset) +{ +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* for x86, as long as this api is called, we suppose that we have a + * valid ioport, so no check and direct call to rte_ioport_xxx */ + rte_ioport_read(p->ioport, data, len, offset); +#else + RTE_SET_USED(p); + RTE_SET_USED(data); + RTE_SET_USED(len); + RTE_SET_USED(offset); +#endif +} + +void +rte_eal_pci_ioport_write(struct rte_pci_ioport *p, + const void *data, size_t len, off_t offset) +{ +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* for x86, as long as this api is called, we suppose that we have a + * valid ioport, so no check and direct call to rte_ioport_xxx */ + rte_ioport_write(p->ioport, data, len, offset); +#else + RTE_SET_USED(p); + RTE_SET_USED(data); + RTE_SET_USED(len); + RTE_SET_USED(offset); +#endif +} + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index d8ac7f7..65da300 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -139,6 +139,10 @@ DPDK_2.2 { DPDK_2.3 { global: + rte_eal_pci_ioport_map; + rte_eal_pci_ioport_read; + rte_eal_pci_ioport_unmap; + rte_eal_pci_ioport_write; rte_eal_pci_map_device; rte_eal_pci_unmap_device; rte_cpu_feature_table; diff --git a/lib/librte_eal/common/include/arch/arm/rte_ioport.h b/lib/librte_eal/common/include/arch/arm/rte_ioport.h new file mode 100644 index 0000000..c6943fc --- /dev/null +++ b/lib/librte_eal/common/include/arch/arm/rte_ioport.h @@ -0,0 +1,41 @@ +/* + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RTE_IOPORT_ARM_H__ +#define __RTE_IOPORT_ARM_H__ + +/* FIXME: empty stub, not working on this arch */ + +typedef unsigned short rte_ioport_t; + +#endif diff --git a/lib/librte_eal/common/include/arch/ppc_64/rte_ioport.h b/lib/librte_eal/common/include/arch/ppc_64/rte_ioport.h new file mode 100644 index 0000000..c6eb98a --- /dev/null +++ b/lib/librte_eal/common/include/arch/ppc_64/rte_ioport.h @@ -0,0 +1,41 @@ +/* + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RTE_IOPORT_PPC_H__ +#define __RTE_IOPORT_PPC_H__ + +/* FIXME: empty stub, not working on this arch */ + +typedef unsigned short rte_ioport_t; + +#endif diff --git a/lib/librte_eal/common/include/arch/tile/rte_ioport.h b/lib/librte_eal/common/include/arch/tile/rte_ioport.h new file mode 100644 index 0000000..2028db8 --- /dev/null +++ b/lib/librte_eal/common/include/arch/tile/rte_ioport.h @@ -0,0 +1,41 @@ +/* + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RTE_IOPORT_TILE_H__ +#define __RTE_IOPORT_TILE_H__ + +/* FIXME: empty stub, not working on this arch */ + +typedef unsigned short rte_ioport_t; + +#endif diff --git a/lib/librte_eal/common/include/arch/x86/rte_ioport.h b/lib/librte_eal/common/include/arch/x86/rte_ioport.h new file mode 100644 index 0000000..1eb3cfc --- /dev/null +++ b/lib/librte_eal/common/include/arch/x86/rte_ioport.h @@ -0,0 +1,109 @@ +/* + * Copyright 2016 6WIND S.A. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * - Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RTE_IOPORT_X86_H__ +#define __RTE_IOPORT_X86_H__ + +#ifndef __FreeBSD__ +#include +#else + +#include +#include + +static inline void +outb_p(unsigned char data, unsigned int port) +{ + outb(port, (u_char)data); +} + +static inline void +outw_p(unsigned short data, unsigned int port) +{ + outw(port, (u_short)data); +} + +static inline void +outl_p(unsigned int data, unsigned int port) +{ + outl(port, (u_int)data); +} +#endif + +typedef unsigned short rte_ioport_t; + +static inline void +rte_ioport_read(const rte_ioport_t port, void *data, size_t len, + off_t offset) +{ + uint8_t *d; + int size; + unsigned short reg = port + offset; + + for (d = data; len > 0; d += size, reg += size, len -= size) { + if (len >= 4) { + size = 4; + *(uint32_t *)d = inl(reg); + } else if (len >= 2) { + size = 2; + *(uint16_t *)d = inw(reg); + } else { + size = 1; + *d = inb(reg); + } + } +} + +static inline void +rte_ioport_write(rte_ioport_t port, const void *data, size_t len, + off_t offset) +{ + const uint8_t *s; + int size; + unsigned short reg = port + offset; + + for (s = data; len > 0; s += size, reg += size, len -= size) { + if (len >= 4) { + size = 4; + outl_p(*(const uint32_t *)s, reg); + } else if (len >= 2) { + size = 2; + outw_p(*(const uint16_t *)s, reg); + } else { + size = 1; + outb_p(*s, reg); + } + } +} + +#endif diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 1508ea9..aedb06f 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -83,6 +83,7 @@ extern "C" { #include #include +#include TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */ TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */ @@ -512,6 +513,73 @@ int rte_eal_pci_read_config(const struct rte_pci_device *device, int rte_eal_pci_write_config(const struct rte_pci_device *device, const void *buf, size_t len, off_t offset); +/** + * A structure used to access io resources for a pci device. + * rte_ioport_t is arch, os, driver specific, and should not be used outside + * of pci ioport api. + */ +struct rte_pci_ioport { + struct rte_pci_device *dev; + rte_ioport_t ioport; +}; + +/** + * Initialises a rte_pci_ioport object for a pci device io resource. + * This object is then used to gain access to those io resources (see below). + * + * @param dev + * A pointer to a rte_pci_device structure describing the device. + * to use + * @param bar + * Index of the io pci resource we want to access. + * @param p + * The rte_pci_ioport object to be initialized. + * @return + * 0 on success, negative on error. + */ +int rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar, + struct rte_pci_ioport *p); + +/** + * Release any resources used in a rte_pci_ioport object. + * + * @param p + * The rte_pci_ioport object to be uninitialized. + */ +int rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p); + +/** + * Read from a io pci resource. + * + * @param p + * The rte_pci_ioport object from which we want to read. + * @param data + * A data buffer where the bytes should be read into + * @param len + * The length of the data buffer. + * @param offset + * The offset into the pci io resource. + * TODO: inline ? + */ +void rte_eal_pci_ioport_read(struct rte_pci_ioport *p, + void *data, size_t len, off_t offset); + +/** + * Write to a io pci resource. + * + * @param p + * The rte_pci_ioport object to which we want to write. + * @param data + * A data buffer where the bytes should be read into + * @param len + * The length of the data buffer. + * @param offset + * The offset into the pci io resource. + * TODO: inline ? + */ +void rte_eal_pci_ioport_write(struct rte_pci_ioport *p, + const void *data, size_t len, off_t offset); + #ifdef RTE_PCI_CONFIG /** * Set special config space registers for performance purpose. diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index db947da..7a4d468 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -621,6 +621,162 @@ int rte_eal_pci_write_config(const struct rte_pci_device *device, } } +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) +static int +pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused, + rte_ioport_t *p) +{ + uint16_t start, end; + FILE *fp; + char *line = NULL; + char pci_id[16]; + int found = 0; + size_t linesz; + + snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, + dev->addr.domain, dev->addr.bus, + dev->addr.devid, dev->addr.function); + + fp = fopen("/proc/ioports", "r"); + if (fp == NULL) { + RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__); + return -1; + } + + while (getdelim(&line, &linesz, '\n', fp) > 0) { + char *ptr = line; + char *left; + int n; + + n = strcspn(ptr, ":"); + ptr[n] = 0; + left = &ptr[n + 1]; + + while (*left && isspace(*left)) + left++; + + if (!strncmp(left, pci_id, strlen(pci_id))) { + found = 1; + + while (*ptr && isspace(*ptr)) + ptr++; + + sscanf(ptr, "%04hx-%04hx", &start, &end); + + break; + } + } + + free(line); + fclose(fp); + + if (!found) + return -1; + + dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; + *p = start; + RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start); + + return 0; +} +#endif + +int +rte_eal_pci_ioport_map(struct rte_pci_device *dev, int bar, + struct rte_pci_ioport *p) +{ + int ret; + + switch (dev->kdrv) { + case RTE_KDRV_VFIO: + ret = -1; +#ifdef VFIO_PRESENT + if (pci_vfio_is_enabled()) + ret = pci_vfio_ioport_map(dev, bar, &p->ioport); +#endif + break; + case RTE_KDRV_IGB_UIO: + case RTE_KDRV_UIO_GENERIC: + ret = pci_uio_ioport_map(dev, bar, &p->ioport); + break; + default: +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* special case for x86 ... */ + ret = pci_ioport_map(dev, bar, &p->ioport); +#else + ret = -1; +#endif + break; + } + + if (!ret) + p->dev = dev; + + return ret; +} + +int +rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p) +{ + int ret; + + switch (p->dev->kdrv) { + case RTE_KDRV_VFIO: + ret = -1; +#ifdef VFIO_PRESENT + if (pci_vfio_is_enabled()) + ret = pci_vfio_ioport_unmap(p->dev, &p->ioport); +#endif + break; + case RTE_KDRV_IGB_UIO: + case RTE_KDRV_UIO_GENERIC: + ret = pci_uio_ioport_unmap(p->dev, &p->ioport); + break; + default: +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* special case for x86 ... nothing to do */ + ret = 0; +#else + ret = -1; +#endif + break; + } + + return ret; +} + +void +rte_eal_pci_ioport_read(struct rte_pci_ioport *p, + void *data, size_t len, off_t offset) +{ +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* for x86, as long as this api is called, we suppose that we have a + * valid ioport, so no check and direct call to rte_ioport_xxx */ + rte_ioport_read(p->ioport, data, len, offset); +#else + RTE_SET_USED(p); + RTE_SET_USED(data); + RTE_SET_USED(len); + RTE_SET_USED(offset); +#endif +} + +void +rte_eal_pci_ioport_write(struct rte_pci_ioport *p, + const void *data, size_t len, off_t offset) +{ +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* for x86, as long as this api is called, we suppose that we have a + * valid ioport, so no check and direct call to rte_ioport_xxx */ + rte_ioport_write(p->ioport, data, len, offset); +#else + RTE_SET_USED(p); + RTE_SET_USED(data); + RTE_SET_USED(len); + RTE_SET_USED(offset); +#endif +} + /* Init the PCI EAL subsystem */ int rte_eal_pci_init(void) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h index a17c708..fdc8c99 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h +++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h @@ -54,6 +54,9 @@ int pci_uio_read_config(const struct rte_intr_handle *intr_handle, int pci_uio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offs); +int pci_uio_ioport_map(struct rte_pci_device *dev, int bar, rte_ioport_t *p); +int pci_uio_ioport_unmap(struct rte_pci_device *dev, rte_ioport_t *p); + #ifdef VFIO_PRESENT #define VFIO_MAX_GROUPS 64 @@ -68,6 +71,9 @@ int pci_vfio_read_config(const struct rte_intr_handle *intr_handle, int pci_vfio_write_config(const struct rte_intr_handle *intr_handle, const void *buf, size_t len, off_t offs); +int pci_vfio_ioport_map(struct rte_pci_device *dev, int bar, rte_ioport_t *p); +int pci_vfio_ioport_unmap(struct rte_pci_device *dev, rte_ioport_t *p); + /* map VFIO resource prototype */ int pci_vfio_map_resource(struct rte_pci_device *dev); int pci_vfio_get_group_fd(int iommu_group_fd); diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c index ac50e13..85ed411 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c @@ -145,7 +145,7 @@ pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num) */ static int pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf, - unsigned int buflen) + unsigned int buflen, int create) { struct rte_pci_addr *loc = &dev->addr; unsigned int uio_num; @@ -208,7 +208,7 @@ pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf, return -1; /* create uio device if we've been asked to */ - if (internal_config.create_uio_dev && + if (internal_config.create_uio_dev && create && pci_mknod_uio_dev(dstbuf, uio_num) < 0) RTE_LOG(WARNING, EAL, "Cannot create /dev/uio%u\n", uio_num); @@ -245,7 +245,7 @@ pci_uio_alloc_resource(struct rte_pci_device *dev, loc = &dev->addr; /* find uio resource */ - uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname)); + uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1); if (uio_num < 0) { RTE_LOG(WARNING, EAL, " "PCI_PRI_FMT" not managed by UIO driver, " "skipping\n", loc->domain, loc->bus, loc->devid, loc->function); @@ -363,3 +363,64 @@ error: rte_free(maps[map_idx].path); return -1; } + +int +pci_uio_ioport_map(struct rte_pci_device *dev, int bar, rte_ioport_t *p) +{ +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + char dirname[PATH_MAX]; + char filename[PATH_MAX]; + int uio_num; + unsigned long start; + + uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0); + if (uio_num < 0) + return -1; + + /* get portio start */ + snprintf(filename, sizeof(filename), + "%s/portio/port%d/start", dirname, bar); + if (eal_parse_sysfs_value(filename, &start) < 0) { + RTE_LOG(ERR, EAL, "%s(): cannot parse portio start\n", + __func__); + return -1; + } + + /* FIXME only for primary process ? */ + if (dev->intr_handle.type == RTE_INTR_HANDLE_UNKNOWN) { + + snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num); + dev->intr_handle.fd = open(filename, O_RDWR); + if (dev->intr_handle.fd < 0) { + RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", + filename, strerror(errno)); + return -1; + } + dev->intr_handle.type = RTE_INTR_HANDLE_UIO; + } + + RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%lx\n", start); + + *p = start; + return 0; +#else + RTE_SET_USED(dev); + RTE_SET_USED(bar); + RTE_SET_USED(p); + return -1; +#endif +} + +int +pci_uio_ioport_unmap(struct rte_pci_device *dev, + rte_ioport_t *p) +{ + RTE_SET_USED(dev); + RTE_SET_USED(p); +#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) + /* FIXME close intr fd ? */ + return 0; +#else + return -1; +#endif +} diff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c index a6c7e16..a8b74e1 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c @@ -976,6 +976,23 @@ pci_vfio_map_resource(struct rte_pci_device *dev) } int +pci_vfio_ioport_map(struct rte_pci_device *dev, int bar, rte_ioport_t *p) +{ + RTE_SET_USED(dev); + RTE_SET_USED(bar); + RTE_SET_USED(p); + return -1; +} + +int +pci_vfio_ioport_unmap(struct rte_pci_device *dev, rte_ioport_t *p) +{ + RTE_SET_USED(dev); + RTE_SET_USED(p); + return -1; +} + +int pci_vfio_enable(void) { /* initialize group list */ diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 4c09c0b..dea260d 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -142,6 +142,10 @@ DPDK_2.2 { DPDK_2.3 { global: + rte_eal_pci_ioport_map; + rte_eal_pci_ioport_read; + rte_eal_pci_ioport_unmap; + rte_eal_pci_ioport_write; rte_eal_pci_map_device; rte_eal_pci_unmap_device; rte_cpu_feature_table; -- 1.9.1