X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ffailsafe%2Ffailsafe_intr.c;h=602c04033c18c7ec5de95c1f33c7fa36f40e1433;hb=f971b7d3013d53a5d911b8c5cf51ab55946253b0;hp=b0eacdcfb6acb87bc44be5077d1703c6989fd8b7;hpb=f234e5bd996dea4ad86e0f7ad48e749e72bdbf42;p=dpdk.git diff --git a/drivers/net/failsafe/failsafe_intr.c b/drivers/net/failsafe/failsafe_intr.c index b0eacdcfb6..602c04033c 100644 --- a/drivers/net/failsafe/failsafe_intr.c +++ b/drivers/net/failsafe/failsafe_intr.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018 Mellanox Technologies, Ltd. + * Copyright 2018 Mellanox Technologies, Ltd */ /** @@ -12,6 +12,13 @@ #endif #include +#include +#include +#include +#include +#include +#include + #include "failsafe_private.h" #define NUM_RX_PROXIES (FAILSAFE_MAX_ETHPORTS * RTE_MAX_RXTX_INTR_VEC_ID) @@ -36,6 +43,162 @@ fs_epoll_create1(int flags) #endif } +/** + * Install failsafe Rx event proxy service. + * The Rx event proxy is the service that listens to Rx events from the + * subdevices and triggers failsafe Rx events accordingly. + * + * @param priv + * Pointer to failsafe private structure. + * @return + * 0 on success, negative errno value otherwise. + */ +static int +fs_rx_event_proxy_routine(void *data) +{ + struct fs_priv *priv; + struct rxq *rxq; + struct rte_epoll_event *events; + uint64_t u64; + int i, n; + int rc = 0; + + u64 = 1; + priv = data; + events = priv->rxp.evec; + n = rte_epoll_wait(priv->rxp.efd, events, NUM_RX_PROXIES, -1); + for (i = 0; i < n; i++) { + rxq = events[i].epdata.data; + if (rxq->enable_events && rxq->event_fd != -1) { + if (write(rxq->event_fd, &u64, sizeof(u64)) != + sizeof(u64)) { + ERROR("Failed to proxy Rx event to socket %d", + rxq->event_fd); + rc = -EIO; + } + } + } + return rc; +} + +/** + * Uninstall failsafe Rx event proxy service. + * + * @param priv + * Pointer to failsafe private structure. + */ +static void +fs_rx_event_proxy_service_uninstall(struct fs_priv *priv) +{ + /* Unregister the event service. */ + switch (priv->rxp.sstate) { + case SS_RUNNING: + rte_service_map_lcore_set(priv->rxp.sid, priv->rxp.scid, 0); + /* fall through */ + case SS_READY: + rte_service_runstate_set(priv->rxp.sid, 0); + rte_service_set_stats_enable(priv->rxp.sid, 0); + rte_service_component_runstate_set(priv->rxp.sid, 0); + /* fall through */ + case SS_REGISTERED: + rte_service_component_unregister(priv->rxp.sid); + /* fall through */ + default: + break; + } +} + +/** + * Install the failsafe Rx event proxy service. + * + * @param priv + * Pointer to failsafe private structure. + * @return + * 0 on success, negative errno value otherwise. + */ +static int +fs_rx_event_proxy_service_install(struct fs_priv *priv) +{ + struct rte_service_spec service; + int32_t num_service_cores; + int ret = 0; + + num_service_cores = rte_service_lcore_count(); + if (num_service_cores <= 0) { + ERROR("Failed to install Rx interrupts, " + "no service core found"); + return -ENOTSUP; + } + /* prepare service info */ + memset(&service, 0, sizeof(struct rte_service_spec)); + snprintf(service.name, sizeof(service.name), "%s_Rx_service", + priv->data->name); + service.socket_id = priv->data->numa_node; + service.callback = fs_rx_event_proxy_routine; + service.callback_userdata = priv; + + if (priv->rxp.sstate == SS_NO_SERVICE) { + uint32_t service_core_list[num_service_cores]; + + /* get a service core to work with */ + ret = rte_service_lcore_list(service_core_list, + num_service_cores); + if (ret <= 0) { + ERROR("Failed to install Rx interrupts, " + "service core list empty or corrupted"); + return -ENOTSUP; + } + priv->rxp.scid = service_core_list[0]; + ret = rte_service_lcore_add(priv->rxp.scid); + if (ret && ret != -EALREADY) { + ERROR("Failed adding service core"); + return ret; + } + /* service core may be in "stopped" state, start it */ + ret = rte_service_lcore_start(priv->rxp.scid); + if (ret && (ret != -EALREADY)) { + ERROR("Failed to install Rx interrupts, " + "service core not started"); + return ret; + } + /* register our service */ + int32_t ret = rte_service_component_register(&service, + &priv->rxp.sid); + if (ret) { + ERROR("service register() failed"); + return -ENOEXEC; + } + priv->rxp.sstate = SS_REGISTERED; + /* run the service */ + ret = rte_service_component_runstate_set(priv->rxp.sid, 1); + if (ret < 0) { + ERROR("Failed Setting component runstate\n"); + return ret; + } + ret = rte_service_set_stats_enable(priv->rxp.sid, 1); + if (ret < 0) { + ERROR("Failed enabling stats\n"); + return ret; + } + ret = rte_service_runstate_set(priv->rxp.sid, 1); + if (ret < 0) { + ERROR("Failed to run service\n"); + return ret; + } + priv->rxp.sstate = SS_READY; + /* map the service with the service core */ + ret = rte_service_map_lcore_set(priv->rxp.sid, + priv->rxp.scid, 1); + if (ret) { + ERROR("Failed to install Rx interrupts, " + "could not map service core"); + return ret; + } + priv->rxp.sstate = SS_RUNNING; + } + return 0; +} + /** * Install failsafe Rx event proxy subsystem. * This is the way the failsafe PMD generates Rx events on behalf of its @@ -69,6 +232,9 @@ fs_rx_event_proxy_install(struct fs_priv *priv) rc = -ENOMEM; goto error; } + rc = fs_rx_event_proxy_service_install(priv); + if (rc < 0) + goto error; return 0; error: if (priv->rxp.efd >= 0) { @@ -107,14 +273,14 @@ failsafe_eth_rx_intr_ctl_subdevice(struct sub_device *sdev, int op) int rc; int ret = 0; + fsdev = fs_dev(sdev); if (sdev == NULL || (ETH(sdev) == NULL) || - sdev->fs_dev == NULL || (PRIV(sdev->fs_dev) == NULL)) { + fsdev == NULL || (PRIV(fsdev) == NULL)) { ERROR("Called with invalid arguments"); return -EINVAL; } dev = ETH(sdev); - fsdev = sdev->fs_dev; - epfd = PRIV(sdev->fs_dev)->rxp.efd; + epfd = PRIV(fsdev)->rxp.efd; pid = PORT_ID(sdev); if (epfd <= 0) { @@ -163,7 +329,7 @@ int failsafe_rx_intr_install_subdevice(struct sub_device *sdev) const struct rte_intr_conf *const intr_conf = Ð(sdev)->data->dev_conf.intr_conf; - fsdev = sdev->fs_dev; + fsdev = fs_dev(sdev); rxq = (struct rxq **)fsdev->data->rx_queues; if (intr_conf->rxq == 0) return 0; @@ -201,11 +367,11 @@ void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev) struct rte_eth_dev *fsdev; struct rxq *fsrxq; - fsdev = sdev->fs_dev; + fsdev = fs_dev(sdev); 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) + if (fsrxq != NULL && fsrxq->enable_events) rte_eth_dev_rx_intr_disable(PORT_ID(sdev), qid); } @@ -222,11 +388,12 @@ void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev) static void fs_rx_event_proxy_uninstall(struct fs_priv *priv) { + fs_rx_event_proxy_service_uninstall(priv); if (priv->rxp.evec != NULL) { free(priv->rxp.evec); priv->rxp.evec = NULL; } - if (priv->rxp.efd > 0) { + if (priv->rxp.efd >= 0) { close(priv->rxp.efd); priv->rxp.efd = -1; } @@ -269,7 +436,7 @@ fs_rx_intr_vec_install(struct fs_priv *priv) unsigned int count; struct rte_intr_handle *intr_handle; - rxqs_n = priv->dev->data->nb_rx_queues; + rxqs_n = priv->data->nb_rx_queues; n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID); count = 0; intr_handle = &priv->intr_handle; @@ -284,7 +451,7 @@ fs_rx_intr_vec_install(struct fs_priv *priv) return -rte_errno; } for (i = 0; i < n; i++) { - struct rxq *rxq = priv->dev->data->rx_queues[i]; + struct rxq *rxq = priv->data->rx_queues[i]; /* Skip queues that cannot request interrupts. */ if (rxq == NULL || rxq->event_fd < 0) { @@ -353,9 +520,9 @@ failsafe_rx_intr_install(struct rte_eth_dev *dev) { struct fs_priv *priv = PRIV(dev); const struct rte_intr_conf *const intr_conf = - &priv->dev->data->dev_conf.intr_conf; + &priv->data->dev_conf.intr_conf; - if (intr_conf->rxq == 0) + if (intr_conf->rxq == 0 || dev->intr_handle != NULL) return 0; if (fs_rx_intr_vec_install(priv) < 0) return -rte_errno;