From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (xvm-189-124.dc0.ghst.net [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6DDE0A09FF; Thu, 7 Jan 2021 08:59:35 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5447D140EC8; Thu, 7 Jan 2021 08:59:35 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id 9D3BA140EB7 for ; Thu, 7 Jan 2021 08:59:33 +0100 (CET) IronPort-SDR: BgSDKbQi+wkBxc91/woJXZ4Z82Mev4+YZlQ9Nbz+dhGv7Omo6bFhT7XZpDl3W1Ccv8q0Jf6x96 xRRoDVg7gmaQ== X-IronPort-AV: E=McAfee;i="6000,8403,9856"; a="165087540" X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="165087540" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Jan 2021 23:59:22 -0800 IronPort-SDR: S9vrgFbljjKhf9OUjfOCODmtdLZPFwlRLjmErosduaQs22yhszRLEhwcQqFgozui7Zci0A9pgP SVa5jPHvNAmg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.79,329,1602572400"; d="scan'208";a="351171619" Received: from dpdk-wujingji.sh.intel.com ([10.67.119.101]) by fmsmga008.fm.intel.com with ESMTP; 06 Jan 2021 23:59:17 -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 15:45:30 +0800 Message-Id: <20210107074533.15465-2-jingjing.wu@intel.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20210107074533.15465-1-jingjing.wu@intel.com> References: <20201219143816.64174-1-jingjing.wu@intel.com> <20210107074533.15465-1-jingjing.wu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH v2 1/4] 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' -- 2.21.1