net/qede/base: support doorbell overflow recovery
[dpdk.git] / drivers / net / mlx5 / mlx5_mac.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 <assert.h>
36 #include <stdint.h>
37 #include <string.h>
38 #include <inttypes.h>
39 #include <errno.h>
40 #include <netinet/in.h>
41 #include <sys/ioctl.h>
42 #include <arpa/inet.h>
43
44 /* Verbs header. */
45 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
46 #ifdef PEDANTIC
47 #pragma GCC diagnostic ignored "-Wpedantic"
48 #endif
49 #include <infiniband/verbs.h>
50 #ifdef PEDANTIC
51 #pragma GCC diagnostic error "-Wpedantic"
52 #endif
53
54 #include <rte_ether.h>
55 #include <rte_ethdev.h>
56 #include <rte_common.h>
57
58 #include "mlx5.h"
59 #include "mlx5_utils.h"
60 #include "mlx5_rxtx.h"
61 #include "mlx5_defs.h"
62
63 /**
64  * Get MAC address by querying netdevice.
65  *
66  * @param[in] priv
67  *   struct priv for the requested device.
68  * @param[out] mac
69  *   MAC address output buffer.
70  *
71  * @return
72  *   0 on success, -1 on failure and errno is set.
73  */
74 int
75 priv_get_mac(struct priv *priv, uint8_t (*mac)[ETHER_ADDR_LEN])
76 {
77         struct ifreq request;
78
79         if (priv_ifreq(priv, SIOCGIFHWADDR, &request))
80                 return -1;
81         memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
82         return 0;
83 }
84
85 /**
86  * Delete MAC flow steering rule.
87  *
88  * @param hash_rxq
89  *   Pointer to hash RX queue structure.
90  * @param mac_index
91  *   MAC address index.
92  * @param vlan_index
93  *   VLAN index to use.
94  */
95 static void
96 hash_rxq_del_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
97                       unsigned int vlan_index)
98 {
99 #ifndef NDEBUG
100         const uint8_t (*mac)[ETHER_ADDR_LEN] =
101                 (const uint8_t (*)[ETHER_ADDR_LEN])
102                 hash_rxq->priv->mac[mac_index].addr_bytes;
103 #endif
104
105         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
106         assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
107         if (hash_rxq->mac_flow[mac_index][vlan_index] == NULL)
108                 return;
109         DEBUG("%p: removing MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
110               " VLAN index %u",
111               (void *)hash_rxq,
112               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
113               mac_index,
114               vlan_index);
115         claim_zero(ibv_exp_destroy_flow(hash_rxq->mac_flow
116                                         [mac_index][vlan_index]));
117         hash_rxq->mac_flow[mac_index][vlan_index] = NULL;
118 }
119
120 /**
121  * Unregister a MAC address from a hash RX queue.
122  *
123  * @param hash_rxq
124  *   Pointer to hash RX queue structure.
125  * @param mac_index
126  *   MAC address index.
127  */
128 static void
129 hash_rxq_mac_addr_del(struct hash_rxq *hash_rxq, unsigned int mac_index)
130 {
131         unsigned int i;
132
133         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
134         for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow[mac_index])); ++i)
135                 hash_rxq_del_mac_flow(hash_rxq, mac_index, i);
136 }
137
138 /**
139  * Unregister all MAC addresses from a hash RX queue.
140  *
141  * @param hash_rxq
142  *   Pointer to hash RX queue structure.
143  */
144 void
145 hash_rxq_mac_addrs_del(struct hash_rxq *hash_rxq)
146 {
147         unsigned int i;
148
149         for (i = 0; (i != RTE_DIM(hash_rxq->mac_flow)); ++i)
150                 hash_rxq_mac_addr_del(hash_rxq, i);
151 }
152
153 /**
154  * Unregister a MAC address.
155  *
156  * This is done for each hash RX queue.
157  *
158  * @param priv
159  *   Pointer to private structure.
160  * @param mac_index
161  *   MAC address index.
162  */
163 static void
164 priv_mac_addr_del(struct priv *priv, unsigned int mac_index)
165 {
166         unsigned int i;
167
168         assert(mac_index < RTE_DIM(priv->mac));
169         if (!BITFIELD_ISSET(priv->mac_configured, mac_index))
170                 return;
171         for (i = 0; (i != priv->hash_rxqs_n); ++i)
172                 hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[i], mac_index);
173         BITFIELD_RESET(priv->mac_configured, mac_index);
174 }
175
176 /**
177  * Unregister all MAC addresses from all hash RX queues.
178  *
179  * @param priv
180  *   Pointer to private structure.
181  */
182 void
183 priv_mac_addrs_disable(struct priv *priv)
184 {
185         unsigned int i;
186
187         for (i = 0; (i != priv->hash_rxqs_n); ++i)
188                 hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[i]);
189 }
190
191 /**
192  * DPDK callback to remove a MAC address.
193  *
194  * @param dev
195  *   Pointer to Ethernet device structure.
196  * @param index
197  *   MAC address index.
198  */
199 void
200 mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
201 {
202         struct priv *priv = dev->data->dev_private;
203
204         if (mlx5_is_secondary())
205                 return;
206
207         priv_lock(priv);
208         DEBUG("%p: removing MAC address from index %" PRIu32,
209               (void *)dev, index);
210         if (index >= RTE_DIM(priv->mac))
211                 goto end;
212         priv_mac_addr_del(priv, index);
213 end:
214         priv_unlock(priv);
215 }
216
217 /**
218  * Add MAC flow steering rule.
219  *
220  * @param hash_rxq
221  *   Pointer to hash RX queue structure.
222  * @param mac_index
223  *   MAC address index to register.
224  * @param vlan_index
225  *   VLAN index to use.
226  *
227  * @return
228  *   0 on success, errno value on failure.
229  */
230 static int
231 hash_rxq_add_mac_flow(struct hash_rxq *hash_rxq, unsigned int mac_index,
232                       unsigned int vlan_index)
233 {
234         struct ibv_exp_flow *flow;
235         struct priv *priv = hash_rxq->priv;
236         const uint8_t (*mac)[ETHER_ADDR_LEN] =
237                         (const uint8_t (*)[ETHER_ADDR_LEN])
238                         priv->mac[mac_index].addr_bytes;
239         FLOW_ATTR_SPEC_ETH(data, priv_flow_attr(priv, NULL, 0, hash_rxq->type));
240         struct ibv_exp_flow_attr *attr = &data->attr;
241         struct ibv_exp_flow_spec_eth *spec = &data->spec;
242         unsigned int vlan_enabled = !!priv->vlan_filter_n;
243         unsigned int vlan_id = priv->vlan_filter[vlan_index];
244
245         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
246         assert(vlan_index < RTE_DIM(hash_rxq->mac_flow[mac_index]));
247         if (hash_rxq->mac_flow[mac_index][vlan_index] != NULL)
248                 return 0;
249         /*
250          * No padding must be inserted by the compiler between attr and spec.
251          * This layout is expected by libibverbs.
252          */
253         assert(((uint8_t *)attr + sizeof(*attr)) == (uint8_t *)spec);
254         priv_flow_attr(priv, attr, sizeof(data), hash_rxq->type);
255         /* The first specification must be Ethernet. */
256         assert(spec->type == IBV_EXP_FLOW_SPEC_ETH);
257         assert(spec->size == sizeof(*spec));
258         *spec = (struct ibv_exp_flow_spec_eth){
259                 .type = IBV_EXP_FLOW_SPEC_ETH,
260                 .size = sizeof(*spec),
261                 .val = {
262                         .dst_mac = {
263                                 (*mac)[0], (*mac)[1], (*mac)[2],
264                                 (*mac)[3], (*mac)[4], (*mac)[5]
265                         },
266                         .vlan_tag = (vlan_enabled ?
267                                      rte_cpu_to_be_16(vlan_id)
268                                      : 0),
269                 },
270                 .mask = {
271                         .dst_mac = "\xff\xff\xff\xff\xff\xff",
272                         .vlan_tag = (vlan_enabled ?
273                                      rte_cpu_to_be_16(0xfff) :
274                                      0),
275                 },
276         };
277         DEBUG("%p: adding MAC address %02x:%02x:%02x:%02x:%02x:%02x index %u"
278               " VLAN index %u filtering %s, ID %u",
279               (void *)hash_rxq,
280               (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5],
281               mac_index,
282               vlan_index,
283               (vlan_enabled ? "enabled" : "disabled"),
284               vlan_id);
285         /* Create related flow. */
286         errno = 0;
287         flow = ibv_exp_create_flow(hash_rxq->qp, attr);
288         if (flow == NULL) {
289                 /* It's not clear whether errno is always set in this case. */
290                 ERROR("%p: flow configuration failed, errno=%d: %s",
291                       (void *)hash_rxq, errno,
292                       (errno ? strerror(errno) : "Unknown error"));
293                 if (errno)
294                         return errno;
295                 return EINVAL;
296         }
297         hash_rxq->mac_flow[mac_index][vlan_index] = flow;
298         return 0;
299 }
300
301 /**
302  * Register a MAC address in a hash RX queue.
303  *
304  * @param hash_rxq
305  *   Pointer to hash RX queue structure.
306  * @param mac_index
307  *   MAC address index to register.
308  *
309  * @return
310  *   0 on success, errno value on failure.
311  */
312 static int
313 hash_rxq_mac_addr_add(struct hash_rxq *hash_rxq, unsigned int mac_index)
314 {
315         struct priv *priv = hash_rxq->priv;
316         unsigned int i = 0;
317         int ret;
318
319         assert(mac_index < RTE_DIM(hash_rxq->mac_flow));
320         assert(RTE_DIM(hash_rxq->mac_flow[mac_index]) ==
321                RTE_DIM(priv->vlan_filter));
322         /* Add a MAC address for each VLAN filter, or at least once. */
323         do {
324                 ret = hash_rxq_add_mac_flow(hash_rxq, mac_index, i);
325                 if (ret) {
326                         /* Failure, rollback. */
327                         while (i != 0)
328                                 hash_rxq_del_mac_flow(hash_rxq, mac_index,
329                                                       --i);
330                         return ret;
331                 }
332         } while (++i < priv->vlan_filter_n);
333         return 0;
334 }
335
336 /**
337  * Register all MAC addresses in a hash RX queue.
338  *
339  * @param hash_rxq
340  *   Pointer to hash RX queue structure.
341  *
342  * @return
343  *   0 on success, errno value on failure.
344  */
345 int
346 hash_rxq_mac_addrs_add(struct hash_rxq *hash_rxq)
347 {
348         struct priv *priv = hash_rxq->priv;
349         unsigned int i;
350         int ret;
351
352         assert(RTE_DIM(priv->mac) == RTE_DIM(hash_rxq->mac_flow));
353         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
354                 if (!BITFIELD_ISSET(priv->mac_configured, i))
355                         continue;
356                 ret = hash_rxq_mac_addr_add(hash_rxq, i);
357                 if (!ret)
358                         continue;
359                 /* Failure, rollback. */
360                 while (i != 0)
361                         hash_rxq_mac_addr_del(hash_rxq, --i);
362                 assert(ret > 0);
363                 return ret;
364         }
365         return 0;
366 }
367
368 /**
369  * Register a MAC address.
370  *
371  * This is done for each hash RX queue.
372  *
373  * @param priv
374  *   Pointer to private structure.
375  * @param mac_index
376  *   MAC address index to use.
377  * @param mac
378  *   MAC address to register.
379  *
380  * @return
381  *   0 on success, errno value on failure.
382  */
383 int
384 priv_mac_addr_add(struct priv *priv, unsigned int mac_index,
385                   const uint8_t (*mac)[ETHER_ADDR_LEN])
386 {
387         unsigned int i;
388         int ret;
389
390         assert(mac_index < RTE_DIM(priv->mac));
391         /* First, make sure this address isn't already configured. */
392         for (i = 0; (i != RTE_DIM(priv->mac)); ++i) {
393                 /* Skip this index, it's going to be reconfigured. */
394                 if (i == mac_index)
395                         continue;
396                 if (!BITFIELD_ISSET(priv->mac_configured, i))
397                         continue;
398                 if (memcmp(priv->mac[i].addr_bytes, *mac, sizeof(*mac)))
399                         continue;
400                 /* Address already configured elsewhere, return with error. */
401                 return EADDRINUSE;
402         }
403         if (BITFIELD_ISSET(priv->mac_configured, mac_index))
404                 priv_mac_addr_del(priv, mac_index);
405         priv->mac[mac_index] = (struct ether_addr){
406                 {
407                         (*mac)[0], (*mac)[1], (*mac)[2],
408                         (*mac)[3], (*mac)[4], (*mac)[5]
409                 }
410         };
411         if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
412                 goto end;
413         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
414                 ret = hash_rxq_mac_addr_add(&(*priv->hash_rxqs)[i], mac_index);
415                 if (!ret)
416                         continue;
417                 /* Failure, rollback. */
418                 while (i != 0)
419                         hash_rxq_mac_addr_del(&(*priv->hash_rxqs)[--i],
420                                               mac_index);
421                 return ret;
422         }
423 end:
424         BITFIELD_SET(priv->mac_configured, mac_index);
425         return 0;
426 }
427
428 /**
429  * Register all MAC addresses in all hash RX queues.
430  *
431  * @param priv
432  *   Pointer to private structure.
433  *
434  * @return
435  *   0 on success, errno value on failure.
436  */
437 int
438 priv_mac_addrs_enable(struct priv *priv)
439 {
440         unsigned int i;
441         int ret;
442
443         if (priv->isolated)
444                 return 0;
445         if (!priv_allow_flow_type(priv, HASH_RXQ_FLOW_TYPE_MAC))
446                 return 0;
447         for (i = 0; (i != priv->hash_rxqs_n); ++i) {
448                 ret = hash_rxq_mac_addrs_add(&(*priv->hash_rxqs)[i]);
449                 if (!ret)
450                         continue;
451                 /* Failure, rollback. */
452                 while (i != 0)
453                         hash_rxq_mac_addrs_del(&(*priv->hash_rxqs)[--i]);
454                 assert(ret > 0);
455                 return ret;
456         }
457         return 0;
458 }
459
460 /**
461  * DPDK callback to add a MAC address.
462  *
463  * @param dev
464  *   Pointer to Ethernet device structure.
465  * @param mac_addr
466  *   MAC address to register.
467  * @param index
468  *   MAC address index.
469  * @param vmdq
470  *   VMDq pool index to associate address with (ignored).
471  */
472 int
473 mlx5_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
474                   uint32_t index, uint32_t vmdq)
475 {
476         struct priv *priv = dev->data->dev_private;
477         int re;
478
479         if (mlx5_is_secondary())
480                 return -ENOTSUP;
481
482         (void)vmdq;
483         priv_lock(priv);
484         DEBUG("%p: adding MAC address at index %" PRIu32,
485               (void *)dev, index);
486         if (index >= RTE_DIM(priv->mac)) {
487                 re = EINVAL;
488                 goto end;
489         }
490         re = priv_mac_addr_add(priv, index,
491                                (const uint8_t (*)[ETHER_ADDR_LEN])
492                                mac_addr->addr_bytes);
493 end:
494         priv_unlock(priv);
495         return -re;
496 }
497
498 /**
499  * DPDK callback to set primary MAC address.
500  *
501  * @param dev
502  *   Pointer to Ethernet device structure.
503  * @param mac_addr
504  *   MAC address to register.
505  */
506 void
507 mlx5_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
508 {
509         DEBUG("%p: setting primary MAC address", (void *)dev);
510         mlx5_mac_addr_remove(dev, 0);
511         mlx5_mac_addr_add(dev, mac_addr, 0, 0);
512 }