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;