From mboxrd@z Thu Jan 1 00:00:00 1970 From: Moti Haimovsky Subject: [PATCH v8 2/3] net/failsafe: slaves Rx interrupts registration Date: Thu, 25 Jan 2018 18:19:31 +0200 Message-ID: <1516897172-81448-3-git-send-email-motih@mellanox.com> References: <1516867635-67104-4-git-send-email-motih@mellanox.com> <1516897172-81448-1-git-send-email-motih@mellanox.com> Mime-Version: 1.0 Content-Type: text/plain Cc: dev@dpdk.org, Moti Haimovsky To: gaetan.rivet@6wind.com, ferruh.yigit@intel.com Return-path: Received: from EUR01-VE1-obe.outbound.protection.outlook.com (mail-ve1eur01on0071.outbound.protection.outlook.com [104.47.1.71]) by dpdk.org (Postfix) with ESMTP id CF2DE1B1EE for ; Thu, 25 Jan 2018 17:20:06 +0100 (CET) In-Reply-To: <1516897172-81448-1-git-send-email-motih@mellanox.com> 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 commit adds the following functionality to failsafe PMD: * Register and unregister slaves Rx interrupts. * Enable and Disable slaves Rx interrupts. The interrupts events generated by the slaves are not handled in this commit. Signed-off-by: Moti Haimovsky --- V8: Modifications according to inputs from Ferruh Yigit in reply to 1516867635-67104-3-git-send-email-motih@mellanox.com V7: Fixed compilation errors in FreeBSD. See 1516810328-39383-3-git-send-email-motih@mellanox.com V6: Added a wrapper around epoll_create1 since it is not supported in FreeBSD. See: 1516193643-130838-1-git-send-email-motih@mellanox.com V5: Initial version of this patch in accordance to inputs from Gaetan Rivet in reply to 1516354344-13495-2-git-send-email-motih@mellanox.com --- drivers/net/failsafe/Makefile | 5 + drivers/net/failsafe/failsafe_ether.c | 1 + drivers/net/failsafe/failsafe_intr.c | 234 +++++++++++++++++++++++++++++++- drivers/net/failsafe/failsafe_ops.c | 36 ++++- drivers/net/failsafe/failsafe_private.h | 16 +++ 5 files changed, 289 insertions(+), 3 deletions(-) diff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile index 91a734b..9bce1f7 100644 --- a/drivers/net/failsafe/Makefile +++ b/drivers/net/failsafe/Makefile @@ -47,6 +47,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_intr.c +ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) +CFLAGS += -DLINUX +else +CFLAGS += -DBSD +endif # No exported include files diff --git a/drivers/net/failsafe/failsafe_ether.c b/drivers/net/failsafe/failsafe_ether.c index 8a4cacf..0f1630e 100644 --- a/drivers/net/failsafe/failsafe_ether.c +++ b/drivers/net/failsafe/failsafe_ether.c @@ -283,6 +283,7 @@ return; switch (sdev->state) { case DEV_STARTED: + failsafe_rx_intr_uninstall_subdevice(sdev); rte_eth_dev_stop(PORT_ID(sdev)); sdev->state = DEV_ACTIVE; /* fallthrough */ diff --git a/drivers/net/failsafe/failsafe_intr.c b/drivers/net/failsafe/failsafe_intr.c index 8829ca4..b0eacdc 100644 --- a/drivers/net/failsafe/failsafe_intr.c +++ b/drivers/net/failsafe/failsafe_intr.c @@ -7,10 +7,231 @@ * Interrupts handling for failsafe driver. */ +#if defined(LINUX) +#include +#endif #include #include "failsafe_private.h" +#define NUM_RX_PROXIES (FAILSAFE_MAX_ETHPORTS * RTE_MAX_RXTX_INTR_VEC_ID) + + +/** + * Open an epoll file descriptor. + * + * @param flags + * Flags for defining epoll behavior. + * @return + * 0 on success, negative errno value otherwise. + */ +static int +fs_epoll_create1(int flags) +{ +#if defined(LINUX) + return epoll_create1(flags); +#elif defined(BSD) + RTE_SET_USED(flags); + return -ENOTSUP; +#endif +} + +/** + * Install failsafe Rx event proxy subsystem. + * This is the way the failsafe PMD generates Rx events on behalf of its + * subdevices. + * + * @param priv + * Pointer to failsafe private structure. + * @return + * 0 on success, negative errno value otherwise and rte_errno is set. + */ +static int +fs_rx_event_proxy_install(struct fs_priv *priv) +{ + int rc = 0; + + /* + * Create the epoll fd and event vector for the proxy service to + * wait on for Rx events generated by the subdevices. + */ + priv->rxp.efd = fs_epoll_create1(0); + if (priv->rxp.efd < 0) { + rte_errno = errno; + ERROR("Failed to create epoll," + " Rx interrupts will not be supported"); + return -rte_errno; + } + priv->rxp.evec = calloc(NUM_RX_PROXIES, sizeof(*priv->rxp.evec)); + if (priv->rxp.evec == NULL) { + ERROR("Failed to allocate memory for event vectors," + " Rx interrupts will not be supported"); + rc = -ENOMEM; + goto error; + } + return 0; +error: + if (priv->rxp.efd >= 0) { + close(priv->rxp.efd); + priv->rxp.efd = -1; + } + if (priv->rxp.evec != NULL) { + free(priv->rxp.evec); + priv->rxp.evec = NULL; + } + rte_errno = -rc; + return rc; +} + +/** + * RX Interrupt control per subdevice. + * + * @param sdev + * Pointer to sub-device structure. + * @param op + * The operation be performed for the vector. + * Operation type of {RTE_INTR_EVENT_ADD, RTE_INTR_EVENT_DEL}. + * @return + * - On success, zero. + * - On failure, a negative value. + */ +static int +failsafe_eth_rx_intr_ctl_subdevice(struct sub_device *sdev, int op) +{ + struct rte_eth_dev *dev; + struct rte_eth_dev *fsdev; + int epfd; + uint16_t pid; + uint16_t qid; + struct rxq *fsrxq; + int rc; + int ret = 0; + + if (sdev == NULL || (ETH(sdev) == NULL) || + sdev->fs_dev == NULL || (PRIV(sdev->fs_dev) == NULL)) { + ERROR("Called with invalid arguments"); + return -EINVAL; + } + dev = ETH(sdev); + fsdev = sdev->fs_dev; + epfd = PRIV(sdev->fs_dev)->rxp.efd; + pid = PORT_ID(sdev); + + if (epfd <= 0) { + if (op == RTE_INTR_EVENT_ADD) { + ERROR("Proxy events are not initialized"); + return -EBADF; + } else { + return 0; + } + } + if (dev->data->nb_rx_queues > fsdev->data->nb_rx_queues) { + ERROR("subdevice has too many queues," + " Interrupts will not be enabled"); + return -E2BIG; + } + for (qid = 0; qid < dev->data->nb_rx_queues; qid++) { + fsrxq = fsdev->data->rx_queues[qid]; + rc = rte_eth_dev_rx_intr_ctl_q(pid, qid, epfd, + op, (void *)fsrxq); + if (rc) { + ERROR("rte_eth_dev_rx_intr_ctl_q failed for " + "port %d queue %d, epfd %d, error %d", + pid, qid, epfd, rc); + ret = rc; + } + } + return ret; +} + +/** + * Install Rx interrupts subsystem for a subdevice. + * This is a support for dynamically adding subdevices. + * + * @param sdev + * Pointer to subdevice structure. + * + * @return + * 0 on success, negative errno value otherwise and rte_errno is set. + */ +int failsafe_rx_intr_install_subdevice(struct sub_device *sdev) +{ + int rc; + int qid; + struct rte_eth_dev *fsdev; + struct rxq **rxq; + const struct rte_intr_conf *const intr_conf = + Ð(sdev)->data->dev_conf.intr_conf; + + fsdev = sdev->fs_dev; + rxq = (struct rxq **)fsdev->data->rx_queues; + if (intr_conf->rxq == 0) + return 0; + rc = failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_ADD); + if (rc) + return rc; + /* enable interrupts on already-enabled queues */ + for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) { + if (rxq[qid]->enable_events) { + int ret = rte_eth_dev_rx_intr_enable(PORT_ID(sdev), + qid); + if (ret && (ret != -ENOTSUP)) { + ERROR("Failed to enable interrupts on " + "port %d queue %d", PORT_ID(sdev), qid); + rc = ret; + } + } + } + return rc; +} + +/** + * Uninstall Rx interrupts subsystem for a subdevice. + * This is a support for dynamically removing subdevices. + * + * @param sdev + * Pointer to subdevice structure. + * + * @return + * 0 on success, negative errno value otherwise and rte_errno is set. + */ +void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev) +{ + int qid; + struct rte_eth_dev *fsdev; + struct rxq *fsrxq; + + fsdev = sdev->fs_dev; + for (qid = 0; qid < ETH(sdev)->data->nb_rx_queues; qid++) { + if (qid < fsdev->data->nb_rx_queues) { + fsrxq = fsdev->data->rx_queues[qid]; + if (fsrxq->enable_events) + rte_eth_dev_rx_intr_disable(PORT_ID(sdev), + qid); + } + } + failsafe_eth_rx_intr_ctl_subdevice(sdev, RTE_INTR_EVENT_DEL); +} + +/** + * Uninstall failsafe Rx event proxy. + * + * @param priv + * Pointer to failsafe private structure. + */ +static void +fs_rx_event_proxy_uninstall(struct fs_priv *priv) +{ + if (priv->rxp.evec != NULL) { + free(priv->rxp.evec); + priv->rxp.evec = NULL; + } + if (priv->rxp.efd > 0) { + close(priv->rxp.efd); + priv->rxp.efd = -1; + } +} + /** * Uninstall failsafe interrupt vector. * @@ -107,7 +328,14 @@ void failsafe_rx_intr_uninstall(struct rte_eth_dev *dev) { - fs_rx_intr_vec_uninstall(PRIV(dev)); + struct fs_priv *priv; + struct rte_intr_handle *intr_handle; + + priv = PRIV(dev); + intr_handle = &priv->intr_handle; + rte_intr_free_epoll_fd(intr_handle); + fs_rx_event_proxy_uninstall(priv); + fs_rx_intr_vec_uninstall(priv); dev->intr_handle = NULL; } @@ -131,6 +359,10 @@ return 0; if (fs_rx_intr_vec_install(priv) < 0) return -rte_errno; + if (fs_rx_event_proxy_install(priv) < 0) { + fs_rx_intr_vec_uninstall(priv); + return -rte_errno; + } dev->intr_handle = &priv->intr_handle; return 0; } diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c index 5cbc591..249baea 100644 --- a/drivers/net/failsafe/failsafe_ops.c +++ b/drivers/net/failsafe/failsafe_ops.c @@ -213,6 +213,13 @@ continue; return ret; } + ret = failsafe_rx_intr_install_subdevice(sdev); + if (ret) { + if (!fs_err(sdev, ret)) + continue; + rte_eth_dev_stop(PORT_ID(sdev)); + return ret; + } sdev->state = DEV_STARTED; } if (PRIV(dev)->state < DEV_STARTED) @@ -230,6 +237,7 @@ PRIV(dev)->state = DEV_STARTED - 1; FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_STARTED) { rte_eth_dev_stop(PORT_ID(sdev)); + failsafe_rx_intr_uninstall_subdevice(sdev); sdev->state = DEV_STARTED - 1; } failsafe_rx_intr_uninstall(dev); @@ -412,6 +420,10 @@ fs_rx_intr_enable(struct rte_eth_dev *dev, uint16_t idx) { struct rxq *rxq; + struct sub_device *sdev; + uint8_t i; + int ret; + int rc = 0; if (idx >= dev->data->nb_rx_queues) { rte_errno = EINVAL; @@ -423,14 +435,26 @@ return -rte_errno; } rxq->enable_events = 1; - return 0; + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + ret = rte_eth_dev_rx_intr_enable(PORT_ID(sdev), idx); + ret = fs_err(sdev, ret); + if (ret) + rc = ret; + } + if (rc) + rte_errno = -rc; + return rc; } static int fs_rx_intr_disable(struct rte_eth_dev *dev, uint16_t idx) { struct rxq *rxq; + struct sub_device *sdev; uint64_t u64; + uint8_t i; + int rc = 0; + int ret; if (idx >= dev->data->nb_rx_queues) { rte_errno = EINVAL; @@ -442,10 +466,18 @@ return -rte_errno; } rxq->enable_events = 0; + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + ret = rte_eth_dev_rx_intr_disable(PORT_ID(sdev), idx); + ret = fs_err(sdev, ret); + if (ret) + rc = ret; + } /* Clear pending events */ while (read(rxq->event_fd, &u64, sizeof(uint64_t)) > 0) ; - return 0; + if (rc) + rte_errno = -rc; + return rc; } static bool diff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h index 419e5e7..ff78b9f 100644 --- a/drivers/net/failsafe/failsafe_private.h +++ b/drivers/net/failsafe/failsafe_private.h @@ -63,6 +63,13 @@ /* TYPES */ +struct rx_proxy { + /* epoll file descriptor */ + int efd; + /* event vector to be used by epoll */ + struct rte_epoll_event *evec; +}; + struct rxq { struct fs_priv *priv; uint16_t qid; @@ -158,6 +165,13 @@ struct fs_priv { */ enum dev_state state; struct rte_eth_stats stats_accumulator; + /* + * Rx interrupts/events proxy. + * The PMD issues Rx events to the EAL on behalf of its subdevices, + * it does that by registering an event-fd for each of its queues with + * the EAL. + */ + struct rx_proxy rxp; unsigned int pending_alarm:1; /* An alarm is pending */ /* flow isolation state */ int flow_isolated:1; @@ -167,6 +181,8 @@ struct fs_priv { int failsafe_rx_intr_install(struct rte_eth_dev *dev); void failsafe_rx_intr_uninstall(struct rte_eth_dev *dev); +int failsafe_rx_intr_install_subdevice(struct sub_device *sdev); +void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev); /* MISC */ -- 1.8.3.1