xref: /dpdk/drivers/net/failsafe/failsafe_rxtx.c (revision df96fd0d73955bdc7ca3909e772ff2ad903249c6)
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