From patchwork Thu Jan 7 08:27:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 86114 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 531A5A09FF; Thu, 7 Jan 2021 09:41:12 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 80AF4140F0D; Thu, 7 Jan 2021 09:41:07 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id B5DAB140EE9 for ; Thu, 7 Jan 2021 09:41:05 +0100 (CET) IronPort-SDR: BAC9cFY42NrV8+lAI3JrIg3NoWyYRWevkO3SP5f9fsndm+ThPsIrBE/t2zpAAv7fcWpwgbVBq+ XLIxRwecLdKQ== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="174819149" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="174819149" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jan 2021 00:41:05 -0800 IronPort-SDR: BI1MLzCyJNUAmITv1sSryMzeVG6BWxdSGPxyFMS7NjC1nmfqzGAjTvIqT53vE8yfVPql6Eo0Rq TiDSGB4cisaA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="346928845" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by orsmga003.jf.intel.com with ESMTP; 07 Jan 2021 00:41:02 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Thu, 7 Jan 2021 16:27:14 +0800 Message-Id: <20210107082718.33748-2-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107082718.33748-1-jingjing.wu@intel.com> References: <20210107074533.15465-1-jingjing.wu@intel.com> <20210107082718.33748-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 1/5] common/iavf: emulated pci interfaces on vfio-user client X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch implements Emulated pci interfaces on vfio-user client which is located in common/iavf/vfio_user/. Four main functions provided to upper layer (driver) to set up or talk to device: - client_vfio_user_setup - client_vfio_user_release - client_vfio_user_get_bar_addr - client_vfio_user_pci_bar_access ---------------------- | ------------------ | | | iavf driver | | | ------------------ | | ------------------ | | | device emulate | |------>(common/iavf/vfio_user/) | ------------------ | ---------------------- | | ---------------------- | vfio-user | | client | ---------------------- Signed-off-by: Jingjing Wu Signed-off-by: Chenbo Xia --- config/rte_config.h | 3 + drivers/common/iavf/iavf_common.c | 7 + drivers/common/iavf/iavf_impl.c | 45 +- drivers/common/iavf/iavf_osdep.h | 14 + drivers/common/iavf/iavf_type.h | 3 + drivers/common/iavf/meson.build | 11 +- drivers/common/iavf/version.map | 5 + drivers/common/iavf/vfio_user/vfio_user_pci.c | 525 ++++++++++++++++++ drivers/common/iavf/vfio_user/vfio_user_pci.h | 68 +++ 9 files changed, 679 insertions(+), 2 deletions(-) create mode 100644 drivers/common/iavf/vfio_user/vfio_user_pci.c create mode 100644 drivers/common/iavf/vfio_user/vfio_user_pci.h diff --git a/config/rte_config.h b/config/rte_config.h index a0b5160ff2..76ed1ae83f 100644 --- a/config/rte_config.h +++ b/config/rte_config.h @@ -151,4 +151,7 @@ #define RTE_LIBRTE_PMD_DLB2_SW_CREDIT_QUANTA 32 #define RTE_PMD_DLB2_DEFAULT_DEPTH_THRESH 256 +/* IAVF bsed on vfio_user client */ +#define RTE_LIBRTE_IAVF_CLIENT 1 + #endif /* _RTE_CONFIG_H_ */ diff --git a/drivers/common/iavf/iavf_common.c b/drivers/common/iavf/iavf_common.c index c951b7d787..2e68f5d08b 100644 --- a/drivers/common/iavf/iavf_common.c +++ b/drivers/common/iavf/iavf_common.c @@ -20,6 +20,13 @@ enum iavf_status iavf_set_mac_type(struct iavf_hw *hw) DEBUGFUNC("iavf_set_mac_type\n"); +#ifdef RTE_LIBRTE_IAVF_CLIENT + if (hw->bus.type == iavf_bus_type_vfio_user) { + hw->mac.type = IAVF_MAC_VF; + return status; + } +#endif + if (hw->vendor_id == IAVF_INTEL_VENDOR_ID) { switch (hw->device_id) { case IAVF_DEV_ID_X722_VF: diff --git a/drivers/common/iavf/iavf_impl.c b/drivers/common/iavf/iavf_impl.c index fc0da31753..79262bf50d 100644 --- a/drivers/common/iavf/iavf_impl.c +++ b/drivers/common/iavf/iavf_impl.c @@ -10,9 +10,14 @@ #include #include +#ifdef RTE_LIBRTE_IAVF_CLIENT +#include "vfio_user/vfio_user_pci.h" +#endif #include "iavf_type.h" #include "iavf_prototype.h" +int iavf_common_logger; + enum iavf_status iavf_allocate_dma_mem_d(__rte_unused struct iavf_hw *hw, struct iavf_dma_mem *mem, @@ -85,4 +90,42 @@ iavf_free_virt_mem_d(__rte_unused struct iavf_hw *hw, return IAVF_SUCCESS; } -RTE_LOG_REGISTER(iavf_common_logger, pmd.common.iavf, NOTICE); +#ifdef RTE_LIBRTE_IAVF_CLIENT +uint32_t +iavf_read_addr(struct iavf_hw *hw, uint32_t offset) +{ + uint32_t value = 0; + + if (!hw || !hw->hw_addr) + return 0; + + if (hw->bus.type == iavf_bus_type_vfio_user) + client_vfio_user_pci_bar_access( + (struct vfio_device *)hw->hw_addr, + 0, offset, 4, &value, false); + else + value = readl(hw->hw_addr + offset); + + return value; +} + +void +iavf_write_addr(struct iavf_hw *hw, uint32_t offset, uint32_t value) +{ + if (!hw || !hw->hw_addr) + return; + if (hw->bus.type == iavf_bus_type_vfio_user) + client_vfio_user_pci_bar_access( + (struct vfio_device *)hw->hw_addr, + 0, offset, 4, &value, true); + else + writel(value, hw->hw_addr + offset); +} +#endif + +RTE_INIT(iavf_common_init_log) +{ + iavf_common_logger = rte_log_register("pmd.common.iavf"); + if (iavf_common_logger >= 0) + rte_log_set_level(iavf_common_logger, RTE_LOG_NOTICE); +} diff --git a/drivers/common/iavf/iavf_osdep.h b/drivers/common/iavf/iavf_osdep.h index 7cba13ff74..025d48a702 100644 --- a/drivers/common/iavf/iavf_osdep.h +++ b/drivers/common/iavf/iavf_osdep.h @@ -107,8 +107,22 @@ writeq(uint64_t value, volatile void *addr) rte_write64(rte_cpu_to_le_64(value), addr); } +#ifdef RTE_LIBRTE_IAVF_CLIENT +struct iavf_hw; + +__rte_internal +uint32_t iavf_read_addr(struct iavf_hw *hw, uint32_t offset); +__rte_internal +void iavf_write_addr(struct iavf_hw *hw, uint32_t offset, uint32_t value); + +#define wr32(a, reg, value) iavf_write_addr((a), (reg), (value)) +#define rd32(a, reg) iavf_read_addr((a), (reg)) + +#else #define wr32(a, reg, value) writel((value), (a)->hw_addr + (reg)) #define rd32(a, reg) readl((a)->hw_addr + (reg)) +#endif /* RTE_LIBRTE_IAVF_CLIENT */ + #define wr64(a, reg, value) writeq((value), (a)->hw_addr + (reg)) #define rd64(a, reg) readq((a)->hw_addr + (reg)) diff --git a/drivers/common/iavf/iavf_type.h b/drivers/common/iavf/iavf_type.h index 0990c9aa33..faa4a21eac 100644 --- a/drivers/common/iavf/iavf_type.h +++ b/drivers/common/iavf/iavf_type.h @@ -264,6 +264,9 @@ enum iavf_bus_type { iavf_bus_type_pci, iavf_bus_type_pcix, iavf_bus_type_pci_express, +#ifdef RTE_LIBRTE_IAVF_CLIENT + iavf_bus_type_vfio_user, +#endif iavf_bus_type_reserved }; diff --git a/drivers/common/iavf/meson.build b/drivers/common/iavf/meson.build index 1f4d8b898d..e0160ea135 100644 --- a/drivers/common/iavf/meson.build +++ b/drivers/common/iavf/meson.build @@ -1,7 +1,16 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2019-2020 Intel Corporation -sources = files('iavf_adminq.c', 'iavf_common.c', 'iavf_impl.c') +includes += include_directories('vfio_user') + +sources = files( + 'iavf_adminq.c', + 'iavf_common.c', + 'iavf_impl.c', + 'vfio_user/vfio_user_pci.c' +) + +deps += ['vfio_user'] if cc.has_argument('-Wno-pointer-to-int-cast') cflags += '-Wno-pointer-to-int-cast' diff --git a/drivers/common/iavf/version.map b/drivers/common/iavf/version.map index e0f117197c..883d919487 100644 --- a/drivers/common/iavf/version.map +++ b/drivers/common/iavf/version.map @@ -7,6 +7,11 @@ INTERNAL { iavf_set_mac_type; iavf_shutdown_adminq; iavf_vf_parse_hw_config; + client_vfio_user_setup; + client_vfio_user_release; + client_vfio_user_get_bar_addr; + iavf_write_addr; + iavf_read_addr; local: *; }; diff --git a/drivers/common/iavf/vfio_user/vfio_user_pci.c b/drivers/common/iavf/vfio_user/vfio_user_pci.c new file mode 100644 index 0000000000..6e95ce4600 --- /dev/null +++ b/drivers/common/iavf/vfio_user/vfio_user_pci.c @@ -0,0 +1,525 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "vfio_user_pci.h" + +#define IAVF_MEM_EVENT_CLB_NAME "iavf_mem_event_clb" + +/* buffer length for irq set */ +#define MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \ + sizeof(int) * IAVF_CLIENT_MAX_VECTORS) +/* buffer length for region infor get */ +#define REG_INFO_GET_BUF_LEN (sizeof(struct vfio_region_info) + \ + sizeof(struct vfio_region_info_cap_sparse_mmap) \ + + 2 * sizeof(struct vfio_region_sparse_mmap_area)) + +static inline int +vfio_add_mr(struct vfio_device *dev, struct vfio_memory_region *mr) +{ + if (dev->nb_mrs == RTE_VUSER_MAX_DMA) { + CLIENT_LOG(ERR, "Exceed Maximum supported memory regions %d", + RTE_VUSER_MAX_DMA); + return -EINVAL; + } + + TAILQ_INSERT_HEAD(&dev->mrs_list, mr, link); + dev->nb_mrs++; + + CLIENT_LOG(DEBUG, "Add memory region: FD %d, VADDR 0x%lx," + " IOVA 0x%lx, Size 0x%lx", + mr->fd, mr->vaddr, mr->iova, mr->size); + return 0; +} + +static inline void +vfio_remove_mr(struct vfio_device *dev, struct vfio_memory_region *mr) +{ + if (dev->nb_mrs == 0) + return; + + CLIENT_LOG(DEBUG, "Remove memory region: FD %d, VADDR 0x%lx," + " IOVA 0x%lx, Size 0x%lx", + mr->fd, mr->vaddr, mr->iova, mr->size); + TAILQ_REMOVE(&dev->mrs_list, mr, link); + dev->nb_mrs--; + rte_free(mr); +} + +static int +update_vfio_memory_region(const struct rte_memseg_list *msl __rte_unused, + const struct rte_memseg *ms, void *arg) +{ + int ret = 0; + struct vfio_device *dev = arg; + struct vfio_memory_region *mr, *mrs; + struct rte_vfio_user_mem_reg mem; + uint64_t offset; + + mr = rte_zmalloc_socket("iavf_client_vfio_user", sizeof(*mr), + 0, SOCKET_ID_ANY); + if (mr == NULL) + return -ENOMEM; + + mr->vaddr = (uint64_t)(uintptr_t)ms->addr; + mr->iova = ms->iova; + mr->size = ms->len; + mr->fd = rte_memseg_get_fd_thread_unsafe(ms); + if (mr->fd == -1) { + CLIENT_LOG(ERR, "Error to get the memory fd"); + rte_free(mr); + return -EFAULT; + } + if (rte_memseg_get_fd_offset_thread_unsafe(ms, &offset) < 0) { + CLIENT_LOG(ERR, "Error to get the memory map offset"); + rte_free(mr); + return -EFAULT; + } + mr->offset = offset; + + TAILQ_FOREACH(mrs, &dev->mrs_list, link) { + if (mrs->vaddr == mr->vaddr) + return 0; + } + + ret = vfio_add_mr(dev, mr); + if (ret) { + CLIENT_LOG(ERR, "Error to add memory region"); + rte_free(mr); + return ret; + } + + mem.gpa = mr->iova; + mem.size = mr->size; + mem.fd_offset = mr->offset; + mem.protection = PROT_WRITE | PROT_READ; + mem.flags = RTE_VUSER_MEM_MAPPABLE; + + ret = rte_vfio_user_dma_map(dev->dev_id, &mem, &mr->fd, 1); + if (ret) { + CLIENT_LOG(ERR, "Error to send dma map request"); + vfio_remove_mr(dev, mr); + rte_free(mr); + return ret; + } + return ret; + +} + +static int +vfio_device_dma_map(struct vfio_device *dev) +{ + if (rte_memseg_walk_thread_unsafe(update_vfio_memory_region, dev) < 0) + return -1; + + return 0; +} + + +static void +vfio_device_dma_unmap(struct vfio_device *dev) +{ + int ret; + struct vfio_memory_region *mr; + + if (dev->nb_mrs == 0) + return; + + while ((mr = TAILQ_FIRST(&dev->mrs_list))) { + struct rte_vfio_user_mem_reg mem; + + mem.gpa = mr->iova; + mem.size = mr->size; + mem.fd_offset = mr->offset; + mem.protection = PROT_WRITE | PROT_READ; + ret = rte_vfio_user_dma_unmap(dev->dev_id, &mem, 1); + if (ret) + CLIENT_LOG(ERR, "Error to send dma unmap request for" + " mr FD %d, VADDR 0x%lx, IOVA 0x%lx, Size 0x%lx", + mr->fd, mr->vaddr, mr->iova, mr->size); + TAILQ_REMOVE(&dev->mrs_list, mr, link); + dev->nb_mrs--; + rte_free(mr); + } + return; +} + +static void +iavf_mem_event_cb(enum rte_mem_event type __rte_unused, + const void *addr, + size_t len __rte_unused, + void *arg) +{ + struct vfio_device *dev = arg; + struct rte_memseg_list *msl; + uint16_t ret; + + /* ignore externally allocated memory */ + msl = rte_mem_virt2memseg_list(addr); + if (msl->external) + return; + ret = vfio_device_dma_map(dev); + if (ret) + CLIENT_LOG(ERR, "DMA map failed"); +} + +static inline struct vfio_info_cap_header * +vfio_device_get_info_cap(struct vfio_region_info *info, int cap) +{ + struct vfio_info_cap_header *h; + size_t offset; + + offset = info->cap_offset; + while (offset != 0 && offset < info->argsz) { + h = (struct vfio_info_cap_header *)((uintptr_t)info + offset); + if (h->id == cap) { + return h; + } + offset = h->next; + } + + return NULL; +} + +static int +vfio_device_setup_sparse_mmaps(struct vfio_device *device, int index, + struct vfio_region_info *info, int *fds) +{ + struct vfio_info_cap_header *hdr; + struct vfio_region_info_cap_sparse_mmap *sparse; + struct vfio_pci_region *region = &device->regions[index]; + uint32_t i, j = 0; + int prot = 0; + + hdr = vfio_device_get_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP); + if (!hdr) { + CLIENT_LOG(ERR, "Device doesn't have sparse mmap"); + return -EEXIST; + } + + sparse = container_of(hdr, struct vfio_region_info_cap_sparse_mmap, header); + for (i = 0; i < sparse->nr_areas; i++) { + if (sparse->areas[i].size == 0) + continue; + region->mmaps[j].offset = sparse->areas[i].offset; + region->mmaps[j].size = sparse->areas[i].size; + prot |= info->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0; + prot |= info->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0; + if (*fds) { + /* Use single fd for now*/ + region->mmaps[j].mem = mmap(NULL, region->mmaps[j].size, + prot, MAP_SHARED, fds[0], + region->offset + region->mmaps[j].offset); + if (region->mmaps[j].mem == MAP_FAILED) { + CLIENT_LOG(ERR, "Device SPARSE MMAP failed"); + return -EIO; + } + } else { + CLIENT_LOG(ERR, "No valid fd, skip mmap for" + " bar %d region %u", index, i); + } + CLIENT_LOG(DEBUG, "Sparse region %u, Size 0x%llx," + " Offset 0x%llx, Map addr %p", + i, sparse->areas[i].size, + sparse->areas[i].offset, region->mmaps[j].mem); + j++; + } + device->regions[index].nr_mmaps = j; + + return 0; +} + +static int +vfio_device_map_region(struct vfio_device *device __rte_unused, + struct vfio_pci_region *region, int fd) +{ + int prot = 0; + + prot |= region->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0; + prot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0; + + region->mmaps[0].offset = 0; + region->mmaps[0].size = region->size; + + region->mmaps[0].mem = mmap(NULL, region->size, prot, MAP_SHARED, + fd, region->offset); + if (region->mmaps[0].mem == MAP_FAILED) { + CLIENT_LOG(ERR, "Device Region MMAP failed"); + return -EFAULT; + } + CLIENT_LOG(DEBUG, "Memory mapped to %p", region->mmaps[0].mem); + region->nr_mmaps = 1; + + return 0; +} + +static void +vfio_device_unmap_bars(struct vfio_device *dev) +{ + uint32_t i, j; + struct vfio_pci_region *region; + + for (i = 0; i < dev->pci_regions; i++) { + region = &dev->regions[i]; + for (j = 0; j < region->nr_mmaps; j++) { + if (region->mmaps[j].mem) + munmap(region->mmaps[j].mem, region->mmaps[j].size); + } + } + memset(dev->regions, 0, sizeof(dev->regions)); +} + +static int +vfio_user_create_irqfd(struct vfio_device *device, uint32_t count) +{ + uint32_t i; + + for (i = 0; i < count; i++) { + device->irqfds[i] = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (device->irqfds[i] < 0) { + CLIENT_LOG(ERR, "Failed to create irqfd"); + return -1; + } + } + device->nb_irqs = count; + return 0; +} + +struct vfio_device * +client_vfio_user_setup(const char *path, int socket) +{ + struct vfio_device *device = NULL; + char irq_set_buf[MSIX_IRQ_SET_BUF_LEN]; + char reg_get_buf[REG_INFO_GET_BUF_LEN]; + int fds[VFIO_MAXIMUM_SPARSE_MMAP_REGISONS]; + struct vfio_device_info dev_info = {}; + struct vfio_irq_info irq_info = {}; + struct vfio_irq_set *irq_set; + struct vfio_region_info *reg_info; + uint32_t i, irq_count; + int dev_id; + int ret; + + device = rte_zmalloc_socket("iavf_client_vfio_user", + sizeof(struct vfio_device), + 0, socket); + if (!device) + return NULL; + + TAILQ_INIT(&device->mrs_list); + + dev_id = rte_vfio_user_attach_dev(path); + if (dev_id < 0) { + rte_free(device); + CLIENT_LOG(ERR, "Error to setup vfio-user via path %s", path); + return NULL; + } + + device->dev_id = dev_id; + snprintf(device->name, sizeof(device->name), "vfio-user%u", dev_id); + snprintf(device->path, PATH_MAX, "%s", path); + + ret = rte_vfio_user_get_dev_info(dev_id, &dev_info); + if (ret) { + CLIENT_LOG(ERR, "Device get info failed"); + goto cleanup; + } + device->pci_regions = dev_info.num_regions; + device->flags = dev_info.flags; + + irq_info.argsz = sizeof(struct vfio_irq_info); + irq_info.index = VFIO_PCI_MSIX_IRQ_INDEX; + ret = rte_vfio_user_get_irq_info(dev_id, &irq_info); + if (ret) { + CLIENT_LOG(ERR, "IRQ get info failed"); + goto cleanup; + } + + if (irq_info.count) { + irq_count = RTE_MIN(irq_info.count, + (uint32_t)IAVF_CLIENT_MAX_VECTORS); + if (vfio_user_create_irqfd(device, irq_count)) + goto cleanup; + + irq_set = (struct vfio_irq_set *)irq_set_buf; + irq_set->argsz = sizeof(irq_set_buf); + irq_set->count = irq_count; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_TRIGGER; + irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; + irq_set->start = 0; + rte_memcpy(irq_set->data, device->irqfds, + sizeof(int) * IAVF_CLIENT_MAX_VECTORS); + ret = rte_vfio_user_set_irqs(dev_id, irq_set); + if (ret) { + CLIENT_LOG(ERR, "IRQ set failed"); + goto cleanup; + } + } + + reg_info = (struct vfio_region_info *)reg_get_buf; + + for (i = 0; i < device->pci_regions; i++) { + memset(reg_info, 0, REG_INFO_GET_BUF_LEN); + memset(fds, 0, sizeof(fds)); + + reg_info->index = i; + reg_info->argsz = sizeof(struct vfio_region_info); + ret = rte_vfio_user_get_reg_info(dev_id, reg_info, fds); + if (reg_info->argsz > sizeof(struct vfio_region_info)) + ret = rte_vfio_user_get_reg_info(dev_id, reg_info, fds); + if (ret) { + CLIENT_LOG(ERR, "Device setup bar %d failed", i); + goto cleanup; + } + + device->regions[i].size = reg_info->size; + device->regions[i].offset = reg_info->offset; + device->regions[i].flags = reg_info->flags; + + CLIENT_LOG(DEBUG, "Bar %d, Size 0x%llx, Offset 0x%llx," + " Flags 0x%x, Cap offset %u", + i, reg_info->size, reg_info->offset, + reg_info->flags, reg_info->cap_offset); + + /* Setup MMAP if any */ + if (reg_info->size && + (reg_info->flags & VFIO_REGION_INFO_FLAG_MMAP)) { + /* Try to map sparse region first */ + if (reg_info->flags & VFIO_REGION_INFO_FLAG_CAPS) + ret = vfio_device_setup_sparse_mmaps(device, i, + reg_info, fds); + else + ret = vfio_device_map_region(device, + &device->regions[i], fds[0]); + + if (ret != 0) { + CLIENT_LOG(ERR, "Setup Device %s region %d failed", + device->name, i); + goto cleanup; + } + } + } + + /* Register DMA Region */ + ret = vfio_device_dma_map(device); + if (ret) { + CLIENT_LOG(ERR, "Container DMA map failed"); + goto cleanup; + } + + CLIENT_LOG(DEBUG, "Device %s, Path %s Setup Successfully", + device->name, device->path); + + if (rte_mem_event_callback_register(IAVF_MEM_EVENT_CLB_NAME, + iavf_mem_event_cb, device)) { + if (rte_errno != ENOTSUP) { + CLIENT_LOG(ERR, "Failed to register mem event" + " callback"); + goto cleanup; + } + } + return device; + +cleanup: + rte_vfio_user_detach_dev(dev_id); + rte_free(device); + return NULL; +} + +void +client_vfio_user_release(struct vfio_device *dev) +{ + rte_mem_event_callback_unregister(IAVF_MEM_EVENT_CLB_NAME, dev); + + vfio_device_unmap_bars(dev); + vfio_device_dma_unmap(dev); + rte_vfio_user_detach_dev(dev->dev_id); + + rte_free(dev); +} + +void * +client_vfio_user_get_bar_addr(struct vfio_device *dev, uint32_t index, + uint64_t offset, uint32_t len) +{ + struct vfio_pci_region *region = &dev->regions[index]; + uint32_t i; + + if (!region->size || !(region->flags & VFIO_REGION_INFO_FLAG_MMAP)) + return NULL; + + for (i = 0; i < region->nr_mmaps; i++) { + if (region->mmaps[i].mem && + (region->mmaps[i].offset <= offset) && + ((offset + len) <= (region->mmaps[i].offset + region->mmaps[i].size))) { + return (void *)((uintptr_t)region->mmaps[i].mem + \ + offset - region->mmaps[i].offset); + } + } + + return NULL; +} + +int +client_vfio_user_pci_bar_access(struct vfio_device *dev, uint32_t index, + uint64_t offset, size_t len, + void *buf, bool is_write) +{ + struct vfio_pci_region *region = &dev->regions[index]; + uint64_t sparse_size, sparse_offset, bar_addr; + uint32_t i; + int ret; + + if ((offset + len > region->size) || + (is_write && !(region->flags & VFIO_REGION_INFO_FLAG_WRITE)) || + (!is_write && !(region->flags & VFIO_REGION_INFO_FLAG_READ))) + return -EINVAL; + + /* Read/write through MMAP */ + for (i = 0; i < region->nr_mmaps; i++) { + sparse_offset = region->mmaps[i].offset; + sparse_size = region->mmaps[i].offset + region->mmaps[i].size; + + if ((offset >= sparse_offset) && + (offset + len <= sparse_size)) { + bar_addr = (uint64_t)(uintptr_t)region->mmaps[i].mem + + offset - sparse_offset; + if (is_write) + rte_memcpy((void *)bar_addr, buf, len); + else + rte_memcpy(buf, (void *)bar_addr, len); + + return 0; + } + } + + /* Read/write through message */ + if (is_write) + ret = rte_vfio_user_region_write(dev->dev_id, index, + offset, len, buf); + else + ret = rte_vfio_user_region_read(dev->dev_id, index, + offset, len, buf); + return ret; +} diff --git a/drivers/common/iavf/vfio_user/vfio_user_pci.h b/drivers/common/iavf/vfio_user/vfio_user_pci.h new file mode 100644 index 0000000000..8a312a472c --- /dev/null +++ b/drivers/common/iavf/vfio_user/vfio_user_pci.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#ifndef _VFIO_USER_PCI_H_ +#define _VFIO_USER_PCI_H_ + +#include +#include + +#define IAVF_CLIENT_MAX_VECTORS 17 +#define VFIO_MAXIMUM_SPARSE_MMAP_REGISONS 8 + +struct vfio_memory_region { + TAILQ_ENTRY(vfio_memory_region) link; + uint64_t iova; + uint64_t size; /* bytes */ + uint64_t vaddr; + uint64_t offset; + int fd; +}; + +struct vfio_sparse_mmaps { + void *mem; + uint64_t offset; + size_t size; +}; + +struct vfio_pci_region { + uint64_t offset; + size_t size; + uint64_t flags; + uint32_t nr_mmaps; + struct vfio_sparse_mmaps mmaps[VFIO_MAXIMUM_SPARSE_MMAP_REGISONS]; +}; + +TAILQ_HEAD(vfio_memory_region_list, vfio_memory_region); + +struct vfio_device { + int dev_id; + char name[64]; + char path[PATH_MAX]; + uint64_t flags; + uint32_t pci_regions; + uint32_t nb_mrs; + uint32_t nb_irqs; + struct vfio_pci_region regions[VFIO_PCI_NUM_REGIONS]; + int irqfds[IAVF_CLIENT_MAX_VECTORS]; + struct vfio_memory_region_list mrs_list; +}; + +extern int iavf_common_logger; +#define CLIENT_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, iavf_common_logger, "%s(): " fmt "\n", \ + __func__, ## args) + +__rte_internal +struct vfio_device *client_vfio_user_setup(const char *path, int socket); +__rte_internal +void client_vfio_user_release(struct vfio_device *dev); +__rte_internal +void *client_vfio_user_get_bar_addr(struct vfio_device *dev, uint32_t index, + uint64_t offset, uint32_t len); +int client_vfio_user_pci_bar_access(struct vfio_device *dev, uint32_t index, + uint64_t offset, size_t len, void *buf, + bool is_write); + +#endif /* _VFIO_USER_PCI_H_ */ From patchwork Thu Jan 7 08:27:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 86115 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6B5BBA09FF; Thu, 7 Jan 2021 09:41:24 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 32854140F1E; Thu, 7 Jan 2021 09:41:10 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 5C70B140EF3 for ; Thu, 7 Jan 2021 09:41:08 +0100 (CET) IronPort-SDR: 0BXnVJGOsGCpDfrrRDJdW/raLmg4XVZVIvjDaiockFULMmKJmI/bcYMWLiGNHkXOy8l08xz4Yw BgNBjbtqOL8g== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="174819155" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="174819155" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jan 2021 00:41:07 -0800 IronPort-SDR: h1kWADr9wMe394r1AsyWyQJdGQPlFCfDqNF2ZQMgNO446Et4Cv2pMbaSO8p1nfiW1A6Gl/J+zo iDRv0XUNrXtQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="346928854" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by orsmga003.jf.intel.com with ESMTP; 07 Jan 2021 00:41:05 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Thu, 7 Jan 2021 16:27:15 +0800 Message-Id: <20210107082718.33748-3-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107082718.33748-1-jingjing.wu@intel.com> References: <20210107074533.15465-1-jingjing.wu@intel.com> <20210107082718.33748-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 2/5] net/iavf_client: introduce iavf driver on vfio-user client X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch add a new net driver based on vdev abstraction, i.e. iavf_client_ethdev.c. It is using common iavf functions to talk with Emulated pci interfaces based on vfio-user. ---------------------- | ------------------ | | | iavf driver | |----> (iavf_client_ethdev.c) | ------------------ | | ------------------ | | | device emulate | | | | vfio-user adapt| | | ------------------ | ---------------------- | | ---------------------- | vfio-user | | client | ---------------------- Signed-off-by: Jingjing Wu --- drivers/common/iavf/iavf_prototype.h | 1 + drivers/common/iavf/version.map | 1 + drivers/net/iavf/iavf.h | 18 +- drivers/net/iavf/iavf_client_ethdev.c | 290 ++++++++++++++++++++++++++ drivers/net/iavf/iavf_ethdev.c | 26 +-- drivers/net/iavf/iavf_rxtx.c | 23 +- drivers/net/iavf/meson.build | 1 + 7 files changed, 339 insertions(+), 21 deletions(-) create mode 100644 drivers/net/iavf/iavf_client_ethdev.c diff --git a/drivers/common/iavf/iavf_prototype.h b/drivers/common/iavf/iavf_prototype.h index f34e77db0f..3998d26dc0 100644 --- a/drivers/common/iavf/iavf_prototype.h +++ b/drivers/common/iavf/iavf_prototype.h @@ -83,6 +83,7 @@ void iavf_destroy_spinlock(struct iavf_spinlock *sp); __rte_internal void iavf_vf_parse_hw_config(struct iavf_hw *hw, struct virtchnl_vf_resource *msg); +__rte_internal enum iavf_status iavf_vf_reset(struct iavf_hw *hw); __rte_internal enum iavf_status iavf_aq_send_msg_to_pf(struct iavf_hw *hw, diff --git a/drivers/common/iavf/version.map b/drivers/common/iavf/version.map index 883d919487..23c3577b3e 100644 --- a/drivers/common/iavf/version.map +++ b/drivers/common/iavf/version.map @@ -7,6 +7,7 @@ INTERNAL { iavf_set_mac_type; iavf_shutdown_adminq; iavf_vf_parse_hw_config; + iavf_vf_reset; client_vfio_user_setup; client_vfio_user_release; client_vfio_user_get_bar_addr; diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h index 6d5912d8c1..c34f971721 100644 --- a/drivers/net/iavf/iavf.h +++ b/drivers/net/iavf/iavf.h @@ -195,7 +195,10 @@ struct iavf_adapter { struct iavf_hw hw; struct rte_eth_dev *eth_dev; struct iavf_info vf; - +#ifdef RTE_LIBRTE_IAVF_CLIENT + /* used for avf_client driver */ + struct vfio_device *user_dev; +#endif bool rx_bulk_alloc_allowed; /* For vector PMD */ bool rx_vec_allowed; @@ -231,6 +234,16 @@ iavf_init_adminq_parameter(struct iavf_hw *hw) hw->aq.asq_buf_size = IAVF_AQ_BUF_SZ; } +static inline void +iavf_disable_irq0(struct iavf_hw *hw) +{ + /* Disable all interrupt types */ + IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1, 0); + IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01, + IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK); + IAVF_WRITE_FLUSH(hw); +} + static inline uint16_t iavf_calc_itr_interval(int16_t interval) { @@ -284,6 +297,9 @@ _atomic_set_cmd(struct iavf_info *vf, enum virtchnl_ops ops) return !ret; } +extern const struct eth_dev_ops iavf_eth_dev_ops; + +int iavf_init_vf(struct rte_eth_dev *dev); int iavf_check_api_version(struct iavf_adapter *adapter); int iavf_get_vf_resource(struct iavf_adapter *adapter); void iavf_handle_virtchnl_msg(struct rte_eth_dev *dev); diff --git a/drivers/net/iavf/iavf_client_ethdev.c b/drivers/net/iavf/iavf_client_ethdev.c new file mode 100644 index 0000000000..989f9d6062 --- /dev/null +++ b/drivers/net/iavf/iavf_client_ethdev.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iavf.h" +#include "iavf_rxtx.h" + +static int iavf_client_dev_close(struct rte_eth_dev *dev); +static int iavf_client_dev_reset(struct rte_eth_dev *dev); + +/* set iavf_client_dev_ops to iavf's by default */ +static struct eth_dev_ops iavf_client_eth_dev_ops; + +static const char *valid_args[] = { +#define AVF_CLIENT_ARG_PATH "path" + AVF_CLIENT_ARG_PATH, + NULL +}; + +/* set up vfio_device for iavf_client*/ +static int +iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); + struct vfio_device *vfio_dev; + + vfio_dev = client_vfio_user_setup(path, dev->device->numa_node); + if (vfio_dev == NULL) { + PMD_INIT_LOG(ERR, "Error to create vfio_device for iavf_client\n"); + return -1; + } + hw->bus.type = iavf_bus_type_vfio_user; + + /* Use hw_addr to record dev ptr */ + hw->hw_addr = (uint8_t *)vfio_dev; + + hw->back = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + + if (!dev->intr_handle) { + dev->intr_handle = rte_zmalloc_socket("iavf_client_intr", + sizeof(*dev->intr_handle), + 0, dev->device->numa_node); + if (!dev->intr_handle) { + PMD_INIT_LOG(ERR, "fail to allocate intr_handle"); + return -1; + } + + } + + dev->intr_handle->fd = -1; + dev->intr_handle->type = RTE_INTR_HANDLE_VDEV; + dev->intr_handle->max_intr = 1; + + return 0; +} + + +static inline void +avf_client_init_eth_ops(void) +{ + iavf_client_eth_dev_ops = iavf_eth_dev_ops; + /* keep other unchanged */ + iavf_client_eth_dev_ops.dev_close = iavf_client_dev_close, + iavf_client_eth_dev_ops.dev_reset = iavf_client_dev_reset, + iavf_client_eth_dev_ops.dev_supported_ptypes_get = NULL; + iavf_client_eth_dev_ops.reta_update = NULL; + iavf_client_eth_dev_ops.reta_query = NULL; + iavf_client_eth_dev_ops.rss_hash_update = NULL; + iavf_client_eth_dev_ops.rss_hash_conf_get = NULL; + iavf_client_eth_dev_ops.rx_queue_intr_enable = NULL; + iavf_client_eth_dev_ops.rx_queue_intr_disable = NULL; +} + +#define IAVF_CLIENT_ALARM_INTERVAL 50000 /* us */ +static void +iavf_client_dev_alarm_handler(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + + iavf_handle_virtchnl_msg(dev); + + rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, + iavf_client_dev_alarm_handler, dev); +} + +/* init ethdev for the avf client device*/ +static int +iavf_client_eth_init(struct rte_eth_dev *eth_dev) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); + + /* update eth_dev_op by assigning ops func pointer */ + avf_client_init_eth_ops(); + eth_dev->dev_ops = (const struct eth_dev_ops *)(&iavf_client_eth_dev_ops); + + eth_dev->rx_pkt_burst = &iavf_recv_pkts; + eth_dev->tx_pkt_burst = &iavf_xmit_pkts; + eth_dev->tx_pkt_prepare = &iavf_prep_pkts; + + hw->back = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + adapter->eth_dev = eth_dev; + adapter->stopped = 1; + + if (iavf_init_vf(eth_dev) != 0) { + PMD_INIT_LOG(ERR, "Init vf failed"); + return -1; + } + + /* set default ptype table */ + adapter->ptype_tbl = iavf_get_default_ptype_table(); + + /* copy mac addr */ + eth_dev->data->mac_addrs = rte_zmalloc( + "iavf_client_mac", + RTE_ETHER_ADDR_LEN * IAVF_NUM_MACADDR_MAX, 0); + if (!eth_dev->data->mac_addrs) { + PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to" + " store MAC addresses", + RTE_ETHER_ADDR_LEN * IAVF_NUM_MACADDR_MAX); + return -ENOMEM; + } + /* If the MAC address is not configured by host, + * generate a random one. + */ + if (!rte_is_valid_assigned_ether_addr( + (struct rte_ether_addr *)hw->mac.addr)) + rte_eth_random_addr(hw->mac.addr); + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr, + ð_dev->data->mac_addrs[0]); + + rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, + iavf_client_dev_alarm_handler, eth_dev); + return 0; +} + +static int +iavf_client_dev_reset(struct rte_eth_dev *dev) +{ + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret; + + rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); + + iavf_shutdown_adminq(hw); + ret = iavf_init_vf(dev); + + /* send reset msg to PF */ + iavf_vf_reset(hw); + rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, + iavf_client_dev_alarm_handler, dev); + + return ret; +} + +static int +iavf_client_dev_close(struct rte_eth_dev *dev) +{ + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + if (!adapter->stopped) { + iavf_stop_queues(dev); + + if (dev->intr_handle) { + rte_free(dev->intr_handle); + dev->intr_handle = NULL; + } + + /* Remove all mac addrs */ + iavf_add_del_all_mac_addr(adapter, false); + adapter->stopped = 1; + } + iavf_shutdown_adminq(hw); + iavf_disable_irq0(hw); + rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); + client_vfio_user_release((struct vfio_device *)hw->hw_addr); + return 0; +} + +static int +iavf_client_get_string_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(char **)extra_args = strdup(value); + + if (!*(char **)extra_args) + return -ENOMEM; + + return 0; +} + +static int +iavf_client_pmd_probe(struct rte_vdev_device *vdev) +{ + struct rte_kvargs *kvlist = NULL; + struct rte_eth_dev *eth_dev; + struct iavf_adapter *adapter; + char *path = NULL; + int ret; + + kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_args); + if (!kvlist) { + PMD_INIT_LOG(ERR, "error when parsing param"); + return -EINVAL; + } + + if (rte_kvargs_count(kvlist, AVF_CLIENT_ARG_PATH) == 1) { + if (rte_kvargs_process(kvlist, AVF_CLIENT_ARG_PATH, + &iavf_client_get_string_arg, &path) < 0) { + PMD_INIT_LOG(ERR, "error to parse %s", + AVF_CLIENT_ARG_PATH); + return -EINVAL; + } + } else { + PMD_INIT_LOG(ERR, "arg %s is mandatory for iavf_client", + AVF_CLIENT_ARG_PATH); + return -EINVAL; + } + + eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*adapter)); + + ret = iavf_client_vfio_user_setup(eth_dev, path); + if (ret) { + goto err; + } + + ret = iavf_client_eth_init(eth_dev); + if (ret) { + goto err; + } + + rte_eth_dev_probing_finish(eth_dev); + rte_kvargs_free(kvlist); + + return 0; +err: + rte_eth_dev_release_port(eth_dev); + rte_kvargs_free(kvlist); + return ret; +} + + +static int +iavf_client_pmd_remove(struct rte_vdev_device *vdev) +{ + struct rte_eth_dev *eth_dev = NULL; + + if (vdev == NULL) + return -1; + + /* find the ethdev entry */ + eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev)); + if (eth_dev == NULL) + return 0; + + iavf_client_dev_close(eth_dev); + rte_eth_dev_release_port(eth_dev); + return 0; +} + +static struct rte_vdev_driver iavf_client_driver = { + .probe = iavf_client_pmd_probe, + .remove = iavf_client_pmd_remove, +}; + +RTE_PMD_REGISTER_VDEV(net_iavf_client, iavf_client_driver); +RTE_PMD_REGISTER_ALIAS(net_iavf_client, iavf_client); +RTE_PMD_REGISTER_PARAM_STRING(net_iavf_client, + "path="); diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index 7e3c26a94e..6b5e47adf2 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -154,7 +154,7 @@ static const struct rte_iavf_xstats_name_off rte_iavf_stats_strings[] = { #define IAVF_NB_XSTATS (sizeof(rte_iavf_stats_strings) / \ sizeof(rte_iavf_stats_strings[0])) -static const struct eth_dev_ops iavf_eth_dev_ops = { +const struct eth_dev_ops iavf_eth_dev_ops = { .dev_configure = iavf_dev_configure, .dev_start = iavf_dev_start, .dev_stop = iavf_dev_stop, @@ -1780,7 +1780,7 @@ iavf_init_proto_xtr(struct rte_eth_dev *dev) } } -static int +int iavf_init_vf(struct rte_eth_dev *dev) { int err, bufsz; @@ -1789,12 +1789,6 @@ iavf_init_vf(struct rte_eth_dev *dev) struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); - err = iavf_parse_devargs(dev); - if (err) { - PMD_INIT_LOG(ERR, "Failed to parse devargs"); - goto err; - } - err = iavf_set_mac_type(hw); if (err) { PMD_INIT_LOG(ERR, "set_mac_type failed: %d", err); @@ -1891,16 +1885,6 @@ iavf_enable_irq0(struct iavf_hw *hw) IAVF_WRITE_FLUSH(hw); } -static inline void -iavf_disable_irq0(struct iavf_hw *hw) -{ - /* Disable all interrupt types */ - IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1, 0); - IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01, - IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK); - IAVF_WRITE_FLUSH(hw); -} - static void iavf_dev_interrupt_handler(void *param) { @@ -1986,6 +1970,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev) adapter->eth_dev = eth_dev; adapter->stopped = 1; + ret = iavf_parse_devargs(eth_dev); + if (ret) { + PMD_INIT_LOG(ERR, "Failed to parse devargs"); + return ret; + } + if (iavf_init_vf(eth_dev) != 0) { PMD_INIT_LOG(ERR, "Init vf failed"); return -1; diff --git a/drivers/net/iavf/iavf_rxtx.c b/drivers/net/iavf/iavf_rxtx.c index 21d508b3f4..d8192f3675 100644 --- a/drivers/net/iavf/iavf_rxtx.c +++ b/drivers/net/iavf/iavf_rxtx.c @@ -24,6 +24,9 @@ #include #include #include +#ifdef RTE_LIBRTE_IAVF_CLIENT +#include +#endif #include "iavf.h" #include "iavf_rxtx.h" @@ -595,7 +598,15 @@ iavf_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx, reset_rx_queue(rxq); rxq->q_set = true; dev->data->rx_queues[queue_idx] = rxq; - rxq->qrx_tail = hw->hw_addr + IAVF_QRX_TAIL1(rxq->queue_id); + +#ifdef RTE_LIBRTE_IAVF_CLIENT + if (hw->bus.type == iavf_bus_type_vfio_user) + rxq->qrx_tail = client_vfio_user_get_bar_addr( + (struct vfio_device *)hw->hw_addr, 0, + IAVF_QRX_TAIL1(rxq->queue_id), 4); + else +#endif + rxq->qrx_tail = hw->hw_addr + IAVF_QRX_TAIL1(rxq->queue_id); rxq->ops = &def_rxq_ops; if (check_rx_bulk_allow(rxq) == true) { @@ -705,7 +716,15 @@ iavf_dev_tx_queue_setup(struct rte_eth_dev *dev, reset_tx_queue(txq); txq->q_set = true; dev->data->tx_queues[queue_idx] = txq; - txq->qtx_tail = hw->hw_addr + IAVF_QTX_TAIL1(queue_idx); +#ifdef RTE_LIBRTE_IAVF_CLIENT + if (hw->bus.type == iavf_bus_type_vfio_user) + txq->qtx_tail = client_vfio_user_get_bar_addr( + (struct vfio_device *)hw->hw_addr, 0, + IAVF_QTX_TAIL1(queue_idx), 4); + else +#endif + txq->qtx_tail = hw->hw_addr + IAVF_QTX_TAIL1(queue_idx); + txq->ops = &def_txq_ops; if (check_tx_vec_allow(txq) == false) { diff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build index 26c02c4401..580307c462 100644 --- a/drivers/net/iavf/meson.build +++ b/drivers/net/iavf/meson.build @@ -13,6 +13,7 @@ sources = files( 'iavf_generic_flow.c', 'iavf_fdir.c', 'iavf_hash.c', + 'iavf_client_ethdev.c', ) if arch_subdir == 'x86' From patchwork Thu Jan 7 08:27:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 86116 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id EFBC5A09FF; Thu, 7 Jan 2021 09:41:33 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 72B29140F19; Thu, 7 Jan 2021 09:41:13 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 8A949140F27 for ; Thu, 7 Jan 2021 09:41:11 +0100 (CET) IronPort-SDR: QAfUbTFs+cTve3yV9cfCj1FgQkgnsSp1d78tw3JdR9uOjW00PF/uLUSl9MCZmUsZQhiLJELVwQ z60EFdXa9EDQ== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="174819156" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="174819156" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jan 2021 00:41:10 -0800 IronPort-SDR: z/W76uWa/qfvn2DwwJ1h8J5J1B7c5/Fsb+cF3XMTdCz/AbPy7HeeR52EadiPLnDa3Bt0PP9CeT bthYxWI+y3nw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="346928863" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by orsmga003.jf.intel.com with ESMTP; 07 Jan 2021 00:41:07 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Thu, 7 Jan 2021 16:27:16 +0800 Message-Id: <20210107082718.33748-4-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107082718.33748-1-jingjing.wu@intel.com> References: <20210107074533.15465-1-jingjing.wu@intel.com> <20210107082718.33748-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 3/5] net/iavf_client: enable interrupt on control queue X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" New devarg "intr": if intr=1, use interrupt mode on control queue Signed-off-by: Jingjing Wu --- drivers/net/iavf/iavf.h | 19 ++++ drivers/net/iavf/iavf_client_ethdev.c | 131 ++++++++++++++++++++++---- drivers/net/iavf/iavf_ethdev.c | 18 +--- 3 files changed, 134 insertions(+), 34 deletions(-) diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h index c34f971721..5516ecf021 100644 --- a/drivers/net/iavf/iavf.h +++ b/drivers/net/iavf/iavf.h @@ -198,6 +198,7 @@ struct iavf_adapter { #ifdef RTE_LIBRTE_IAVF_CLIENT /* used for avf_client driver */ struct vfio_device *user_dev; + int intr_mode; /* interrupt mode if true */ #endif bool rx_bulk_alloc_allowed; /* For vector PMD */ @@ -234,6 +235,22 @@ iavf_init_adminq_parameter(struct iavf_hw *hw) hw->aq.asq_buf_size = IAVF_AQ_BUF_SZ; } +/* Enable default admin queue interrupt setting */ +static inline void +iavf_enable_irq0(struct iavf_hw *hw) +{ + /* Enable admin queue interrupt trigger */ + IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1, + IAVF_VFINT_ICR0_ENA1_ADMINQ_MASK); + + IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01, + IAVF_VFINT_DYN_CTL01_INTENA_MASK | + IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK | + IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK); + + IAVF_WRITE_FLUSH(hw); +} + static inline void iavf_disable_irq0(struct iavf_hw *hw) { @@ -342,4 +359,6 @@ int iavf_add_del_mc_addr_list(struct iavf_adapter *adapter, uint32_t mc_addrs_num, bool add); int iavf_request_queues(struct iavf_adapter *adapter, uint16_t num); int iavf_get_max_rss_queue_region(struct iavf_adapter *adapter); +void iavf_dev_interrupt_handler(void *param); + #endif /* _IAVF_ETHDEV_H_ */ diff --git a/drivers/net/iavf/iavf_client_ethdev.c b/drivers/net/iavf/iavf_client_ethdev.c index 989f9d6062..770a7a8200 100644 --- a/drivers/net/iavf/iavf_client_ethdev.c +++ b/drivers/net/iavf/iavf_client_ethdev.c @@ -6,6 +6,8 @@ #include #include +#include + #include #include #include @@ -18,6 +20,9 @@ #include "iavf.h" #include "iavf_rxtx.h" +#define AVF_CLIENT_ARG_PATH "path" +#define AVF_CLIENT_ARG_INTR "intr" + static int iavf_client_dev_close(struct rte_eth_dev *dev); static int iavf_client_dev_reset(struct rte_eth_dev *dev); @@ -25,11 +30,27 @@ static int iavf_client_dev_reset(struct rte_eth_dev *dev); static struct eth_dev_ops iavf_client_eth_dev_ops; static const char *valid_args[] = { -#define AVF_CLIENT_ARG_PATH "path" AVF_CLIENT_ARG_PATH, + AVF_CLIENT_ARG_INTR, NULL }; +static void +iavf_client_event_handler(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + eventfd_t buf; + + eventfd_read(dev->intr_handle->fd, &buf); + + iavf_disable_irq0(hw); + + iavf_handle_virtchnl_msg(dev); + + iavf_enable_irq0(hw); +} + /* set up vfio_device for iavf_client*/ static int iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) @@ -51,6 +72,11 @@ iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) hw->back = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + if (!vfio_dev->nb_irqs && adapter->intr_mode) { + PMD_INIT_LOG(ERR, "No irq support on device"); + return -1; + } + if (!dev->intr_handle) { dev->intr_handle = rte_zmalloc_socket("iavf_client_intr", sizeof(*dev->intr_handle), @@ -62,7 +88,7 @@ iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) } - dev->intr_handle->fd = -1; + dev->intr_handle->fd = vfio_dev->irqfds[0]; dev->intr_handle->type = RTE_INTR_HANDLE_VDEV; dev->intr_handle->max_intr = 1; @@ -145,26 +171,52 @@ iavf_client_eth_init(struct rte_eth_dev *eth_dev) rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr, ð_dev->data->mac_addrs[0]); - rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, - iavf_client_dev_alarm_handler, eth_dev); + if (adapter->intr_mode) { + /* register callback func to eal lib */ + rte_intr_callback_register(eth_dev->intr_handle, + iavf_client_event_handler, + (void *)eth_dev); + iavf_enable_irq0(hw); + } else { + rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, + iavf_client_dev_alarm_handler, eth_dev); + } return 0; } static int iavf_client_dev_reset(struct rte_eth_dev *dev) { + struct iavf_adapter *adapter = + IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_intr_handle *intr_handle = dev->intr_handle; int ret; - rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); + if (adapter->intr_mode) { + iavf_disable_irq0(hw); + /* unregister callback func from eal lib */ + rte_intr_callback_unregister(intr_handle, + iavf_client_event_handler, dev); + } else { + rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); + } iavf_shutdown_adminq(hw); ret = iavf_init_vf(dev); /* send reset msg to PF */ iavf_vf_reset(hw); - rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, - iavf_client_dev_alarm_handler, dev); + if (adapter->intr_mode) { + /* register callback func to eal lib */ + rte_intr_callback_register(dev->intr_handle, + iavf_client_event_handler, + (void *)dev); + iavf_enable_irq0(hw); + } else { + rte_eal_alarm_set(IAVF_CLIENT_ALARM_INTERVAL, + iavf_client_dev_alarm_handler, dev); + } return ret; } @@ -176,6 +228,15 @@ iavf_client_dev_close(struct rte_eth_dev *dev) IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (adapter->intr_mode) { + iavf_disable_irq0(hw); + /* unregister callback func from eal lib */ + rte_intr_callback_unregister(dev->intr_handle, + iavf_client_event_handler, dev); + } else { + rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); + } + if (!adapter->stopped) { iavf_stop_queues(dev); @@ -188,10 +249,10 @@ iavf_client_dev_close(struct rte_eth_dev *dev) iavf_add_del_all_mac_addr(adapter, false); adapter->stopped = 1; } + iavf_shutdown_adminq(hw); - iavf_disable_irq0(hw); - rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); client_vfio_user_release((struct vfio_device *)hw->hw_addr); + return 0; } @@ -210,6 +271,23 @@ iavf_client_get_string_arg(const char *key __rte_unused, return 0; } +static int +iavf_client_intr_check(__rte_unused const char *key, + const char *value, void *opaque) +{ + int *intr = (int *)opaque; + int ret = 0; + + if (!strcmp(value, "1")) + *intr = 1; + else if (!strcmp(value, "0")) + *intr = 0; + else + ret = -1; + + return ret; +} + static int iavf_client_pmd_probe(struct rte_vdev_device *vdev) { @@ -217,6 +295,7 @@ iavf_client_pmd_probe(struct rte_vdev_device *vdev) struct rte_eth_dev *eth_dev; struct iavf_adapter *adapter; char *path = NULL; + int intr_mode = 0; int ret; kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_args); @@ -227,35 +306,52 @@ iavf_client_pmd_probe(struct rte_vdev_device *vdev) if (rte_kvargs_count(kvlist, AVF_CLIENT_ARG_PATH) == 1) { if (rte_kvargs_process(kvlist, AVF_CLIENT_ARG_PATH, - &iavf_client_get_string_arg, &path) < 0) { + &iavf_client_get_string_arg, + &path) < 0) { PMD_INIT_LOG(ERR, "error to parse %s", AVF_CLIENT_ARG_PATH); - return -EINVAL; + ret = -EINVAL; + goto free_kvlist; } } else { PMD_INIT_LOG(ERR, "arg %s is mandatory for iavf_client", AVF_CLIENT_ARG_PATH); - return -EINVAL; + ret = -EINVAL; + goto free_kvlist; + } + + if (rte_kvargs_count(kvlist, AVF_CLIENT_ARG_INTR) == 1) { + if (rte_kvargs_process(kvlist, AVF_CLIENT_ARG_INTR, + iavf_client_intr_check, + &intr_mode) < 0) { + PMD_INIT_LOG(ERR, "arg %s must be 1 or 0", + AVF_CLIENT_ARG_INTR); + ret = -EINVAL; + goto free_kvlist; + } } eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*adapter)); ret = iavf_client_vfio_user_setup(eth_dev, path); - if (ret) { + if (ret) goto err; - } + + adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + adapter->intr_mode = intr_mode; ret = iavf_client_eth_init(eth_dev); - if (ret) { + if (ret) goto err; - } rte_eth_dev_probing_finish(eth_dev); + rte_kvargs_free(kvlist); return 0; err: rte_eth_dev_release_port(eth_dev); +free_kvlist: rte_kvargs_free(kvlist); return ret; } @@ -287,4 +383,5 @@ static struct rte_vdev_driver iavf_client_driver = { RTE_PMD_REGISTER_VDEV(net_iavf_client, iavf_client_driver); RTE_PMD_REGISTER_ALIAS(net_iavf_client, iavf_client); RTE_PMD_REGISTER_PARAM_STRING(net_iavf_client, - "path="); + "path=" + "intr=[0|1]"); diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index 6b5e47adf2..bc07ecbed7 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -1869,23 +1869,7 @@ iavf_init_vf(struct rte_eth_dev *dev) return -1; } -/* Enable default admin queue interrupt setting */ -static inline void -iavf_enable_irq0(struct iavf_hw *hw) -{ - /* Enable admin queue interrupt trigger */ - IAVF_WRITE_REG(hw, IAVF_VFINT_ICR0_ENA1, - IAVF_VFINT_ICR0_ENA1_ADMINQ_MASK); - - IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01, - IAVF_VFINT_DYN_CTL01_INTENA_MASK | - IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK | - IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK); - - IAVF_WRITE_FLUSH(hw); -} - -static void +void iavf_dev_interrupt_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; From patchwork Thu Jan 7 08:27:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 86117 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DE230A09FF; Thu, 7 Jan 2021 09:41:43 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B68AC140F07; Thu, 7 Jan 2021 09:41:16 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 389DD140F06 for ; Thu, 7 Jan 2021 09:41:15 +0100 (CET) IronPort-SDR: aLs42ceKL+H5W8x5lznN8psEnjf4JdJ5ik2Kc70ePwdgxKnQdGuEw74LYTODZ91MOl7HGFzIcx hrtwcn4jeWGA== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="174819162" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="174819162" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jan 2021 00:41:14 -0800 IronPort-SDR: OC8wVmEG6u57o5F2vCcw7ffl4zl+nbM7iJNhhxW5lAtBuDj6zebfm8rwfvpeppq/BxaqAP9Lwt b+8PWldzGuhw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="346928876" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by orsmga003.jf.intel.com with ESMTP; 07 Jan 2021 00:41:10 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Thu, 7 Jan 2021 16:27:17 +0800 Message-Id: <20210107082718.33748-5-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107082718.33748-1-jingjing.wu@intel.com> References: <20210107074533.15465-1-jingjing.wu@intel.com> <20210107082718.33748-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 4/5] net/iavf_client: enable interrupt of Rx queue X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Signed-off-by: Jingjing Wu --- drivers/net/iavf/iavf_client_ethdev.c | 29 +++++++++++++++++++++------ drivers/net/iavf/iavf_ethdev.c | 9 +++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/iavf/iavf_client_ethdev.c b/drivers/net/iavf/iavf_client_ethdev.c index 770a7a8200..27daaed0e8 100644 --- a/drivers/net/iavf/iavf_client_ethdev.c +++ b/drivers/net/iavf/iavf_client_ethdev.c @@ -59,6 +59,7 @@ iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); struct vfio_device *vfio_dev; + uint32_t max_fds, i; vfio_dev = client_vfio_user_setup(path, dev->device->numa_node); if (vfio_dev == NULL) { @@ -87,11 +88,21 @@ iavf_client_vfio_user_setup(struct rte_eth_dev *dev, const char *path) } } - dev->intr_handle->fd = vfio_dev->irqfds[0]; dev->intr_handle->type = RTE_INTR_HANDLE_VDEV; dev->intr_handle->max_intr = 1; + /* Assign rxq fds */ + if (vfio_dev->nb_irqs > 1) { + max_fds = RTE_MIN((uint32_t)RTE_MAX_RXTX_INTR_VEC_ID, + vfio_dev->nb_irqs - 1); + dev->intr_handle->nb_efd = max_fds; + for (i = 0; i < max_fds; ++i) + dev->intr_handle->efds[i] = + vfio_dev->irqfds[i + RTE_INTR_VEC_RXTX_OFFSET]; + dev->intr_handle->efd_counter_size = 0; + dev->intr_handle->max_intr += max_fds; + } return 0; } @@ -108,8 +119,6 @@ avf_client_init_eth_ops(void) iavf_client_eth_dev_ops.reta_query = NULL; iavf_client_eth_dev_ops.rss_hash_update = NULL; iavf_client_eth_dev_ops.rss_hash_conf_get = NULL; - iavf_client_eth_dev_ops.rx_queue_intr_enable = NULL; - iavf_client_eth_dev_ops.rx_queue_intr_disable = NULL; } #define IAVF_CLIENT_ALARM_INTERVAL 50000 /* us */ @@ -227,11 +236,12 @@ iavf_client_dev_close(struct rte_eth_dev *dev) struct iavf_adapter *adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_intr_handle *intr_handle = dev->intr_handle; if (adapter->intr_mode) { iavf_disable_irq0(hw); /* unregister callback func from eal lib */ - rte_intr_callback_unregister(dev->intr_handle, + rte_intr_callback_unregister(intr_handle, iavf_client_event_handler, dev); } else { rte_eal_alarm_cancel(iavf_client_dev_alarm_handler, dev); @@ -240,8 +250,15 @@ iavf_client_dev_close(struct rte_eth_dev *dev) if (!adapter->stopped) { iavf_stop_queues(dev); - if (dev->intr_handle) { - rte_free(dev->intr_handle); + if (intr_handle) { + /* Disable the interrupt for Rx */ + rte_intr_efd_disable(intr_handle); + /* Rx interrupt vector mapping free */ + if (intr_handle->intr_vec) { + rte_free(intr_handle->intr_vec); + intr_handle->intr_vec = NULL; + } + rte_free(intr_handle); dev->intr_handle = NULL; } diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index bc07ecbed7..06395f852b 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -1368,11 +1368,10 @@ iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) { struct iavf_adapter *adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); - struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); uint16_t msix_intr; - msix_intr = pci_dev->intr_handle.intr_vec[queue_id]; + msix_intr = dev->intr_handle->intr_vec[queue_id]; if (msix_intr == IAVF_MISC_VEC_ID) { PMD_DRV_LOG(INFO, "MISC is also enabled for control"); IAVF_WRITE_REG(hw, IAVF_VFINT_DYN_CTL01, @@ -1387,10 +1386,9 @@ iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) IAVF_VFINT_DYN_CTL01_CLEARPBA_MASK | IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK); } - IAVF_WRITE_FLUSH(hw); - rte_intr_ack(&pci_dev->intr_handle); + rte_intr_ack(dev->intr_handle); return 0; } @@ -1398,11 +1396,10 @@ iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { - struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); uint16_t msix_intr; - msix_intr = pci_dev->intr_handle.intr_vec[queue_id]; + msix_intr = dev->intr_handle->intr_vec[queue_id]; if (msix_intr == IAVF_MISC_VEC_ID) { PMD_DRV_LOG(ERR, "MISC is used for control, cannot disable it"); return -EIO; From patchwork Thu Jan 7 08:27:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jingjing Wu X-Patchwork-Id: 86118 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C460CA09FF; Thu, 7 Jan 2021 09:41:54 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 748BF140F3E; Thu, 7 Jan 2021 09:41:20 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 4F42E140F31 for ; Thu, 7 Jan 2021 09:41:17 +0100 (CET) IronPort-SDR: qzO5uhltdR48g856wkPoj/pgz9Ve1Q0c+/OaB8qLGFSNgpuS1LrzLzrDIt4rjpZPEo6h8+sVw/ OVmqQov+mgLQ== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="174819166" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="174819166" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Jan 2021 00:41:16 -0800 IronPort-SDR: y7x4+y6uEwic3STd52rGY/V+KikC9nT582JiYn086KHea9AoIlqqi6oOwHyGqoMNstQUofKN1V R9BLaSAviV7A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="346928888" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by orsmga003.jf.intel.com with ESMTP; 07 Jan 2021 00:41:14 -0800 From: Jingjing Wu To: dev@dpdk.org Cc: jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com, xiuchun.lu@intel.com Date: Thu, 7 Jan 2021 16:27:18 +0800 Message-Id: <20210107082718.33748-6-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107082718.33748-1-jingjing.wu@intel.com> References: <20210107074533.15465-1-jingjing.wu@intel.com> <20210107082718.33748-1-jingjing.wu@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 5/5] net/iavf: fix vector mapping with queue X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Fix the vector mapping with queue by changing the recircle when exceeds RX_VEC_START + nb_msix; Fixes: d6bde6b5eae9 ("net/avf: enable Rx interrupt") Signed-off-by: Jingjing Wu Tested-by: Xie,WeiX < weix.xie@intel.com> --- drivers/net/iavf/iavf_ethdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c index 06395f852b..b169b19975 100644 --- a/drivers/net/iavf/iavf_ethdev.c +++ b/drivers/net/iavf/iavf_ethdev.c @@ -570,7 +570,7 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev *dev, /* If Rx interrupt is reuquired, and we can use * multi interrupts, then the vec is from 1 */ - vf->nb_msix = RTE_MIN(vf->vf_res->max_vectors, + vf->nb_msix = RTE_MIN(vf->vf_res->max_vectors - 1, intr_handle->nb_efd); vf->msix_base = IAVF_RX_VEC_START; vec = IAVF_RX_VEC_START; @@ -578,7 +578,7 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev *dev, qv_map[i].queue_id = i; qv_map[i].vector_id = vec; intr_handle->intr_vec[i] = vec++; - if (vec >= vf->nb_msix) + if (vec >= vf->nb_msix + IAVF_RX_VEC_START) vec = IAVF_RX_VEC_START; } vf->qv_map = qv_map;