net/failsafe: add fast burst functions
[dpdk.git] / drivers / net / failsafe / failsafe_rxtx.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2017 6WIND S.A.
5  *   Copyright 2017 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_debug.h>
35 #include <rte_mbuf.h>
36 #include <rte_ethdev.h>
37
38 #include "failsafe_private.h"
39
40 static inline int
41 fs_rx_unsafe(struct sub_device *sdev)
42 {
43         return (ETH(sdev) == NULL) ||
44                 (ETH(sdev)->rx_pkt_burst == NULL) ||
45                 (sdev->state != DEV_STARTED);
46 }
47
48 static inline int
49 fs_tx_unsafe(struct sub_device *sdev)
50 {
51         return (sdev == NULL) ||
52                 (ETH(sdev) == NULL) ||
53                 (ETH(sdev)->tx_pkt_burst == NULL) ||
54                 (sdev->state != DEV_STARTED);
55 }
56
57 void
58 set_burst_fn(struct rte_eth_dev *dev, int force_safe)
59 {
60         struct sub_device *sdev;
61         uint8_t i;
62         int need_safe;
63         int safe_set;
64
65         need_safe = force_safe;
66         FOREACH_SUBDEV(sdev, i, dev)
67                 need_safe |= fs_rx_unsafe(sdev);
68         safe_set = (dev->rx_pkt_burst == &failsafe_rx_burst);
69         if (need_safe && !safe_set) {
70                 DEBUG("Using safe RX bursts%s",
71                       (force_safe ? " (forced)" : ""));
72                 dev->rx_pkt_burst = &failsafe_rx_burst;
73         } else if (!need_safe && safe_set) {
74                 DEBUG("Using fast RX bursts");
75                 dev->rx_pkt_burst = &failsafe_rx_burst_fast;
76         }
77         need_safe = force_safe || fs_tx_unsafe(TX_SUBDEV(dev));
78         safe_set = (dev->tx_pkt_burst == &failsafe_tx_burst);
79         if (need_safe && !safe_set) {
80                 DEBUG("Using safe TX bursts%s",
81                       (force_safe ? " (forced)" : ""));
82                 dev->tx_pkt_burst = &failsafe_tx_burst;
83         } else if (!need_safe && safe_set) {
84                 DEBUG("Using fast TX bursts");
85                 dev->tx_pkt_burst = &failsafe_tx_burst_fast;
86         }
87         rte_wmb();
88 }
89
90 uint16_t
91 failsafe_rx_burst(void *queue,
92                   struct rte_mbuf **rx_pkts,
93                   uint16_t nb_pkts)
94 {
95         struct fs_priv *priv;
96         struct sub_device *sdev;
97         struct rxq *rxq;
98         void *sub_rxq;
99         uint16_t nb_rx;
100         uint8_t nb_polled, nb_subs;
101         uint8_t i;
102
103         rxq = queue;
104         priv = rxq->priv;
105         nb_subs = priv->subs_tail - priv->subs_head;
106         nb_polled = 0;
107         for (i = rxq->last_polled; nb_polled < nb_subs; nb_polled++) {
108                 i++;
109                 if (i == priv->subs_tail)
110                         i = priv->subs_head;
111                 sdev = &priv->subs[i];
112                 if (unlikely(fs_rx_unsafe(sdev)))
113                         continue;
114                 sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid];
115                 nb_rx = ETH(sdev)->
116                         rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts);
117                 if (nb_rx) {
118                         rxq->last_polled = i;
119                         return nb_rx;
120                 }
121         }
122         return 0;
123 }
124
125 uint16_t
126 failsafe_rx_burst_fast(void *queue,
127                          struct rte_mbuf **rx_pkts,
128                          uint16_t nb_pkts)
129 {
130         struct fs_priv *priv;
131         struct sub_device *sdev;
132         struct rxq *rxq;
133         void *sub_rxq;
134         uint16_t nb_rx;
135         uint8_t nb_polled, nb_subs;
136         uint8_t i;
137
138         rxq = queue;
139         priv = rxq->priv;
140         nb_subs = priv->subs_tail - priv->subs_head;
141         nb_polled = 0;
142         for (i = rxq->last_polled; nb_polled < nb_subs; nb_polled++) {
143                 i++;
144                 if (i == priv->subs_tail)
145                         i = priv->subs_head;
146                 sdev = &priv->subs[i];
147                 RTE_ASSERT(!fs_rx_unsafe(sdev));
148                 sub_rxq = ETH(sdev)->data->rx_queues[rxq->qid];
149                 nb_rx = ETH(sdev)->
150                         rx_pkt_burst(sub_rxq, rx_pkts, nb_pkts);
151                 if (nb_rx) {
152                         rxq->last_polled = i;
153                         return nb_rx;
154                 }
155         }
156         return 0;
157 }
158
159 uint16_t
160 failsafe_tx_burst(void *queue,
161                   struct rte_mbuf **tx_pkts,
162                   uint16_t nb_pkts)
163 {
164         struct sub_device *sdev;
165         struct txq *txq;
166         void *sub_txq;
167
168         txq = queue;
169         sdev = TX_SUBDEV(txq->priv->dev);
170         if (unlikely(fs_tx_unsafe(sdev)))
171                 return 0;
172         sub_txq = ETH(sdev)->data->tx_queues[txq->qid];
173         return ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts);
174 }
175
176 uint16_t
177 failsafe_tx_burst_fast(void *queue,
178                          struct rte_mbuf **tx_pkts,
179                          uint16_t nb_pkts)
180 {
181         struct sub_device *sdev;
182         struct txq *txq;
183         void *sub_txq;
184
185         txq = queue;
186         sdev = TX_SUBDEV(txq->priv->dev);
187         RTE_ASSERT(!fs_tx_unsafe(sdev));
188         sub_txq = ETH(sdev)->data->tx_queues[txq->qid];
189         return ETH(sdev)->tx_pkt_burst(sub_txq, tx_pkts, nb_pkts);
190 }