mlx5: refactor Rx code for the new verbs RSS API
[dpdk.git] / drivers / net / mlx5 / mlx5_rxmode.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2015 6WIND S.A.
5  *   Copyright 2015 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 <stddef.h>
35 #include <errno.h>
36 #include <string.h>
37
38 /* Verbs header. */
39 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
40 #ifdef PEDANTIC
41 #pragma GCC diagnostic ignored "-pedantic"
42 #endif
43 #include <infiniband/verbs.h>
44 #ifdef PEDANTIC
45 #pragma GCC diagnostic error "-pedantic"
46 #endif
47
48 /* DPDK headers don't like -pedantic. */
49 #ifdef PEDANTIC
50 #pragma GCC diagnostic ignored "-pedantic"
51 #endif
52 #include <rte_ethdev.h>
53 #ifdef PEDANTIC
54 #pragma GCC diagnostic error "-pedantic"
55 #endif
56
57 #include "mlx5.h"
58 #include "mlx5_rxtx.h"
59 #include "mlx5_utils.h"
60
61 static void hash_rxq_promiscuous_disable(struct hash_rxq *);
62 static void hash_rxq_allmulticast_disable(struct hash_rxq *);
63
64 /**
65  * Enable promiscuous mode in a hash RX queue.
66  *
67  * @param hash_rxq
68  *   Pointer to hash RX queue structure.
69  *
70  * @return
71  *   0 on success, errno value on failure.
72  */
73 static int
74 hash_rxq_promiscuous_enable(struct hash_rxq *hash_rxq)
75 {
76         struct ibv_flow *flow;
77         struct ibv_flow_attr attr = {
78                 .type = IBV_FLOW_ATTR_ALL_DEFAULT,
79                 .num_of_specs = 0,
80                 .port = hash_rxq->priv->port,
81                 .flags = 0
82         };
83
84         if (hash_rxq->priv->vf)
85                 return 0;
86         if (hash_rxq->promisc_flow != NULL)
87                 return 0;
88         DEBUG("%p: enabling promiscuous mode", (void *)hash_rxq);
89         errno = 0;
90         flow = ibv_create_flow(hash_rxq->qp, &attr);
91         if (flow == NULL) {
92                 /* It's not clear whether errno is always set in this case. */
93                 ERROR("%p: flow configuration failed, errno=%d: %s",
94                       (void *)hash_rxq, errno,
95                       (errno ? strerror(errno) : "Unknown error"));
96                 if (errno)
97                         return errno;
98                 return EINVAL;
99         }
100         hash_rxq->promisc_flow = flow;
101         DEBUG("%p: promiscuous mode enabled", (void *)hash_rxq);
102         return 0;
103 }
104
105 /**
106  * Enable promiscuous mode in all hash RX queues.
107  *
108  * @param priv
109  *   Private structure.
110  *
111  * @return
112  *   0 on success, errno value on failure.
113  */
114 int
115 priv_promiscuous_enable(struct priv *priv)
116 {
117         unsigned int i;
118
119         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
120                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
121                 int ret;
122
123                 ret = hash_rxq_promiscuous_enable(hash_rxq);
124                 if (!ret)
125                         continue;
126                 /* Failure, rollback. */
127                 while (i != 0) {
128                         hash_rxq = &(*priv->hash_rxqs)[--i];
129                         hash_rxq_promiscuous_disable(hash_rxq);
130                 }
131                 return ret;
132         }
133         return 0;
134 }
135
136 /**
137  * DPDK callback to enable promiscuous mode.
138  *
139  * @param dev
140  *   Pointer to Ethernet device structure.
141  */
142 void
143 mlx5_promiscuous_enable(struct rte_eth_dev *dev)
144 {
145         struct priv *priv = dev->data->dev_private;
146         int ret;
147
148         priv_lock(priv);
149         priv->promisc_req = 1;
150         ret = priv_promiscuous_enable(priv);
151         if (ret)
152                 ERROR("cannot enable promiscuous mode: %s", strerror(ret));
153         priv_unlock(priv);
154 }
155
156 /**
157  * Disable promiscuous mode in a hash RX queue.
158  *
159  * @param hash_rxq
160  *   Pointer to hash RX queue structure.
161  */
162 static void
163 hash_rxq_promiscuous_disable(struct hash_rxq *hash_rxq)
164 {
165         if (hash_rxq->priv->vf)
166                 return;
167         if (hash_rxq->promisc_flow == NULL)
168                 return;
169         DEBUG("%p: disabling promiscuous mode", (void *)hash_rxq);
170         claim_zero(ibv_destroy_flow(hash_rxq->promisc_flow));
171         hash_rxq->promisc_flow = NULL;
172         DEBUG("%p: promiscuous mode disabled", (void *)hash_rxq);
173 }
174
175 /**
176  * Disable promiscuous mode in all hash RX queues.
177  *
178  * @param priv
179  *   Private structure.
180  */
181 void
182 priv_promiscuous_disable(struct priv *priv)
183 {
184         unsigned int i;
185
186         for (i = 0; (i != priv->hash_rxqs_n); ++i)
187                 hash_rxq_promiscuous_disable(&(*priv->hash_rxqs)[i]);
188 }
189
190 /**
191  * DPDK callback to disable promiscuous mode.
192  *
193  * @param dev
194  *   Pointer to Ethernet device structure.
195  */
196 void
197 mlx5_promiscuous_disable(struct rte_eth_dev *dev)
198 {
199         struct priv *priv = dev->data->dev_private;
200
201         priv_lock(priv);
202         priv->promisc_req = 0;
203         priv_promiscuous_disable(priv);
204         priv_unlock(priv);
205 }
206
207 /**
208  * Enable allmulti mode in a hash RX queue.
209  *
210  * @param hash_rxq
211  *   Pointer to hash RX queue structure.
212  *
213  * @return
214  *   0 on success, errno value on failure.
215  */
216 static int
217 hash_rxq_allmulticast_enable(struct hash_rxq *hash_rxq)
218 {
219         struct ibv_flow *flow;
220         struct ibv_flow_attr attr = {
221                 .type = IBV_FLOW_ATTR_MC_DEFAULT,
222                 .num_of_specs = 0,
223                 .port = hash_rxq->priv->port,
224                 .flags = 0
225         };
226
227         if (hash_rxq->allmulti_flow != NULL)
228                 return 0;
229         DEBUG("%p: enabling allmulticast mode", (void *)hash_rxq);
230         errno = 0;
231         flow = ibv_create_flow(hash_rxq->qp, &attr);
232         if (flow == NULL) {
233                 /* It's not clear whether errno is always set in this case. */
234                 ERROR("%p: flow configuration failed, errno=%d: %s",
235                       (void *)hash_rxq, errno,
236                       (errno ? strerror(errno) : "Unknown error"));
237                 if (errno)
238                         return errno;
239                 return EINVAL;
240         }
241         hash_rxq->allmulti_flow = flow;
242         DEBUG("%p: allmulticast mode enabled", (void *)hash_rxq);
243         return 0;
244 }
245
246 /**
247  * Enable allmulti mode in most hash RX queues.
248  * TCP queues are exempted to save resources.
249  *
250  * @param priv
251  *   Private structure.
252  *
253  * @return
254  *   0 on success, errno value on failure.
255  */
256 int
257 priv_allmulticast_enable(struct priv *priv)
258 {
259         unsigned int i;
260
261         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
262                 struct hash_rxq *hash_rxq = &(*priv->hash_rxqs)[i];
263                 int ret;
264
265                 ret = hash_rxq_allmulticast_enable(hash_rxq);
266                 if (!ret)
267                         continue;
268                 /* Failure, rollback. */
269                 while (i != 0) {
270                         hash_rxq = &(*priv->hash_rxqs)[--i];
271                         hash_rxq_allmulticast_disable(hash_rxq);
272                 }
273                 return ret;
274         }
275         return 0;
276 }
277
278 /**
279  * DPDK callback to enable allmulti mode.
280  *
281  * @param dev
282  *   Pointer to Ethernet device structure.
283  */
284 void
285 mlx5_allmulticast_enable(struct rte_eth_dev *dev)
286 {
287         struct priv *priv = dev->data->dev_private;
288         int ret;
289
290         priv_lock(priv);
291         priv->allmulti_req = 1;
292         ret = priv_allmulticast_enable(priv);
293         if (ret)
294                 ERROR("cannot enable allmulticast mode: %s", strerror(ret));
295         priv_unlock(priv);
296 }
297
298 /**
299  * Disable allmulti mode in a hash RX queue.
300  *
301  * @param hash_rxq
302  *   Pointer to hash RX queue structure.
303  */
304 static void
305 hash_rxq_allmulticast_disable(struct hash_rxq *hash_rxq)
306 {
307         if (hash_rxq->allmulti_flow == NULL)
308                 return;
309         DEBUG("%p: disabling allmulticast mode", (void *)hash_rxq);
310         claim_zero(ibv_destroy_flow(hash_rxq->allmulti_flow));
311         hash_rxq->allmulti_flow = NULL;
312         DEBUG("%p: allmulticast mode disabled", (void *)hash_rxq);
313 }
314
315 /**
316  * Disable allmulti mode in all hash RX queues.
317  *
318  * @param priv
319  *   Private structure.
320  */
321 void
322 priv_allmulticast_disable(struct priv *priv)
323 {
324         unsigned int i;
325
326         for (i = 0; (i != priv->hash_rxqs_n); ++i)
327                 hash_rxq_allmulticast_disable(&(*priv->hash_rxqs)[i]);
328 }
329
330 /**
331  * DPDK callback to disable allmulti mode.
332  *
333  * @param dev
334  *   Pointer to Ethernet device structure.
335  */
336 void
337 mlx5_allmulticast_disable(struct rte_eth_dev *dev)
338 {
339         struct priv *priv = dev->data->dev_private;
340
341         priv_lock(priv);
342         priv->allmulti_req = 0;
343         priv_allmulticast_disable(priv);
344         priv_unlock(priv);
345 }