1009c327cSOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2a46f8d58SGaetan Rivet * Copyright 2017 6WIND S.A.
35feecc57SShahaf Shuler * Copyright 2017 Mellanox Technologies, Ltd
4a46f8d58SGaetan Rivet */
5a46f8d58SGaetan Rivet
6598fb8aeSGaetan Rivet #include <rte_atomic.h>
772a57bfdSGaetan Rivet #include <rte_debug.h>
8a46f8d58SGaetan Rivet #include <rte_mbuf.h>
9*df96fd0dSBruce Richardson #include <ethdev_driver.h>
10a46f8d58SGaetan Rivet
11a46f8d58SGaetan Rivet #include "failsafe_private.h"
12a46f8d58SGaetan Rivet
1372a57bfdSGaetan Rivet static inline int
fs_rx_unsafe(struct sub_device * sdev)1472a57bfdSGaetan Rivet fs_rx_unsafe(struct sub_device *sdev)
1572a57bfdSGaetan Rivet {
1672a57bfdSGaetan Rivet return (ETH(sdev) == NULL) ||
1772a57bfdSGaetan Rivet (ETH(sdev)->rx_pkt_burst == NULL) ||
18295f7ed2SMatan Azrad (sdev->state != DEV_STARTED) ||
19295f7ed2SMatan Azrad (sdev->remove != 0);
2072a57bfdSGaetan Rivet }
2172a57bfdSGaetan Rivet
2272a57bfdSGaetan Rivet static inline int
fs_tx_unsafe(struct sub_device * sdev)2372a57bfdSGaetan Rivet fs_tx_unsafe(struct sub_device *sdev)
2472a57bfdSGaetan Rivet {
2572a57bfdSGaetan Rivet return (sdev == NULL) ||
2672a57bfdSGaetan Rivet (ETH(sdev) == NULL) ||
2772a57bfdSGaetan Rivet (ETH(sdev)->tx_pkt_burst == NULL) ||
2872a57bfdSGaetan Rivet (sdev->state != DEV_STARTED);
2972a57bfdSGaetan Rivet }
3072a57bfdSGaetan Rivet
3172a57bfdSGaetan Rivet void
failsafe_set_burst_fn(struct rte_eth_dev * dev,int force_safe)3286123c2dSStephen Hemminger failsafe_set_burst_fn(struct rte_eth_dev *dev, int force_safe)
3372a57bfdSGaetan Rivet {
3472a57bfdSGaetan Rivet struct sub_device *sdev;
3572a57bfdSGaetan Rivet uint8_t i;
3672a57bfdSGaetan Rivet int need_safe;
3772a57bfdSGaetan Rivet int safe_set;
3872a57bfdSGaetan Rivet
3972a57bfdSGaetan Rivet need_safe = force_safe;
4072a57bfdSGaetan Rivet FOREACH_SUBDEV(sdev, i, dev)
4172a57bfdSGaetan Rivet need_safe |= fs_rx_unsafe(sdev);
4272a57bfdSGaetan Rivet safe_set = (dev->rx_pkt_burst == &failsafe_rx_burst);
4372a57bfdSGaetan Rivet if (need_safe && !safe_set) {
4472a57bfdSGaetan Rivet DEBUG("Using safe RX bursts%s",
4572a57bfdSGaetan Rivet (force_safe ? " (forced)" : ""));
4672a57bfdSGaetan Rivet dev->rx_pkt_burst = &failsafe_rx_burst;
4772a57bfdSGaetan Rivet } else if (!need_safe && safe_set) {
4872a57bfdSGaetan Rivet DEBUG("Using fast RX bursts");
4972a57bfdSGaetan Rivet dev->rx_pkt_burst = &failsafe_rx_burst_fast;
5072a57bfdSGaetan Rivet }
5172a57bfdSGaetan Rivet need_safe = force_safe || fs_tx_unsafe(TX_SUBDEV(dev));
5272a57bfdSGaetan Rivet safe_set = (dev->tx_pkt_burst == &failsafe_tx_burst);
5372a57bfdSGaetan Rivet if (need_safe && !safe_set) {
5472a57bfdSGaetan Rivet DEBUG("Using safe TX bursts%s",
5572a57bfdSGaetan Rivet (force_safe ? " (forced)" : ""));
5672a57bfdSGaetan Rivet dev->tx_pkt_burst = &failsafe_tx_burst;
5772a57bfdSGaetan Rivet } else if (!need_safe && safe_set) {
5872a57bfdSGaetan Rivet DEBUG("Using fast TX bursts");
5972a57bfdSGaetan Rivet dev->tx_pkt_burst = &failsafe_tx_burst_fast;
6072a57bfdSGaetan Rivet }
6172a57bfdSGaetan Rivet rte_wmb();
6272a57bfdSGaetan Rivet }
6372a57bfdSGaetan Rivet
6498e91784SAdrien Mazarguil /*
6598e91784SAdrien Mazarguil * Override source port in Rx packets.
6698e91784SAdrien Mazarguil *
6798e91784SAdrien Mazarguil * Make Rx packets originate from this PMD instance instead of one of its
6898e91784SAdrien Mazarguil * sub-devices. This is mandatory to avoid breaking applications.
6998e91784SAdrien Mazarguil */
7098e91784SAdrien Mazarguil static void
failsafe_rx_set_port(struct rte_mbuf ** rx_pkts,uint16_t nb_pkts,uint16_t port)7198e91784SAdrien Mazarguil failsafe_rx_set_port(struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint16_t port)
7298e91784SAdrien Mazarguil {
7398e91784SAdrien Mazarguil unsigned int i;
7498e91784SAdrien Mazarguil
7598e91784SAdrien Mazarguil for (i = 0; i != nb_pkts; ++i)
7698e91784SAdrien Mazarguil rx_pkts[i]->port = port;
7798e91784SAdrien Mazarguil }
7898e91784SAdrien Mazarguil
79a46f8d58SGaetan Rivet uint16_t
failsafe_rx_burst(void * queue,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)80a46f8d58SGaetan Rivet failsafe_rx_burst(void *queue,
81a46f8d58SGaetan Rivet struct rte_mbuf **rx_pkts,
82a46f8d58SGaetan Rivet uint16_t nb_pkts)
83a46f8d58SGaetan Rivet {
84a46f8d58SGaetan Rivet struct sub_device *sdev;
85a46f8d58SGaetan Rivet struct rxq *rxq;
86a46f8d58SGaetan Rivet void *sub_rxq;
87a46f8d58SGaetan Rivet uint16_t nb_rx;
88a46f8d58SGaetan Rivet
89a46f8d58SGaetan Rivet rxq = queue;
908052bbd9SMatan Azrad sdev = rxq->sdev;
918052bbd9SMatan Azrad do {
928052bbd9SMatan Azrad if (fs_rx_unsafe(sdev)) {
938052bbd9SMatan Azrad nb_rx = 0;
94745b72daSMatan Azrad sdev = sdev->next;
95a46f8d58SGaetan Rivet continue;
968052bbd9SMatan Azrad }
97a46f8d58SGaetan Rivet sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid];
98598fb8aeSGaetan Rivet FS_ATOMIC_P(rxq->refcnt[sdev->sid]);
99a46f8d58SGaetan Rivet nb_rx = ETH(sdev)->
100a46f8d58SGaetan Rivet rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts);
101598fb8aeSGaetan Rivet FS_ATOMIC_V(rxq->refcnt[sdev->sid]);
1028052bbd9SMatan Azrad sdev = sdev->next;
1038052bbd9SMatan Azrad } while (nb_rx == 0 && sdev != rxq->sdev);
1048052bbd9SMatan Azrad rxq->sdev = sdev;
10598e91784SAdrien Mazarguil if (nb_rx)
10698e91784SAdrien Mazarguil failsafe_rx_set_port(rx_pkts, nb_rx,
10798e91784SAdrien Mazarguil rxq->priv->data->port_id);
108a46f8d58SGaetan Rivet return nb_rx;
109a46f8d58SGaetan Rivet }
110a46f8d58SGaetan Rivet
11172a57bfdSGaetan Rivet uint16_t
failsafe_rx_burst_fast(void * queue,struct rte_mbuf ** rx_pkts,uint16_t nb_pkts)11272a57bfdSGaetan Rivet failsafe_rx_burst_fast(void *queue,
11372a57bfdSGaetan Rivet struct rte_mbuf **rx_pkts,
11472a57bfdSGaetan Rivet uint16_t nb_pkts)
11572a57bfdSGaetan Rivet {
11672a57bfdSGaetan Rivet struct sub_device *sdev;
11772a57bfdSGaetan Rivet struct rxq *rxq;
11872a57bfdSGaetan Rivet void *sub_rxq;
11972a57bfdSGaetan Rivet uint16_t nb_rx;
12072a57bfdSGaetan Rivet
12172a57bfdSGaetan Rivet rxq = queue;
1228052bbd9SMatan Azrad sdev = rxq->sdev;
1238052bbd9SMatan Azrad do {
12472a57bfdSGaetan Rivet RTE_ASSERT(!fs_rx_unsafe(sdev));
12572a57bfdSGaetan Rivet sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid];
126598fb8aeSGaetan Rivet FS_ATOMIC_P(rxq->refcnt[sdev->sid]);
12772a57bfdSGaetan Rivet nb_rx = ETH(sdev)->
12872a57bfdSGaetan Rivet rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts);
129598fb8aeSGaetan Rivet FS_ATOMIC_V(rxq->refcnt[sdev->sid]);
1308052bbd9SMatan Azrad sdev = sdev->next;
1318052bbd9SMatan Azrad } while (nb_rx == 0 && sdev != rxq->sdev);
1328052bbd9SMatan Azrad rxq->sdev = sdev;
13398e91784SAdrien Mazarguil if (nb_rx)
13498e91784SAdrien Mazarguil failsafe_rx_set_port(rx_pkts, nb_rx,
13598e91784SAdrien Mazarguil rxq->priv->data->port_id);
13672a57bfdSGaetan Rivet return nb_rx;
13772a57bfdSGaetan Rivet }
13872a57bfdSGaetan Rivet
139a46f8d58SGaetan Rivet uint16_t
failsafe_tx_burst(void * queue,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)140a46f8d58SGaetan Rivet failsafe_tx_burst(void *queue,
141a46f8d58SGaetan Rivet struct rte_mbuf **tx_pkts,
142a46f8d58SGaetan Rivet uint16_t nb_pkts)
143a46f8d58SGaetan Rivet {
144a46f8d58SGaetan Rivet struct sub_device *sdev;
145a46f8d58SGaetan Rivet struct txq *txq;
146a46f8d58SGaetan Rivet void *sub_txq;
147598fb8aeSGaetan Rivet uint16_t nb_tx;
148a46f8d58SGaetan Rivet
149a46f8d58SGaetan Rivet txq = queue;
15008647012SRaslan Darawsheh sdev = TX_SUBDEV(&rte_eth_devices[txq->priv->data->port_id]);
15172a57bfdSGaetan Rivet if (unlikely(fs_tx_unsafe(sdev)))
152a46f8d58SGaetan Rivet return 0;
15372a57bfdSGaetan Rivet sub_txq = ETH(sdev)->data->tx_queues[txq->qid];
154598fb8aeSGaetan Rivet FS_ATOMIC_P(txq->refcnt[sdev->sid]);
155598fb8aeSGaetan Rivet nb_tx = ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts);
156598fb8aeSGaetan Rivet FS_ATOMIC_V(txq->refcnt[sdev->sid]);
157598fb8aeSGaetan Rivet return nb_tx;
15872a57bfdSGaetan Rivet }
15972a57bfdSGaetan Rivet
16072a57bfdSGaetan Rivet uint16_t
failsafe_tx_burst_fast(void * queue,struct rte_mbuf ** tx_pkts,uint16_t nb_pkts)16172a57bfdSGaetan Rivet failsafe_tx_burst_fast(void *queue,
16272a57bfdSGaetan Rivet struct rte_mbuf **tx_pkts,
16372a57bfdSGaetan Rivet uint16_t nb_pkts)
16472a57bfdSGaetan Rivet {
16572a57bfdSGaetan Rivet struct sub_device *sdev;
16672a57bfdSGaetan Rivet struct txq *txq;
16772a57bfdSGaetan Rivet void *sub_txq;
168598fb8aeSGaetan Rivet uint16_t nb_tx;
16972a57bfdSGaetan Rivet
17072a57bfdSGaetan Rivet txq = queue;
17108647012SRaslan Darawsheh sdev = TX_SUBDEV(&rte_eth_devices[txq->priv->data->port_id]);
17272a57bfdSGaetan Rivet RTE_ASSERT(!fs_tx_unsafe(sdev));
173a46f8d58SGaetan Rivet sub_txq = ETH(sdev)->data->tx_queues[txq->qid];
174598fb8aeSGaetan Rivet FS_ATOMIC_P(txq->refcnt[sdev->sid]);
175598fb8aeSGaetan Rivet nb_tx = ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts);
176598fb8aeSGaetan Rivet FS_ATOMIC_V(txq->refcnt[sdev->sid]);
177598fb8aeSGaetan Rivet return nb_tx;
178a46f8d58SGaetan Rivet }
179