From patchwork Fri Dec 4 17:35:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Santosh Shukla X-Patchwork-Id: 9365 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 775799204; Fri, 4 Dec 2015 18:35:47 +0100 (CET) Received: from mail-pa0-f44.google.com (mail-pa0-f44.google.com [209.85.220.44]) by dpdk.org (Postfix) with ESMTP id 7B5079204 for ; Fri, 4 Dec 2015 18:35:46 +0100 (CET) Received: by pacdm15 with SMTP id dm15so89797895pac.3 for ; Fri, 04 Dec 2015 09:35:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mvista-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8ee6Rr+BHj4NwdS0r2CdBMVMdmVjTsPS+CQUxJEKIHE=; b=jwZRLv7On/jsUGOIjeRcHj8ioogdBGs9qw8wus8Aj3/mhYGJtxjD0t7c6svoDVqGSX /c2xYrQI6yF/fMTr19YdzLYyVEh/+5QdG9/Vne61P0EQ+zeCA0n19LwWuzYKj6ttb45A zhhwP03rPs+aytJDMvoI+dp7IolIMBQnikeU2D976iGa0aG2VHX+Kg/ePYMiM1oA1fxJ rTuKWrrmlcl6e6Ae9cris/GhUn31e1CWwWr8gCTssRt0q5N+hWnBZsnQseuDJunXoPGs JwolSTPt4uePFs0tbm98qFtD2POArz1lblBwu5VPzGKLtqiDQvvZNdjYqvNjy9pbdQRr liYQ== 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=8ee6Rr+BHj4NwdS0r2CdBMVMdmVjTsPS+CQUxJEKIHE=; b=KVtMJT/4Sw55woBh1+XPZudz5y9FINqhiWJzNGOIrfmr5sHl4eEXwnLzHoVhPe5j1t 1Mtdl9dg1ygJiU4ZOzgdX0UhsyLd7MQzuiUv9F4raHTwahFDIBnuH1cAm/9A88gegn25 dG+WSee2MGnito2WUUNXuVPZJFJxeTMihz8mkOCDPfxCWTyZAGwyigZp/4IwPr5CJ86Q jZE0ZcrdvvRaClbyQdLWDSVjKOmyZh55uNAJuAHS5NC9H9UPfkguvT77wUY8z8uGFXEl z+AlWiTxa6Uj1as/uI6k02bztMoyCPYuTfGF8UQLs16Kmz9XAOdjZzuiwV5drqzYL4oq zwJg== X-Gm-Message-State: ALoCoQkWPzFZygb5goZqNA0gsS2hvp9RouL2dZPAUJ9MSeSfNKNO2OnqyBAqP8FKpNryiV8iF0V+ X-Received: by 10.66.194.198 with SMTP id hy6mr23443730pac.34.1449250545899; Fri, 04 Dec 2015 09:35:45 -0800 (PST) Received: from rakeshk-OptiPlex-9020.mvista.com ([111.93.218.67]) by smtp.gmail.com with ESMTPSA id 134sm18365609pfa.30.2015.12.04.09.35.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 04 Dec 2015 09:35:45 -0800 (PST) From: Santosh Shukla To: dev@dpdk.org Date: Fri, 4 Dec 2015 23:05:19 +0530 Message-Id: <1449250519-28372-7-git-send-email-sshukla@mvista.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1449250519-28372-1-git-send-email-sshukla@mvista.com> References: <1449250519-28372-1-git-send-email-sshukla@mvista.com> Cc: Rizwan Ansari Subject: [dpdk-dev] [PATCH 6/6] virtio: arm/arm64: memory mapped IO support in pmd driver 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch set add memory-mapped-IO support for arm/arm64 archs in virtio-pmd driver. Patch creates ioport-mem device name /dev/igb_ioport. virtio_ethdev_init function to open that device file for once, mappes 4K page_size memory such that all entry in cat /proc/ioport {all PCI_IOBAR entry} mapped for once. For that two ancessor api;s - virtio_map_ioport : Maps all cat /proc/ioport pci iobars. - virtio_set_ioport_addr : manages the each pci_iobar slot as an offset. Tested for thunderX/arm64 platform, by creating maximum guest kernel supported virtio-net-pci device i.e.. 31 max, then attaching all 32 interface to uio, Verified with tespmd io_fwd application. Signed-off-by: Santosh Shukla Signed-off-by: Rizwan Ansari --- drivers/net/virtio/virtio_ethdev.c | 138 ++++++++++++++++++++++++++++- lib/librte_eal/linuxapp/igb_uio/igb_uio.c | 80 ++++++++++++++++- 2 files changed, 214 insertions(+), 4 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 74c00ee..93b8784 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -63,6 +63,30 @@ #include "virtqueue.h" #include "virtio_rxtx.h" +#ifdef RTE_EXEC_ENV_LINUXAPP +/* start address of first pci_iobar slot (user-space virtual-addres) */ +void *ioport_map; +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + +#include +#define DEV_NAME "/dev/igb_ioport" + +/* Keeping pci_ioport_size = 4k. + * So maximum mmaped pci_iobar supported = + * (ioport_size/pci_dev->mem_resource[0].len) + * + * note: kernel could allow maximum 32 virtio-net-pci interface, that mean + * maximum 32 PCI_IOBAR(s) where each PCI_IOBAR_LEN=0x20, so virtio_map_ioport() + * func by theory gonna support 4k/0x20 ==> 128 PCI_IOBAR(s), more than + * max-virtio-net-pci interface. + */ +#define PAGE_SIZE 4096 +#define PCI_IOPORT_SIZE PAGE_SIZE +#define PCI_IOPORT_MAX 128 /* 4k / 0x20 */ + +int ioport_map_cnt; +#endif /* ARM, ARM64 */ +#endif /* RTE_EXEC_ENV_LINUXAPP */ static int eth_virtio_dev_init(struct rte_eth_dev *eth_dev); static int eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev); @@ -497,6 +521,18 @@ virtio_dev_close(struct rte_eth_dev *dev) hw->started = 0; virtio_dev_free_mbufs(dev); virtio_free_queues(dev); + +#ifdef RTE_EXEC_ENV_LINUXAPP +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + + /* unmap ioport memory */ + ioport_map_cnt--; + if (!ioport_map_cnt) + munmap(ioport_map, PCI_IOPORT_SIZE); + + PMD_INIT_LOG(DEBUG, "unmapping ioport_mem %d\n", ioport_map_cnt); +#endif +#endif } static void @@ -1172,7 +1208,6 @@ static int virtio_resource_init_by_ioports(struct rte_pci_device *pci_dev) sscanf(ptr, "%04hx-%04hx", &start, &end); size = end - start + 1; - break; } } @@ -1256,6 +1291,81 @@ rx_func_get(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = &virtio_recv_pkts; } +#ifdef RTE_EXEC_ENV_LINUXAPP +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + +static int +virtio_map_ioport(void **resource_addr) +{ + int fd; + int ret = 0; + + fd = open(DEV_NAME, O_RDWR); + if (fd < 0) { + PMD_INIT_LOG(ERR, "device file %s open error: %d\n", + DEV_NAME, fd); + ret = -1; + goto out; + } + + ioport_map = mmap(NULL, PCI_IOPORT_SIZE, + PROT_EXEC | PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); + + if (ioport_map == MAP_FAILED) { + PMD_INIT_LOG(ERR, "mmap: failed to map bar Address=%p\n", + *resource_addr); + ret = -ENOMEM; + goto out1; + } + + PMD_INIT_LOG(INFO, "First pci_iobar mapped at %p\n", ioport_map); + +out1: + close(fd); +out: + return ret; +} + +static int +virtio_set_ioport_addr(void **resource_addr, unsigned long offset) +{ + int ret = 0; + + if (ioport_map_cnt >= PCI_IOPORT_MAX) { + ret = -1; + PMD_INIT_LOG(ERR, + "ioport_map_cnt(%d) greater than" + "PCI_IOPORT_MAX(%d)\n", + ioport_map_cnt, PCI_IOPORT_MAX); + goto out; + } + *resource_addr = (void *)((char *)ioport_map + (ioport_map_cnt)*offset); + ioport_map_cnt++; + + PMD_INIT_LOG(DEBUG, "pci.resource_addr %p ioport_map_cnt %d\n", + *resource_addr, ioport_map_cnt); +out: + return ret; +} +#else /* !ARM, !ARM64 */ +static int +virtio_map_ioport(void *resource_addr) +{ + (void)resource_addr; + return 0; +} + +static int +virtio_set_ioport_addr(void *resource_addr, unsigned long offset) +{ + (void)resource_addr; + (void)offset; + return 0; +} + +#endif /* ARM, ARM64 */ +#endif /* RTE_EXEC_ENV_LINUXAPP */ + /* * This function is based on probe() function in virtio_pci.c * It returns 0 on success. @@ -1294,8 +1404,31 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) if (virtio_resource_init(pci_dev) < 0) return -1; +#ifdef RTE_EXEC_ENV_LINUXAPP + int ret = 0; + + /* Map the all IOBAR entry from /proc/ioport to 4k page_size only once. + * Later virtio_set_ioport_addr() func will update correct bar_addr + * eachk ioport (i.e..pci_dev->mem_resource[0].addr) + */ + if (!ioport_map) { + ret = virtio_map_ioport(&pci_dev->mem_resource[0].addr); + if (ret < 0) + return -1; + } + + ret = virtio_set_ioport_addr(&pci_dev->mem_resource[0].addr, + pci_dev->mem_resource[0].len); + if (ret < 0) + return -1; + + PMD_INIT_LOG(INFO, "ioport_map %p resource_addr %p resource_len :%ld\n", + ioport_map, pci_dev->mem_resource[0].addr, + (unsigned long)pci_dev->mem_resource[0].len); + +#endif hw->use_msix = virtio_has_msix(&pci_dev->addr); - hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr; + hw->io_base = (unsigned long)(uintptr_t)pci_dev->mem_resource[0].addr; /* Reset the device although not necessary at startup */ vtpci_reset(hw); @@ -1430,7 +1563,6 @@ eth_virtio_dev_uninit(struct rte_eth_dev *eth_dev) rte_intr_callback_unregister(&pci_dev->intr_handle, virtio_interrupt_handler, eth_dev); - PMD_INIT_LOG(DEBUG, "dev_uninit completed"); return 0; diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c index f5617d2..b154a44 100644 --- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c +++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c @@ -324,6 +324,61 @@ igbuio_dom0_pci_mmap(struct uio_info *info, struct vm_area_struct *vma) } #endif +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) +#ifdef CONFIG_HAS_IOPORT_MAP +/* + * mmap driver to map x86-style PCI_IOBAR (i.e..cat /proc/ioport pci-bar-memory) + * from kernel-space virtual address to user-space virtual address. This module + * required for non-x86 archs example arm/arm64, as those archs donot do + * IO_MAP_IO types access, Infact supports memory-mapped-IO. That is because + * arm/arm64 doesn't support direct IO instruction, so the design approach is to + * map `cat /proc/ioport` PCI_IOBAR's kernel-space virtual-addr to user-space + * virtual-addr. Therefore the need for mmap-driver. + */ +#include /* file_operations */ +#include +#include /* VM_IO */ +#include +#include +#include +#include + +void *__iomem mapped_io; /* ioport addr of `cat /proc/ioport` */ + +static int igb_ioport_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct page *npage; + int ret = 0; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + npage = vmalloc_to_page(mapped_io); + ret = remap_pfn_range(vma, vma->vm_start, + page_to_pfn(npage), + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + if (ret) { + pr_info("Error: Failed to remap pfn=%lu error=%d\n", + page_to_pfn(npage), ret); + } + return 0; +} + +static const struct file_operations igb_ioport_fops = { + .mmap = igb_ioport_mmap, +}; + +static struct miscdevice igb_ioport_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "igb_ioport", + .fops = &igb_ioport_fops +}; +#else /* !CONFIG_HAS_IOPORT_MAP */ + +#error "CONFIG_HAS_IOPORT_MAP not supported for $RTE_ARCH" + +#endif /* CONFIG_HAS_IOPORT_MAP */ +#endif /* RTE_ARCH_ARM, RTE_ARCH_ARM64 */ + /* Remap pci resources described by bar #pci_bar in uio resource n. */ static int igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info, @@ -365,11 +420,22 @@ igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info, if (addr == 0 || len == 0) return -EINVAL; +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + /* + * TODO: KNI/procfs:: porttype entry need to be added for ARM/ARM64, + * for below mmap driver; + * */ + mapped_io = ioport_map(addr, 0); + info->port[n].name = name; + info->port[n].start = (unsigned long)(uintptr_t)mapped_io; + info->port[n].size = len; + info->port[n].porttype = UIO_PORT_X86; +#else info->port[n].name = name; info->port[n].start = addr; info->port[n].size = len; info->port[n].porttype = UIO_PORT_X86; - +#endif return 0; } @@ -615,6 +681,15 @@ igbuio_pci_init_module(void) { int ret; +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + ret = misc_register(&igb_ioport_dev); + if (ret < 0) { + pr_info("Error: failed to register ioport map driver (%d)\n", + ret); + return ret; + } +#endif + ret = igbuio_config_intr_mode(intr_mode); if (ret < 0) return ret; @@ -625,6 +700,9 @@ igbuio_pci_init_module(void) static void __exit igbuio_pci_exit_module(void) { +#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64) + misc_deregister(&igb_ioport_dev); +#endif pci_unregister_driver(&igbuio_pci_driver); }