From patchwork Thu Jan 14 06:25:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chenbo Xia X-Patchwork-Id: 86514 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 16D6DA0A02; Thu, 14 Jan 2021 07:31:07 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E5A3A140E4D; Thu, 14 Jan 2021 07:30:27 +0100 (CET) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mails.dpdk.org (Postfix) with ESMTP id 2B9FE140E4B for ; Thu, 14 Jan 2021 07:30:25 +0100 (CET) IronPort-SDR: 82L58yDrMd+0EAY8ceuLlG9jTZxsUZoiN2kXIsgK+qRK6Ngw/d9sCb0DOXC8W/OliiFvGrdnGb c9BLQHmni36A== X-IronPort-AV: E=McAfee;i="6000,8403,9863"; a="178407172" X-IronPort-AV: E=Sophos;i="5.79,346,1602572400"; d="scan'208";a="178407172" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jan 2021 22:30:24 -0800 IronPort-SDR: rToLVGwONUQ299Uwy7+8NZXcPCHqaNgFgY5deYlKJ0IUNr39NLYSBujMOuTztCF0YRrdk4pRM3 P4Hqd5De9/WA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,346,1602572400"; d="scan'208";a="400799465" Received: from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123]) by fmsmga002.fm.intel.com with ESMTP; 13 Jan 2021 22:30:22 -0800 From: Chenbo Xia To: dev@dpdk.org, thomas@monjalon.net, david.marchand@redhat.com Cc: stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com, miao.li@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com Date: Thu, 14 Jan 2021 14:25:10 +0800 Message-Id: <20210114062512.45462-7-chenbo.xia@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210114062512.45462-1-chenbo.xia@intel.com> References: <20201219062806.56477-1-chenbo.xia@intel.com> <20210114062512.45462-1-chenbo.xia@intel.com> Subject: [dpdk-dev] [PATCH v3 6/8] emu/iavf: add emudev operations to fit in emudev framework 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 emudev operations to make emulated iavf fit into rte_emudev framework. Lifecycle related and device resource related operations are both implemented. Signed-off-by: Chenbo Xia Signed-off-by: Xiuchun Lu --- drivers/emu/iavf/iavf_emu.c | 229 ++++++++++++++++++++++++++++++++ drivers/emu/iavf/rte_iavf_emu.h | 59 ++++++++ 2 files changed, 288 insertions(+) diff --git a/drivers/emu/iavf/iavf_emu.c b/drivers/emu/iavf/iavf_emu.c index 7506849e42..cc56ec1c4b 100644 --- a/drivers/emu/iavf/iavf_emu.c +++ b/drivers/emu/iavf/iavf_emu.c @@ -2,7 +2,75 @@ * Copyright(c) 2020 Intel Corporation */ +#include +#include +#include + +#include +#include + #include "iavf_vfio_user.h" +#include + +static int +iavf_emu_dev_start(struct rte_emudev *dev) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + if (iavf->ops != NULL && iavf->ops->device_start != NULL) + iavf->ops->device_start(dev); + + return 0; +} + +static void +iavf_emu_dev_stop(struct rte_emudev *dev) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + if (iavf->ops != NULL && iavf->ops->device_stop != NULL) + iavf->ops->device_stop(dev); +} + +static int +iavf_emu_dev_configure(struct rte_emudev *dev, + struct rte_emudev_info *dev_conf) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + struct rte_iavf_emu_config *conf = + (struct rte_iavf_emu_config *)dev_conf->dev_priv; + + if (!dev_conf->dev_priv) + return -EINVAL; + + /* Currently emulated iavf does not support max_qp_num + * and region num configuration + */ + if (dev->dev_info.max_qp_num != dev_conf->max_qp_num || + dev->dev_info.region_num != dev_conf->region_num) { + EMU_IAVF_LOG(ERR, + "Configure max_qp_num/region num not supported\n"); + return -ENOTSUP; + } + + if (conf->qp_num > RTE_MAX_QUEUES_PER_PORT || + conf->qp_num > RTE_IAVF_EMU_MAX_QP_NUM) { + EMU_IAVF_LOG(ERR, "Queue pair num exceeds max\n"); + return -EINVAL; + } + + /* For now, we don't support device configure when data + * path driver is attached + */ + if (dev->backend_priv) { + EMU_IAVF_LOG(ERR, "Configure failed because of " + "data path attached\n"); + return -EPERM; + } + + iavf->max_be_lanqp = conf->qp_num; + return 0; +} static int iavf_emu_dev_close(struct rte_emudev *dev) @@ -27,6 +95,167 @@ iavf_emu_dev_close(struct rte_emudev *dev) return 0; } +static int +iavf_emu_get_dev_info(struct rte_emudev *dev, + rte_emudev_obj_t info) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + struct rte_iavf_emu_config *conf = (struct rte_iavf_emu_config *)info; + + if (!info) + return -EINVAL; + + conf->qp_num = iavf->max_be_lanqp; + return 0; +} + +static int +iavf_emu_get_mem_table(struct rte_emudev *dev, + rte_emudev_mem_table_t *tb) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + *tb = iavf->mem; + + return 0; +} + +static int +iavf_emu_get_queue_info(struct rte_emudev *dev, uint32_t queue, + struct rte_emudev_q_info *info) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + if (queue < RTE_IAVF_EMU_ADMINQ_NUM) { + struct iavf_emu_adminQ *adq = &iavf->adq[queue]; + uint64_t base, size; + + if (adq->ring_addr_lo == NULL || + adq->ring_addr_hi == NULL || + adq->ring_sz == NULL) + return -1; + base = RTE_IAVF_EMU_32_TO_64(*adq->ring_addr_hi, + *adq->ring_addr_lo); + size = *adq->ring_sz; + info->base = base; + info->size = size; + info->doorbell_id = queue; + /* RX AdminQ should have IRQ vector 0 */ + info->irq_vector = queue - 1; + } else { + info->base = 0; + info->size = 0; + info->doorbell_id = queue; + info->irq_vector = -1; + } + + return 0; +} + +static int +iavf_emu_get_irq_info(struct rte_emudev *dev, uint32_t vector, + struct rte_emudev_irq_info *info) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + struct iavf_emu_intr *intr = iavf->intr; + struct iavf_emu_intr_info *intr_info = &intr->info[vector]; + + if (vector >= intr->intr_num) + return -EINVAL; + + info->eventfd = intr_info->fd; + info->enable = intr_info->enable; + info->vector = vector; + + return 0; +} + +static int +iavf_emu_get_db_info(struct rte_emudev *dev, uint32_t doorbell, + struct rte_emudev_db_info *info) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + if (doorbell < RTE_IAVF_EMU_ADMINQ_NUM) { + struct iavf_emu_adminQ *adq = &iavf->adq[doorbell]; + + info->data.mem.base = (uint64_t)adq->doorbell; + info->data.mem.size = adq->db_size; + } else { + struct iavf_emu_lanQ *lanq = + &iavf->lanq[doorbell - RTE_IAVF_EMU_ADMINQ_NUM]; + + info->data.mem.base = (uint64_t)lanq->doorbell; + info->data.mem.size = lanq->db_size; + } + + info->flag |= RTE_EMUDEV_DB_MEM; + info->id = doorbell; + + return 0; +} + +static int +iavf_emu_subs_ev(struct rte_emudev *dev, + rte_emudev_event_chnl_t ev_chnl) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + iavf->ops = (struct rte_iavf_emu_notify_ops *)ev_chnl; + + return 0; +} + +static int +iavf_emu_unsubs_ev(struct rte_emudev *dev, + rte_emudev_event_chnl_t ev_chnl) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + + if ((struct rte_iavf_emu_notify_ops *)ev_chnl == iavf->ops) { + iavf->ops = NULL; + return 0; + } + + return -EINVAL; +} + +static int +iavf_emu_get_attr(struct rte_emudev *dev, const char *attr_name, + rte_emudev_attr_t attr) +{ + struct iavf_emudev *iavf = (struct iavf_emudev *)dev->priv_data; + struct rte_vfio_user_reg_info *info; + int ret = 0; + + info = &iavf->vfio->reg->reg_info[0]; + + if (!strcmp(attr_name, RTE_IAVF_EMU_ATTR_ASQ_HEAD)) + *(uint64_t *)attr = (uint64_t)(uintptr_t)info->base + + IAVF_VF_ATQH1; + else if (!strcmp(attr_name, RTE_IAVF_EMU_ATTR_ARQ_HEAD)) + *(uint64_t *)attr = (uint64_t)(uintptr_t)info->base + + IAVF_VF_ARQH1; + else if (!strcmp(attr_name, RTE_IAVF_EMU_ATTR_RESET)) + *(uint64_t *)attr = (uint64_t)(uintptr_t)info->base + + IAVF_VFGEN_RSTAT; + else + ret = -EINVAL; + + return ret; +} + struct rte_emudev_ops emu_iavf_ops = { + .dev_start = iavf_emu_dev_start, + .dev_stop = iavf_emu_dev_stop, + .dev_configure = iavf_emu_dev_configure, .dev_close = iavf_emu_dev_close, + .dev_info_get = iavf_emu_get_dev_info, + .get_mem_table = iavf_emu_get_mem_table, + .get_queue_info = iavf_emu_get_queue_info, + .get_irq_info = iavf_emu_get_irq_info, + .get_db_info = iavf_emu_get_db_info, + .subscribe_event = iavf_emu_subs_ev, + .unsubscribe_event = iavf_emu_unsubs_ev, + .get_attr = iavf_emu_get_attr, }; diff --git a/drivers/emu/iavf/rte_iavf_emu.h b/drivers/emu/iavf/rte_iavf_emu.h index 6de0989f0b..2abcec97d4 100644 --- a/drivers/emu/iavf/rte_iavf_emu.h +++ b/drivers/emu/iavf/rte_iavf_emu.h @@ -6,13 +6,24 @@ #define _IAVF_EMU_H #include +#include +#include +#include +#include +#include #include #define RTE_IAVF_EMUDEV_TYPE "iavf" +#define RTE_IAVF_EMU_ATTR_ASQ_HEAD "ASQ_H" +#define RTE_IAVF_EMU_ATTR_ARQ_HEAD "ARQ_H" +#define RTE_IAVF_EMU_ATTR_RESET "RESET" +#define RTE_IAVF_EMU_RESET_IN_PROGRESS 0x00 +#define RTE_IAVF_EMU_RESET_COMPLETED 0x01 #define RTE_IAVF_EMU_MAX_MEM_REGIONS 256 #define RTE_IAVF_EMU_MAX_QP_NUM 256 #define RTE_IAVF_EMU_MAX_INTR 32 +#define RTE_IAVF_EMU_32_TO_64(hi, lo) ((((uint64_t)(hi)) << 32) + (lo)) enum { RTE_IAVF_EMU_ADMINQ_TXQ = 0, @@ -26,6 +37,11 @@ enum { RTE_IAVF_EMU_MAPPABLE_REG_NUM = 2, }; +struct rte_iavf_emu_config { + /* Maximum queue pair number that data path driver can use */ + uint32_t qp_num; +}; + struct rte_iavf_emu_mem_reg { uint64_t guest_phys_addr; uint64_t host_user_addr; @@ -40,6 +56,49 @@ struct rte_iavf_emu_mem { struct rte_iavf_emu_mem_reg regions[RTE_IAVF_EMU_MAX_MEM_REGIONS]; }; +/** + * Helper function for data path driver to translate address + * of one region + * + * @param mem + * A pointer to DMA memory table + * @param g_addr + * Guest I/O virtual base address of the region + * @param[in/out] len + * The length of region + * @return + * - >0: Success, process virtual address returned + * - 0: Failure on translation + */ +__rte_experimental +__rte_always_inline uint64_t +rte_iavf_emu_get_dma_vaddr(struct rte_iavf_emu_mem *mem, + uint64_t g_addr, uint64_t *len) +{ + struct rte_iavf_emu_mem_reg *reg; + uint32_t i; + + for (i = 0; i < mem->region_num; i++) { + reg = &mem->regions[i]; + + if (g_addr >= reg->guest_phys_addr && + g_addr < reg->guest_phys_addr + reg->size) { + + if (unlikely(*len > reg->guest_phys_addr + + reg->size - g_addr)) + *len = reg->guest_phys_addr + + reg->size - g_addr; + + return g_addr - reg->guest_phys_addr + + reg->host_user_addr; + } + } + + *len = 0; + + return 0; +} + struct rte_iavf_emu_notify_ops { /* Device is ready */ int (*device_ready)(struct rte_emudev *dev);