Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright 2017 6WIND S.A. 3 : : * Copyright 2017 Mellanox Technologies, Ltd 4 : : */ 5 : : 6 : : #include <rte_atomic.h> 7 : : #include <rte_debug.h> 8 : : #include <rte_mbuf.h> 9 : : #include <ethdev_driver.h> 10 : : 11 : : #include "failsafe_private.h" 12 : : 13 : : static inline int 14 : : fs_rx_unsafe(struct sub_device *sdev) 15 : : { 16 : 0 : return (ETH(sdev) == NULL) || 17 [ # # # # ]: 0 : (ETH(sdev)->rx_pkt_burst == NULL) || 18 [ # # # # : 0 : (sdev->state != DEV_STARTED) || # # # # ] 19 [ # # # # ]: 0 : (sdev->remove != 0); 20 : : } 21 : : 22 : : static inline int 23 : : fs_tx_unsafe(struct sub_device *sdev) 24 : : { 25 : 0 : return (sdev == NULL) || 26 [ # # # # ]: 0 : (ETH(sdev) == NULL) || 27 [ # # # # : 0 : (ETH(sdev)->tx_pkt_burst == NULL) || # # # # ] 28 : : (sdev->state != DEV_STARTED); 29 : : } 30 : : 31 : : void 32 [ # # ]: 0 : failsafe_set_burst_fn(struct rte_eth_dev *dev, int force_safe) 33 : : { 34 : : struct sub_device *sdev; 35 : : uint8_t i; 36 : : int need_safe; 37 : : int safe_set; 38 : : 39 : : need_safe = force_safe; 40 [ # # ]: 0 : FOREACH_SUBDEV(sdev, i, dev) 41 [ # # ]: 0 : need_safe |= fs_rx_unsafe(sdev); 42 : 0 : safe_set = (dev->rx_pkt_burst == &failsafe_rx_burst); 43 [ # # ]: 0 : if (need_safe && !safe_set) { 44 [ # # ]: 0 : DEBUG("Using safe RX bursts%s", 45 : : (force_safe ? " (forced)" : "")); 46 : 0 : dev->rx_pkt_burst = &failsafe_rx_burst; 47 [ # # ]: 0 : } else if (!need_safe && safe_set) { 48 : 0 : DEBUG("Using fast RX bursts"); 49 : 0 : dev->rx_pkt_burst = &failsafe_rx_burst_fast; 50 : : } 51 [ # # # # : 0 : need_safe = force_safe || fs_tx_unsafe(TX_SUBDEV(dev)); # # ] 52 : 0 : safe_set = (dev->tx_pkt_burst == &failsafe_tx_burst); 53 [ # # ]: 0 : if (need_safe && !safe_set) { 54 [ # # ]: 0 : DEBUG("Using safe TX bursts%s", 55 : : (force_safe ? " (forced)" : "")); 56 : 0 : dev->tx_pkt_burst = &failsafe_tx_burst; 57 [ # # ]: 0 : } else if (!need_safe && safe_set) { 58 : 0 : DEBUG("Using fast TX bursts"); 59 : 0 : dev->tx_pkt_burst = &failsafe_tx_burst_fast; 60 : : } 61 : : rte_wmb(); 62 : 0 : } 63 : : 64 : : /* 65 : : * Override source port in Rx packets. 66 : : * 67 : : * Make Rx packets originate from this PMD instance instead of one of its 68 : : * sub-devices. This is mandatory to avoid breaking applications. 69 : : */ 70 : : static void 71 : : failsafe_rx_set_port(struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint16_t port) 72 : : { 73 : : unsigned int i; 74 : : 75 [ # # # # ]: 0 : for (i = 0; i != nb_pkts; ++i) 76 : 0 : rx_pkts[i]->port = port; 77 : : } 78 : : 79 : : uint16_t 80 : 0 : failsafe_rx_burst(void *queue, 81 : : struct rte_mbuf **rx_pkts, 82 : : uint16_t nb_pkts) 83 : : { 84 : : struct sub_device *sdev; 85 : : struct rxq *rxq; 86 : : void *sub_rxq; 87 : : uint16_t nb_rx; 88 : : 89 : : rxq = queue; 90 : 0 : sdev = rxq->sdev; 91 : : do { 92 : 0 : if (fs_rx_unsafe(sdev)) { 93 : : nb_rx = 0; 94 : 0 : sdev = sdev->next; 95 : : continue; 96 : : } 97 : 0 : sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid]; 98 : 0 : FS_ATOMIC_P(rxq->refcnt[sdev->sid]); 99 : 0 : nb_rx = ETH(sdev)-> 100 : : rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts); 101 [ # # ]: 0 : FS_ATOMIC_V(rxq->refcnt[sdev->sid]); 102 : 0 : sdev = sdev->next; 103 [ # # # # ]: 0 : } while (nb_rx == 0 && sdev != rxq->sdev); 104 : 0 : rxq->sdev = sdev; 105 [ # # ]: 0 : if (nb_rx) 106 : : failsafe_rx_set_port(rx_pkts, nb_rx, 107 : 0 : rxq->priv->data->port_id); 108 : 0 : return nb_rx; 109 : : } 110 : : 111 : : uint16_t 112 : 0 : failsafe_rx_burst_fast(void *queue, 113 : : struct rte_mbuf **rx_pkts, 114 : : uint16_t nb_pkts) 115 : : { 116 : : struct sub_device *sdev; 117 : : struct rxq *rxq; 118 : : void *sub_rxq; 119 : : uint16_t nb_rx; 120 : : 121 : : rxq = queue; 122 : 0 : sdev = rxq->sdev; 123 : : do { 124 : : RTE_ASSERT(!fs_rx_unsafe(sdev)); 125 [ # # ]: 0 : sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid]; 126 : 0 : FS_ATOMIC_P(rxq->refcnt[sdev->sid]); 127 : 0 : nb_rx = ETH(sdev)-> 128 : : rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts); 129 [ # # ]: 0 : FS_ATOMIC_V(rxq->refcnt[sdev->sid]); 130 : 0 : sdev = sdev->next; 131 [ # # # # ]: 0 : } while (nb_rx == 0 && sdev != rxq->sdev); 132 : 0 : rxq->sdev = sdev; 133 [ # # ]: 0 : if (nb_rx) 134 : : failsafe_rx_set_port(rx_pkts, nb_rx, 135 : 0 : rxq->priv->data->port_id); 136 : 0 : return nb_rx; 137 : : } 138 : : 139 : : uint16_t 140 : 0 : failsafe_tx_burst(void *queue, 141 : : struct rte_mbuf **tx_pkts, 142 : : uint16_t nb_pkts) 143 : : { 144 : : struct sub_device *sdev; 145 : : struct txq *txq; 146 : : void *sub_txq; 147 : : uint16_t nb_tx; 148 : : 149 : : txq = queue; 150 [ # # # # ]: 0 : sdev = TX_SUBDEV(&rte_eth_devices[txq->priv->data->port_id]); 151 [ # # ]: 0 : if (unlikely(fs_tx_unsafe(sdev))) 152 : : return 0; 153 [ # # ]: 0 : sub_txq = ETH(sdev)->data->tx_queues[txq->qid]; 154 : 0 : FS_ATOMIC_P(txq->refcnt[sdev->sid]); 155 : 0 : nb_tx = ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts); 156 : 0 : FS_ATOMIC_V(txq->refcnt[sdev->sid]); 157 : 0 : return nb_tx; 158 : : } 159 : : 160 : : uint16_t 161 : 0 : failsafe_tx_burst_fast(void *queue, 162 : : struct rte_mbuf **tx_pkts, 163 : : uint16_t nb_pkts) 164 : : { 165 : : struct sub_device *sdev; 166 : : struct txq *txq; 167 : : void *sub_txq; 168 : : uint16_t nb_tx; 169 : : 170 : : txq = queue; 171 [ # # # # ]: 0 : sdev = TX_SUBDEV(&rte_eth_devices[txq->priv->data->port_id]); 172 : : RTE_ASSERT(!fs_tx_unsafe(sdev)); 173 [ # # ]: 0 : sub_txq = ETH(sdev)->data->tx_queues[txq->qid]; 174 : 0 : FS_ATOMIC_P(txq->refcnt[sdev->sid]); 175 : 0 : nb_tx = ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts); 176 : 0 : FS_ATOMIC_V(txq->refcnt[sdev->sid]); 177 : 0 : return nb_tx; 178 : : }