diff options
author | Luca Boccassi <luca.boccassi@gmail.com> | 2018-02-19 11:16:57 +0000 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2018-02-19 11:17:28 +0000 |
commit | ca33590b6af032bff57d9cc70455660466a654b2 (patch) | |
tree | 0b68b090bd9b4a78a3614b62400b29279d76d553 /drivers/net/failsafe/failsafe_ops.c | |
parent | 169a9de21e263aa6599cdc2d87a45ae158d9f509 (diff) |
New upstream version 18.02upstream/18.02
Change-Id: I89ed24cb2a49b78fe5be6970b99dd46c1499fcc3
Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Diffstat (limited to 'drivers/net/failsafe/failsafe_ops.c')
-rw-r--r-- | drivers/net/failsafe/failsafe_ops.c | 422 |
1 files changed, 362 insertions, 60 deletions
diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c index e16a5903..057e435c 100644 --- a/drivers/net/failsafe/failsafe_ops.c +++ b/drivers/net/failsafe/failsafe_ops.c @@ -1,41 +1,15 @@ -/*- - * BSD LICENSE - * - * Copyright 2017 6WIND S.A. - * Copyright 2017 Mellanox. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of 6WIND S.A. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2017 6WIND S.A. + * Copyright 2017 Mellanox. */ +#include <stdbool.h> #include <stdint.h> +#include <unistd.h> #include <rte_debug.h> #include <rte_atomic.h> -#include <rte_ethdev.h> +#include <rte_ethdev_driver.h> #include <rte_malloc.h> #include <rte_flow.h> #include <rte_cycles.h> @@ -71,12 +45,43 @@ static struct rte_eth_dev_info default_infos = { */ .rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP | + DEV_RX_OFFLOAD_IPV4_CKSUM | + DEV_RX_OFFLOAD_UDP_CKSUM | + DEV_RX_OFFLOAD_TCP_CKSUM | + DEV_RX_OFFLOAD_TCP_LRO | DEV_RX_OFFLOAD_QINQ_STRIP | + DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | + DEV_RX_OFFLOAD_MACSEC_STRIP | + DEV_RX_OFFLOAD_HEADER_SPLIT | + DEV_RX_OFFLOAD_VLAN_FILTER | + DEV_RX_OFFLOAD_VLAN_EXTEND | + DEV_RX_OFFLOAD_JUMBO_FRAME | + DEV_RX_OFFLOAD_CRC_STRIP | + DEV_RX_OFFLOAD_SCATTER | + DEV_RX_OFFLOAD_TIMESTAMP | + DEV_RX_OFFLOAD_SECURITY, + .rx_queue_offload_capa = + DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM | - DEV_RX_OFFLOAD_TCP_LRO, - .tx_offload_capa = 0x0, + DEV_RX_OFFLOAD_TCP_LRO | + DEV_RX_OFFLOAD_QINQ_STRIP | + DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | + DEV_RX_OFFLOAD_MACSEC_STRIP | + DEV_RX_OFFLOAD_HEADER_SPLIT | + DEV_RX_OFFLOAD_VLAN_FILTER | + DEV_RX_OFFLOAD_VLAN_EXTEND | + DEV_RX_OFFLOAD_JUMBO_FRAME | + DEV_RX_OFFLOAD_CRC_STRIP | + DEV_RX_OFFLOAD_SCATTER | + DEV_RX_OFFLOAD_TIMESTAMP | + DEV_RX_OFFLOAD_SECURITY, + .tx_offload_capa = + DEV_TX_OFFLOAD_MULTI_SEGS | + DEV_TX_OFFLOAD_IPV4_CKSUM | + DEV_TX_OFFLOAD_UDP_CKSUM | + DEV_TX_OFFLOAD_TCP_CKSUM, .flow_type_rss_offloads = 0x0, }; @@ -84,15 +89,29 @@ static int fs_dev_configure(struct rte_eth_dev *dev) { struct sub_device *sdev; + uint64_t supp_tx_offloads; + uint64_t tx_offloads; uint8_t i; int ret; + fs_lock(dev, 0); + supp_tx_offloads = PRIV(dev)->infos.tx_offload_capa; + tx_offloads = dev->data->dev_conf.txmode.offloads; + if ((tx_offloads & supp_tx_offloads) != tx_offloads) { + rte_errno = ENOTSUP; + ERROR("Some Tx offloads are not supported, " + "requested 0x%" PRIx64 " supported 0x%" PRIx64, + tx_offloads, supp_tx_offloads); + fs_unlock(dev, 0); + return -rte_errno; + } FOREACH_SUBDEV(sdev, i, dev) { int rmv_interrupt = 0; int lsc_interrupt = 0; int lsc_enabled; - if (sdev->state != DEV_PROBED) + if (sdev->state != DEV_PROBED && + !(PRIV(dev)->alarm_lock == 0 && sdev->state == DEV_ACTIVE)) continue; rmv_interrupt = ETH(sdev)->data->dev_flags & @@ -115,13 +134,15 @@ fs_dev_configure(struct rte_eth_dev *dev) dev->data->dev_conf.intr_conf.lsc = 0; } DEBUG("Configuring sub-device %d", i); - sdev->remove = 0; ret = rte_eth_dev_configure(PORT_ID(sdev), dev->data->nb_rx_queues, dev->data->nb_tx_queues, &dev->data->dev_conf); if (ret) { + if (!fs_err(sdev, ret)) + continue; ERROR("Could not configure sub_device %d", i); + fs_unlock(dev, 0); return ret; } if (rmv_interrupt) { @@ -148,6 +169,7 @@ fs_dev_configure(struct rte_eth_dev *dev) } if (PRIV(dev)->state < DEV_ACTIVE) PRIV(dev)->state = DEV_ACTIVE; + fs_unlock(dev, 0); return 0; } @@ -158,18 +180,37 @@ fs_dev_start(struct rte_eth_dev *dev) uint8_t i; int ret; + fs_lock(dev, 0); + ret = failsafe_rx_intr_install(dev); + if (ret) { + fs_unlock(dev, 0); + return ret; + } FOREACH_SUBDEV(sdev, i, dev) { if (sdev->state != DEV_ACTIVE) continue; DEBUG("Starting sub_device %d", i); ret = rte_eth_dev_start(PORT_ID(sdev)); - if (ret) + if (ret) { + if (!fs_err(sdev, ret)) + continue; + fs_unlock(dev, 0); + return ret; + } + ret = failsafe_rx_intr_install_subdevice(sdev); + if (ret) { + if (!fs_err(sdev, ret)) + continue; + rte_eth_dev_stop(PORT_ID(sdev)); + fs_unlock(dev, 0); return ret; + } sdev->state = DEV_STARTED; } if (PRIV(dev)->state < DEV_STARTED) PRIV(dev)->state = DEV_STARTED; fs_switch_dev(dev, NULL); + fs_unlock(dev, 0); return 0; } @@ -179,11 +220,15 @@ fs_dev_stop(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); 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); + fs_unlock(dev, 0); } static int @@ -193,15 +238,18 @@ fs_dev_set_link_up(struct rte_eth_dev *dev) uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_set_link_up on sub_device %d", i); ret = rte_eth_dev_set_link_up(PORT_ID(sdev)); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_set_link_up failed for sub_device %d" " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -212,15 +260,18 @@ fs_dev_set_link_down(struct rte_eth_dev *dev) uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_set_link_down on sub_device %d", i); ret = rte_eth_dev_set_link_down(PORT_ID(sdev)); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_set_link_down failed for sub_device %d" " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -231,6 +282,7 @@ fs_dev_close(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); failsafe_hotplug_alarm_cancel(dev); if (PRIV(dev)->state == DEV_STARTED) dev->dev_ops->dev_stop(dev); @@ -241,6 +293,26 @@ fs_dev_close(struct rte_eth_dev *dev) sdev->state = DEV_ACTIVE - 1; } fs_dev_free_queues(dev); + fs_unlock(dev, 0); +} + +static bool +fs_rxq_offloads_valid(struct rte_eth_dev *dev, uint64_t offloads) +{ + uint64_t port_offloads; + uint64_t queue_supp_offloads; + uint64_t port_supp_offloads; + + port_offloads = dev->data->dev_conf.rxmode.offloads; + queue_supp_offloads = PRIV(dev)->infos.rx_queue_offload_capa; + port_supp_offloads = PRIV(dev)->infos.rx_offload_capa; + if ((offloads & (queue_supp_offloads | port_supp_offloads)) != + offloads) + return false; + /* Verify we have no conflict with port offloads */ + if ((port_offloads ^ offloads) & port_supp_offloads) + return false; + return true; } static void @@ -255,11 +327,15 @@ fs_rx_queue_release(void *queue) return; rxq = queue; dev = rxq->priv->dev; + fs_lock(dev, 0); + if (rxq->event_fd > 0) + close(rxq->event_fd); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) SUBOPS(sdev, rx_queue_release) (ETH(sdev)->data->rx_queues[rxq->qid]); dev->data->rx_queues[rxq->qid] = NULL; rte_free(rxq); + fs_unlock(dev, 0); } static int @@ -270,22 +346,48 @@ fs_rx_queue_setup(struct rte_eth_dev *dev, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool) { + /* + * FIXME: Add a proper interface in rte_eal_interrupts for + * allocating eventfd as an interrupt vector. + * For the time being, fake as if we are using MSIX interrupts, + * this will cause rte_intr_efd_enable to allocate an eventfd for us. + */ + struct rte_intr_handle intr_handle = { + .type = RTE_INTR_HANDLE_VFIO_MSIX, + .efds = { -1, }, + }; struct sub_device *sdev; struct rxq *rxq; uint8_t i; int ret; + fs_lock(dev, 0); rxq = dev->data->rx_queues[rx_queue_id]; if (rxq != NULL) { fs_rx_queue_release(rxq); dev->data->rx_queues[rx_queue_id] = NULL; } + /* Verify application offloads are valid for our port and queue. */ + if (fs_rxq_offloads_valid(dev, rx_conf->offloads) == false) { + rte_errno = ENOTSUP; + ERROR("Rx queue offloads 0x%" PRIx64 + " don't match port offloads 0x%" PRIx64 + " or supported offloads 0x%" PRIx64, + rx_conf->offloads, + dev->data->dev_conf.rxmode.offloads, + PRIV(dev)->infos.rx_offload_capa | + PRIV(dev)->infos.rx_queue_offload_capa); + fs_unlock(dev, 0); + return -rte_errno; + } rxq = rte_zmalloc(NULL, sizeof(*rxq) + sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail, RTE_CACHE_LINE_SIZE); - if (rxq == NULL) + if (rxq == NULL) { + fs_unlock(dev, 0); return -ENOMEM; + } FOREACH_SUBDEV(sdev, i, dev) rte_atomic64_init(&rxq->refcnt[i]); rxq->qid = rx_queue_id; @@ -294,23 +396,127 @@ fs_rx_queue_setup(struct rte_eth_dev *dev, rxq->info.conf = *rx_conf; rxq->info.nb_desc = nb_rx_desc; rxq->priv = PRIV(dev); + rxq->sdev = PRIV(dev)->subs; + ret = rte_intr_efd_enable(&intr_handle, 1); + if (ret < 0) { + fs_unlock(dev, 0); + return ret; + } + rxq->event_fd = intr_handle.efds[0]; dev->data->rx_queues[rx_queue_id] = rxq; FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { ret = rte_eth_rx_queue_setup(PORT_ID(sdev), rx_queue_id, nb_rx_desc, socket_id, rx_conf, mb_pool); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("RX queue setup failed for sub_device %d", i); goto free_rxq; } } + fs_unlock(dev, 0); return 0; free_rxq: fs_rx_queue_release(rxq); + fs_unlock(dev, 0); return ret; } +static int +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; + + fs_lock(dev, 0); + if (idx >= dev->data->nb_rx_queues) { + rc = -EINVAL; + goto unlock; + } + rxq = dev->data->rx_queues[idx]; + if (rxq == NULL || rxq->event_fd <= 0) { + rc = -EINVAL; + goto unlock; + } + /* Fail if proxy service is nor running. */ + if (PRIV(dev)->rxp.sstate != SS_RUNNING) { + ERROR("failsafe interrupt services are not running"); + rc = -EAGAIN; + goto unlock; + } + rxq->enable_events = 1; + 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; + } +unlock: + fs_unlock(dev, 0); + 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; + + fs_lock(dev, 0); + if (idx >= dev->data->nb_rx_queues) { + rc = -EINVAL; + goto unlock; + } + rxq = dev->data->rx_queues[idx]; + if (rxq == NULL || rxq->event_fd <= 0) { + rc = -EINVAL; + goto unlock; + } + 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) + ; +unlock: + fs_unlock(dev, 0); + if (rc) + rte_errno = -rc; + return rc; +} + +static bool +fs_txq_offloads_valid(struct rte_eth_dev *dev, uint64_t offloads) +{ + uint64_t port_offloads; + uint64_t queue_supp_offloads; + uint64_t port_supp_offloads; + + port_offloads = dev->data->dev_conf.txmode.offloads; + queue_supp_offloads = PRIV(dev)->infos.tx_queue_offload_capa; + port_supp_offloads = PRIV(dev)->infos.tx_offload_capa; + if ((offloads & (queue_supp_offloads | port_supp_offloads)) != + offloads) + return false; + /* Verify we have no conflict with port offloads */ + if ((port_offloads ^ offloads) & port_supp_offloads) + return false; + return true; +} + static void fs_tx_queue_release(void *queue) { @@ -323,11 +529,13 @@ fs_tx_queue_release(void *queue) return; txq = queue; dev = txq->priv->dev; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) SUBOPS(sdev, tx_queue_release) (ETH(sdev)->data->tx_queues[txq->qid]); dev->data->tx_queues[txq->qid] = NULL; rte_free(txq); + fs_unlock(dev, 0); } static int @@ -342,17 +550,38 @@ fs_tx_queue_setup(struct rte_eth_dev *dev, uint8_t i; int ret; + fs_lock(dev, 0); txq = dev->data->tx_queues[tx_queue_id]; if (txq != NULL) { fs_tx_queue_release(txq); dev->data->tx_queues[tx_queue_id] = NULL; } + /* + * Don't verify queue offloads for applications which + * use the old API. + */ + if (tx_conf != NULL && + (tx_conf->txq_flags & ETH_TXQ_FLAGS_IGNORE) && + fs_txq_offloads_valid(dev, tx_conf->offloads) == false) { + rte_errno = ENOTSUP; + ERROR("Tx queue offloads 0x%" PRIx64 + " don't match port offloads 0x%" PRIx64 + " or supported offloads 0x%" PRIx64, + tx_conf->offloads, + dev->data->dev_conf.txmode.offloads, + PRIV(dev)->infos.tx_offload_capa | + PRIV(dev)->infos.tx_queue_offload_capa); + fs_unlock(dev, 0); + return -rte_errno; + } txq = rte_zmalloc("ethdev TX queue", sizeof(*txq) + sizeof(rte_atomic64_t) * PRIV(dev)->subs_tail, RTE_CACHE_LINE_SIZE); - if (txq == NULL) + if (txq == NULL) { + fs_unlock(dev, 0); return -ENOMEM; + } FOREACH_SUBDEV(sdev, i, dev) rte_atomic64_init(&txq->refcnt[i]); txq->qid = tx_queue_id; @@ -366,14 +595,16 @@ fs_tx_queue_setup(struct rte_eth_dev *dev, tx_queue_id, nb_tx_desc, socket_id, tx_conf); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("TX queue setup failed for sub_device %d", i); goto free_txq; } } + fs_unlock(dev, 0); return 0; free_txq: fs_tx_queue_release(txq); + fs_unlock(dev, 0); return ret; } @@ -400,8 +631,10 @@ fs_promiscuous_enable(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) rte_eth_promiscuous_enable(PORT_ID(sdev)); + fs_unlock(dev, 0); } static void @@ -410,8 +643,10 @@ fs_promiscuous_disable(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) rte_eth_promiscuous_disable(PORT_ID(sdev)); + fs_unlock(dev, 0); } static void @@ -420,8 +655,10 @@ fs_allmulticast_enable(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) rte_eth_allmulticast_enable(PORT_ID(sdev)); + fs_unlock(dev, 0); } static void @@ -430,8 +667,10 @@ fs_allmulticast_disable(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) rte_eth_allmulticast_disable(PORT_ID(sdev)); + fs_unlock(dev, 0); } static int @@ -442,12 +681,15 @@ fs_link_update(struct rte_eth_dev *dev, uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling link_update on sub_device %d", i); ret = (SUBOPS(sdev, link_update))(ETH(sdev), wait_to_complete); - if (ret && ret != -1) { + if (ret && ret != -1 && sdev->remove == 0 && + rte_eth_dev_is_removed(PORT_ID(sdev)) == 0) { ERROR("Link update failed for sub_device %d with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } @@ -459,9 +701,11 @@ fs_link_update(struct rte_eth_dev *dev, l2 = Ð(TX_SUBDEV(dev))->data->dev_link; if (memcmp(l1, l2, sizeof(*l1))) { *l1 = *l2; + fs_unlock(dev, 0); return 0; } } + fs_unlock(dev, 0); return -1; } @@ -469,25 +713,35 @@ static int fs_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { + struct rte_eth_stats backup; struct sub_device *sdev; uint8_t i; int ret; + fs_lock(dev, 0); rte_memcpy(stats, &PRIV(dev)->stats_accumulator, sizeof(*stats)); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { struct rte_eth_stats *snapshot = &sdev->stats_snapshot.stats; uint64_t *timestamp = &sdev->stats_snapshot.timestamp; + rte_memcpy(&backup, snapshot, sizeof(backup)); ret = rte_eth_stats_get(PORT_ID(sdev), snapshot); if (ret) { + if (!fs_err(sdev, ret)) { + rte_memcpy(snapshot, &backup, sizeof(backup)); + goto inc; + } ERROR("Operation rte_eth_stats_get failed for sub_device %d with error %d", i, ret); *timestamp = 0; + fs_unlock(dev, 0); return ret; } *timestamp = rte_rdtsc(); +inc: failsafe_stats_increment(stats, snapshot); } + fs_unlock(dev, 0); return 0; } @@ -497,11 +751,13 @@ fs_stats_reset(struct rte_eth_dev *dev) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { rte_eth_stats_reset(PORT_ID(sdev)); memset(&sdev->stats_snapshot, 0, sizeof(struct rte_eth_stats)); } memset(&PRIV(dev)->stats_accumulator, 0, sizeof(struct rte_eth_stats)); + fs_unlock(dev, 0); } /** @@ -546,19 +802,26 @@ fs_dev_infos_get(struct rte_eth_dev *dev, rte_memcpy(&PRIV(dev)->infos, &default_infos, sizeof(default_infos)); } else { - uint32_t rx_offload_capa; + uint64_t rx_offload_capa; + uint64_t rxq_offload_capa; rx_offload_capa = default_infos.rx_offload_capa; + rxq_offload_capa = default_infos.rx_queue_offload_capa; FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) { rte_eth_dev_info_get(PORT_ID(sdev), &PRIV(dev)->infos); rx_offload_capa &= PRIV(dev)->infos.rx_offload_capa; + rxq_offload_capa &= + PRIV(dev)->infos.rx_queue_offload_capa; } sdev = TX_SUBDEV(dev); rte_eth_dev_info_get(PORT_ID(sdev), &PRIV(dev)->infos); PRIV(dev)->infos.rx_offload_capa = rx_offload_capa; + PRIV(dev)->infos.rx_queue_offload_capa = rxq_offload_capa; PRIV(dev)->infos.tx_offload_capa &= default_infos.tx_offload_capa; + PRIV(dev)->infos.tx_queue_offload_capa &= + default_infos.tx_queue_offload_capa; PRIV(dev)->infos.flow_type_rss_offloads &= default_infos.flow_type_rss_offloads; } @@ -570,14 +833,20 @@ fs_dev_supported_ptypes_get(struct rte_eth_dev *dev) { struct sub_device *sdev; struct rte_eth_dev *edev; + const uint32_t *ret; + fs_lock(dev, 0); sdev = TX_SUBDEV(dev); - if (sdev == NULL) - return NULL; + if (sdev == NULL) { + ret = NULL; + goto unlock; + } edev = ETH(sdev); /* ENOTSUP: counts as no supported ptypes */ - if (SUBOPS(sdev, dev_supported_ptypes_get) == NULL) - return NULL; + if (SUBOPS(sdev, dev_supported_ptypes_get) == NULL) { + ret = NULL; + goto unlock; + } /* * The API does not permit to do a clean AND of all ptypes, * It is also incomplete by design and we do not really care @@ -585,7 +854,10 @@ fs_dev_supported_ptypes_get(struct rte_eth_dev *dev) * We just return the ptypes of the device of highest * priority, usually the PREFERRED device. */ - return SUBOPS(sdev, dev_supported_ptypes_get)(edev); + ret = SUBOPS(sdev, dev_supported_ptypes_get)(edev); +unlock: + fs_unlock(dev, 0); + return ret; } static int @@ -595,15 +867,18 @@ fs_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_set_mtu on sub_device %d", i); ret = rte_eth_dev_set_mtu(PORT_ID(sdev), mtu); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_set_mtu failed for sub_device %d with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -614,15 +889,18 @@ fs_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_vlan_filter on sub_device %d", i); ret = rte_eth_dev_vlan_filter(PORT_ID(sdev), vlan_id, on); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_vlan_filter failed for sub_device %d" " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -631,13 +909,22 @@ fs_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { struct sub_device *sdev; + int ret; + fs_lock(dev, 0); sdev = TX_SUBDEV(dev); - if (sdev == NULL) - return 0; - if (SUBOPS(sdev, flow_ctrl_get) == NULL) - return -ENOTSUP; - return SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf); + if (sdev == NULL) { + ret = 0; + goto unlock; + } + if (SUBOPS(sdev, flow_ctrl_get) == NULL) { + ret = -ENOTSUP; + goto unlock; + } + ret = SUBOPS(sdev, flow_ctrl_get)(ETH(sdev), fc_conf); +unlock: + fs_unlock(dev, 0); + return ret; } static int @@ -648,15 +935,18 @@ fs_flow_ctrl_set(struct rte_eth_dev *dev, uint8_t i; int ret; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_flow_ctrl_set on sub_device %d", i); ret = rte_eth_dev_flow_ctrl_set(PORT_ID(sdev), fc_conf); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_flow_ctrl_set failed for sub_device %d" " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -666,6 +956,7 @@ fs_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); /* No check: already done within the rte_eth_dev_mac_addr_remove * call for the fail-safe device. */ @@ -673,6 +964,7 @@ fs_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index) rte_eth_dev_mac_addr_remove(PORT_ID(sdev), &dev->data->mac_addrs[index]); PRIV(dev)->mac_addr_pool[index] = 0; + fs_unlock(dev, 0); } static int @@ -686,11 +978,13 @@ fs_mac_addr_add(struct rte_eth_dev *dev, uint8_t i; RTE_ASSERT(index < FAILSAFE_MAX_ETHADDR); + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { ret = rte_eth_dev_mac_addr_add(PORT_ID(sdev), mac_addr, vmdq); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_mac_addr_add failed for sub_device %" PRIu8 " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } @@ -699,6 +993,7 @@ fs_mac_addr_add(struct rte_eth_dev *dev, PRIV(dev)->nb_mac_addr = index; } PRIV(dev)->mac_addr_pool[index] = vmdq; + fs_unlock(dev, 0); return 0; } @@ -708,8 +1003,10 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) struct sub_device *sdev; uint8_t i; + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr); + fs_unlock(dev, 0); } static int @@ -727,15 +1024,18 @@ fs_filter_ctrl(struct rte_eth_dev *dev, *(const void **)arg = &fs_flow_ops; return 0; } + fs_lock(dev, 0); FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { DEBUG("Calling rte_eth_dev_filter_ctrl on sub_device %d", i); ret = rte_eth_dev_filter_ctrl(PORT_ID(sdev), type, op, arg); - if (ret) { + if ((ret = fs_err(sdev, ret))) { ERROR("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" " with error %d", i, ret); + fs_unlock(dev, 0); return ret; } } + fs_unlock(dev, 0); return 0; } @@ -761,6 +1061,8 @@ const struct eth_dev_ops failsafe_ops = { .tx_queue_setup = fs_tx_queue_setup, .rx_queue_release = fs_rx_queue_release, .tx_queue_release = fs_tx_queue_release, + .rx_queue_intr_enable = fs_rx_intr_enable, + .rx_queue_intr_disable = fs_rx_intr_disable, .flow_ctrl_get = fs_flow_ctrl_get, .flow_ctrl_set = fs_flow_ctrl_set, .mac_addr_remove = fs_mac_addr_remove, |