]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/sfxge/common/efx_mac.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / sfxge / common / efx_mac.c
1 /*-
2  * Copyright (c) 2007-2015 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efsys.h"
35 #include "efx.h"
36 #include "efx_types.h"
37 #include "efx_impl.h"
38
39 #if EFSYS_OPT_MAC_FALCON_GMAC
40 #include "falcon_gmac.h"
41 #endif
42
43 #if EFSYS_OPT_MAC_FALCON_XMAC
44 #include "falcon_xmac.h"
45 #endif
46
47 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
48
49 static  __checkReturn   int
50 falconsiena_mac_multicast_list_set(
51         __in                            efx_nic_t *enp);
52
53 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
54
55 #if EFSYS_OPT_MAC_FALCON_GMAC
56 static efx_mac_ops_t    __efx_falcon_gmac_ops = {
57         falcon_gmac_reset,                      /* emo_reset */
58         falcon_mac_poll,                        /* emo_poll */
59         falcon_mac_up,                          /* emo_up */
60         falcon_gmac_reconfigure,                /* emo_addr_set */
61         falcon_gmac_reconfigure,                /* emo_reconfigure */
62         falconsiena_mac_multicast_list_set,     /* emo_multicast_list_set */
63         NULL,                                   /* emo_filter_set_default_rxq */
64         NULL,                           /* emo_filter_default_rxq_clear */
65 #if EFSYS_OPT_LOOPBACK
66         falcon_mac_loopback_set,                /* emo_loopback_set */
67 #endif  /* EFSYS_OPT_LOOPBACK */
68 #if EFSYS_OPT_MAC_STATS
69         falcon_mac_stats_upload,                /* emo_stats_upload */
70         NULL,                                   /* emo_stats_periodic */
71         falcon_gmac_stats_update                /* emo_stats_update */
72 #endif  /* EFSYS_OPT_MAC_STATS */
73 };
74 #endif  /* EFSYS_OPT_MAC_FALCON_GMAC */
75
76 #if EFSYS_OPT_MAC_FALCON_XMAC
77 static efx_mac_ops_t    __efx_falcon_xmac_ops = {
78         falcon_xmac_reset,                      /* emo_reset */
79         falcon_mac_poll,                        /* emo_poll */
80         falcon_mac_up,                          /* emo_up */
81         falcon_xmac_reconfigure,                /* emo_addr_set */
82         falcon_xmac_reconfigure,                /* emo_reconfigure */
83         falconsiena_mac_multicast_list_set,     /* emo_multicast_list_set */
84         NULL,                                   /* emo_filter_set_default_rxq */
85         NULL,                           /* emo_filter_default_rxq_clear */
86 #if EFSYS_OPT_LOOPBACK
87         falcon_mac_loopback_set,                /* emo_loopback_set */
88 #endif  /* EFSYS_OPT_LOOPBACK */
89 #if EFSYS_OPT_MAC_STATS
90         falcon_mac_stats_upload,                /* emo_stats_upload */
91         NULL,                                   /* emo_stats_periodic */
92         falcon_xmac_stats_update                /* emo_stats_update */
93 #endif  /* EFSYS_OPT_MAC_STATS */
94 };
95 #endif  /* EFSYS_OPT_MAC_FALCON_XMAC */
96
97 #if EFSYS_OPT_SIENA
98 static efx_mac_ops_t    __efx_siena_mac_ops = {
99         NULL,                                   /* emo_reset */
100         siena_mac_poll,                         /* emo_poll */
101         siena_mac_up,                           /* emo_up */
102         siena_mac_reconfigure,                  /* emo_addr_set */
103         siena_mac_reconfigure,                  /* emo_reconfigure */
104         falconsiena_mac_multicast_list_set,     /* emo_multicast_list_set */
105         NULL,                                   /* emo_filter_set_default_rxq */
106         NULL,                           /* emo_filter_default_rxq_clear */
107 #if EFSYS_OPT_LOOPBACK
108         siena_mac_loopback_set,                 /* emo_loopback_set */
109 #endif  /* EFSYS_OPT_LOOPBACK */
110 #if EFSYS_OPT_MAC_STATS
111         efx_mcdi_mac_stats_upload,              /* emo_stats_upload */
112         efx_mcdi_mac_stats_periodic,            /* emo_stats_periodic */
113         siena_mac_stats_update                  /* emo_stats_update */
114 #endif  /* EFSYS_OPT_MAC_STATS */
115 };
116 #endif  /* EFSYS_OPT_SIENA */
117
118 #if EFSYS_OPT_HUNTINGTON
119 static efx_mac_ops_t    __efx_hunt_mac_ops = {
120         NULL,                                   /* emo_reset */
121         hunt_mac_poll,                          /* emo_poll */
122         hunt_mac_up,                            /* emo_up */
123         hunt_mac_addr_set,                      /* emo_addr_set */
124         hunt_mac_reconfigure,                   /* emo_reconfigure */
125         hunt_mac_multicast_list_set,            /* emo_multicast_list_set */
126         hunt_mac_filter_default_rxq_set,        /* emo_filter_default_rxq_set */
127         hunt_mac_filter_default_rxq_clear,
128                                         /* emo_filter_default_rxq_clear */
129 #if EFSYS_OPT_LOOPBACK
130         hunt_mac_loopback_set,                  /* emo_loopback_set */
131 #endif  /* EFSYS_OPT_LOOPBACK */
132 #if EFSYS_OPT_MAC_STATS
133         efx_mcdi_mac_stats_upload,              /* emo_stats_upload */
134         efx_mcdi_mac_stats_periodic,            /* emo_stats_periodic */
135         hunt_mac_stats_update                   /* emo_stats_update */
136 #endif  /* EFSYS_OPT_MAC_STATS */
137 };
138 #endif  /* EFSYS_OPT_HUNTINGTON */
139
140 static efx_mac_ops_t    *__efx_mac_ops[] = {
141         /* [EFX_MAC_INVALID] */
142         NULL,
143         /* [EFX_MAC_FALCON_GMAC] */
144 #if EFSYS_OPT_MAC_FALCON_GMAC
145         &__efx_falcon_gmac_ops,
146 #else
147         NULL,
148 #endif
149         /* [EFX_MAC_FALCON_XMAC] */
150 #if EFSYS_OPT_MAC_FALCON_XMAC
151         &__efx_falcon_xmac_ops,
152 #else
153         NULL,
154 #endif
155         /* [EFX_MAC_SIENA] */
156 #if EFSYS_OPT_SIENA
157         &__efx_siena_mac_ops,
158 #else
159         NULL,
160 #endif
161         /* [EFX_MAC_HUNTINGTON] */
162 #if EFSYS_OPT_HUNTINGTON
163         &__efx_hunt_mac_ops,
164 #else
165         NULL,
166 #endif
167 };
168
169         __checkReturn                   int
170 efx_mac_pdu_set(
171         __in                            efx_nic_t *enp,
172         __in                            size_t pdu)
173 {
174         efx_port_t *epp = &(enp->en_port);
175         efx_mac_ops_t *emop = epp->ep_emop;
176         uint32_t old_pdu;
177         int rc;
178
179         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
180         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
181         EFSYS_ASSERT(emop != NULL);
182
183         if (pdu < EFX_MAC_PDU_MIN) {
184                 rc = EINVAL;
185                 goto fail1;
186         }
187
188         if (pdu > EFX_MAC_PDU_MAX) {
189                 rc = EINVAL;
190                 goto fail2;
191         }
192
193         old_pdu = epp->ep_mac_pdu;
194         epp->ep_mac_pdu = (uint32_t)pdu;
195         if ((rc = emop->emo_reconfigure(enp)) != 0)
196                 goto fail3;
197
198         return (0);
199
200 fail3:
201         EFSYS_PROBE(fail3);
202
203         epp->ep_mac_pdu = old_pdu;
204
205 fail2:
206         EFSYS_PROBE(fail2);
207 fail1:
208         EFSYS_PROBE1(fail1, int, rc);
209
210         return (rc);
211 }
212
213         __checkReturn                   int
214 efx_mac_addr_set(
215         __in                            efx_nic_t *enp,
216         __in                            uint8_t *addr)
217 {
218         efx_port_t *epp = &(enp->en_port);
219         efx_mac_ops_t *emop = epp->ep_emop;
220         uint8_t old_addr[6];
221         uint32_t oui;
222         int rc;
223
224         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
226
227         if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
228                 rc = EINVAL;
229                 goto fail1;
230         }
231
232         oui = addr[0] << 16 | addr[1] << 8 | addr[2];
233         if (oui == 0x000000) {
234                 rc = EINVAL;
235                 goto fail2;
236         }
237
238         EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
239         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
240         if ((rc = emop->emo_addr_set(enp)) != 0)
241                 goto fail3;
242
243         return (0);
244
245 fail3:
246         EFSYS_PROBE(fail3);
247
248         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
249
250 fail2:
251         EFSYS_PROBE(fail2);
252 fail1:
253         EFSYS_PROBE1(fail1, int, rc);
254
255         return (rc);
256 }
257
258         __checkReturn                   int
259 efx_mac_filter_set(
260         __in                            efx_nic_t *enp,
261         __in                            boolean_t all_unicst,
262         __in                            boolean_t mulcst,
263         __in                            boolean_t all_mulcst,
264         __in                            boolean_t brdcst)
265 {
266         efx_port_t *epp = &(enp->en_port);
267         efx_mac_ops_t *emop = epp->ep_emop;
268         boolean_t old_all_unicst;
269         boolean_t old_mulcst;
270         boolean_t old_all_mulcst;
271         boolean_t old_brdcst;
272         int rc;
273
274         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
275         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
276
277         old_all_unicst = epp->ep_all_unicst;
278         old_mulcst = epp->ep_mulcst;
279         old_all_mulcst = epp->ep_all_mulcst;
280         old_brdcst = epp->ep_brdcst;
281
282         epp->ep_all_unicst = all_unicst;
283         epp->ep_mulcst = mulcst;
284         epp->ep_all_mulcst = all_mulcst;
285         epp->ep_brdcst = brdcst;
286
287         if ((rc = emop->emo_reconfigure(enp)) != 0)
288                 goto fail1;
289
290         return (0);
291
292 fail1:
293         EFSYS_PROBE1(fail1, int, rc);
294
295         epp->ep_all_unicst = old_all_unicst;
296         epp->ep_mulcst = old_mulcst;
297         epp->ep_all_mulcst = old_all_mulcst;
298         epp->ep_brdcst = old_brdcst;
299
300         return (rc);
301 }
302
303         __checkReturn                   int
304 efx_mac_drain(
305         __in                            efx_nic_t *enp,
306         __in                            boolean_t enabled)
307 {
308         efx_port_t *epp = &(enp->en_port);
309         efx_mac_ops_t *emop = epp->ep_emop;
310         int rc;
311
312         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
314         EFSYS_ASSERT(emop != NULL);
315
316         if (epp->ep_mac_drain == enabled)
317                 return (0);
318
319         epp->ep_mac_drain = enabled;
320
321         if (enabled && emop->emo_reset != NULL) {
322                 if ((rc = emop->emo_reset(enp)) != 0)
323                         goto fail1;
324
325                 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
326                 enp->en_reset_flags &= ~EFX_RESET_PHY;
327         }
328
329         if ((rc = emop->emo_reconfigure(enp)) != 0)
330                 goto fail2;
331
332         return (0);
333
334 fail2:
335         EFSYS_PROBE(fail2);
336 fail1:
337         EFSYS_PROBE1(fail1, int, rc);
338
339         return (rc);
340 }
341
342         __checkReturn   int
343 efx_mac_up(
344         __in            efx_nic_t *enp,
345         __out           boolean_t *mac_upp)
346 {
347         efx_port_t *epp = &(enp->en_port);
348         efx_mac_ops_t *emop = epp->ep_emop;
349         int rc;
350
351         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
352         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
353
354         if ((rc = emop->emo_up(enp, mac_upp)) != 0)
355                 goto fail1;
356
357         return (0);
358
359 fail1:
360         EFSYS_PROBE1(fail1, int, rc);
361
362         return (rc);
363 }
364
365         __checkReturn                   int
366 efx_mac_fcntl_set(
367         __in                            efx_nic_t *enp,
368         __in                            unsigned int fcntl,
369         __in                            boolean_t autoneg)
370 {
371         efx_port_t *epp = &(enp->en_port);
372         efx_mac_ops_t *emop = epp->ep_emop;
373         efx_phy_ops_t *epop = epp->ep_epop;
374         unsigned int old_fcntl;
375         boolean_t old_autoneg;
376         unsigned int old_adv_cap;
377         int rc;
378
379         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
380         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
381
382         if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
383                 rc = EINVAL;
384                 goto fail1;
385         }
386
387         /*
388          * Ignore a request to set flow control auto-negotiation
389          * if the PHY doesn't support it.
390          */
391         if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
392                 autoneg = B_FALSE;
393
394         old_fcntl = epp->ep_fcntl;
395         old_autoneg = epp->ep_fcntl_autoneg;
396         old_adv_cap = epp->ep_adv_cap_mask;
397
398         epp->ep_fcntl = fcntl;
399         epp->ep_fcntl_autoneg = autoneg;
400
401         /*
402          * Always encode the flow control settings in the advertised
403          * capabilities even if we are not trying to auto-negotiate
404          * them and reconfigure both the PHY and the MAC.
405          */
406         if (fcntl & EFX_FCNTL_RESPOND)
407                 epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
408                                             1 << EFX_PHY_CAP_ASYM);
409         else
410                 epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
411                                             1 << EFX_PHY_CAP_ASYM);
412
413         if (fcntl & EFX_FCNTL_GENERATE)
414                 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
415
416         if ((rc = epop->epo_reconfigure(enp)) != 0)
417                 goto fail2;
418
419         if ((rc = emop->emo_reconfigure(enp)) != 0)
420                 goto fail3;
421
422         return (0);
423
424 fail3:
425         EFSYS_PROBE(fail3);
426
427 fail2:
428         EFSYS_PROBE(fail2);
429
430         epp->ep_fcntl = old_fcntl;
431         epp->ep_fcntl_autoneg = old_autoneg;
432         epp->ep_adv_cap_mask = old_adv_cap;
433
434 fail1:
435         EFSYS_PROBE1(fail1, int, rc);
436
437         return (rc);
438 }
439
440                         void
441 efx_mac_fcntl_get(
442         __in            efx_nic_t *enp,
443         __out           unsigned int *fcntl_wantedp,
444         __out           unsigned int *fcntl_linkp)
445 {
446         efx_port_t *epp = &(enp->en_port);
447         unsigned int wanted = 0;
448
449         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
450         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
451
452         /*
453          * Decode the requested flow control settings from the PHY
454          * advertised capabilities.
455          */
456         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
457                 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
458         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
459                 wanted ^= EFX_FCNTL_GENERATE;
460
461         *fcntl_linkp = epp->ep_fcntl;
462         *fcntl_wantedp = wanted;
463 }
464
465 /*
466  * FIXME: efx_mac_hash_set() should be deleted once all its callers have been
467  * updated to use efx_mac_multicast_list_set().
468  * Then efx_port_t.ep_multicst_hash could be made Falcon/Siena specific as
469  * well.
470  */
471         __checkReturn                   int
472 efx_mac_hash_set(
473         __in                            efx_nic_t *enp,
474         __in_ecount(EFX_MAC_HASH_BITS)  unsigned int const *bucket)
475 {
476         efx_port_t *epp = &(enp->en_port);
477         efx_mac_ops_t *emop = epp->ep_emop;
478         efx_oword_t old_hash[2];
479         unsigned int index;
480         int rc;
481
482         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
483         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
484
485         memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
486
487         /* Set the lower 128 bits of the hash */
488         EFX_ZERO_OWORD(epp->ep_multicst_hash[0]);
489         for (index = 0; index < 128; index++) {
490                 if (bucket[index] != 0)
491                         EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index);
492         }
493
494         /* Set the upper 128 bits of the hash */
495         EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
496         for (index = 0; index < 128; index++) {
497                 if (bucket[index + 128] != 0)
498                         EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index);
499         }
500
501         if ((rc = emop->emo_reconfigure(enp)) != 0)
502                 goto fail1;
503
504         return (0);
505
506 fail1:
507         EFSYS_PROBE1(fail1, int, rc);
508
509         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
510
511         return (rc);
512 }
513
514         __checkReturn   int
515 efx_mac_multicast_list_set(
516         __in                            efx_nic_t *enp,
517         __in_ecount(6*count)            uint8_t const *addrs,
518         __in                            int count)
519 {
520         efx_port_t *epp = &(enp->en_port);
521         efx_mac_ops_t *emop = epp->ep_emop;
522         uint8_t *old_mulcst_addr_list = NULL;
523         uint32_t old_mulcst_addr_count;
524         int rc;
525
526         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
527         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
528
529         if (count > EFX_MAC_MULTICAST_LIST_MAX) {
530                 rc = EINVAL;
531                 goto fail1;
532         }
533
534         old_mulcst_addr_count = epp->ep_mulcst_addr_count;
535         if (old_mulcst_addr_count > 0) {
536                 /* Allocate memory to store old list (instead of using stack) */
537                 EFSYS_KMEM_ALLOC(enp->en_esip,
538                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
539                                 old_mulcst_addr_list);
540                 if (old_mulcst_addr_list == NULL) {
541                         rc = ENOMEM;
542                         goto fail2;
543                 }
544
545                 /* Save the old list in case we need to rollback */
546                 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
547                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
548         }
549
550         /* Store the new list */
551         memcpy(epp->ep_mulcst_addr_list, addrs,
552                 count * EFX_MAC_ADDR_LEN);
553         epp->ep_mulcst_addr_count = count;
554
555         if ((rc = emop->emo_multicast_list_set(enp)) != 0)
556                 goto fail3;
557
558         if (old_mulcst_addr_count > 0) {
559                 EFSYS_KMEM_FREE(enp->en_esip,
560                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
561                                 old_mulcst_addr_list);
562         }
563
564         return (0);
565
566 fail3:
567         EFSYS_PROBE(fail3);
568
569         /* Restore original list on failure */
570         epp->ep_mulcst_addr_count = old_mulcst_addr_count;
571         if (old_mulcst_addr_count > 0) {
572                 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
573                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
574
575                 EFSYS_KMEM_FREE(enp->en_esip,
576                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
577                                 old_mulcst_addr_list);
578         }
579
580 fail2:
581         EFSYS_PROBE(fail2);
582
583 fail1:
584         EFSYS_PROBE1(fail1, int, rc);
585
586         return (rc);
587
588 }
589
590         __checkReturn   int
591 efx_mac_filter_default_rxq_set(
592         __in            efx_nic_t *enp,
593         __in            efx_rxq_t *erp,
594         __in            boolean_t using_rss)
595 {
596         efx_port_t *epp = &(enp->en_port);
597         efx_mac_ops_t *emop = epp->ep_emop;
598         int rc;
599
600         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
601         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
602
603         if (emop->emo_filter_default_rxq_set != NULL) {
604                 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
605                 if (rc != 0)
606                         goto fail1;
607         }
608
609         return (0);
610
611 fail1:
612         EFSYS_PROBE1(fail1, int, rc);
613
614         return (rc);
615 }
616
617                         void
618 efx_mac_filter_default_rxq_clear(
619         __in            efx_nic_t *enp)
620 {
621         efx_port_t *epp = &(enp->en_port);
622         efx_mac_ops_t *emop = epp->ep_emop;
623
624         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
625         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
626
627         if (emop->emo_filter_default_rxq_clear != NULL)
628                 emop->emo_filter_default_rxq_clear(enp);
629 }
630
631
632 #if EFSYS_OPT_MAC_STATS
633
634 #if EFSYS_OPT_NAMES
635
636 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
637 static const char       *__efx_mac_stat_name[] = {
638         "rx_octets",
639         "rx_pkts",
640         "rx_unicst_pkts",
641         "rx_multicst_pkts",
642         "rx_brdcst_pkts",
643         "rx_pause_pkts",
644         "rx_le_64_pkts",
645         "rx_65_to_127_pkts",
646         "rx_128_to_255_pkts",
647         "rx_256_to_511_pkts",
648         "rx_512_to_1023_pkts",
649         "rx_1024_to_15xx_pkts",
650         "rx_ge_15xx_pkts",
651         "rx_errors",
652         "rx_fcs_errors",
653         "rx_drop_events",
654         "rx_false_carrier_errors",
655         "rx_symbol_errors",
656         "rx_align_errors",
657         "rx_internal_errors",
658         "rx_jabber_pkts",
659         "rx_lane0_char_err",
660         "rx_lane1_char_err",
661         "rx_lane2_char_err",
662         "rx_lane3_char_err",
663         "rx_lane0_disp_err",
664         "rx_lane1_disp_err",
665         "rx_lane2_disp_err",
666         "rx_lane3_disp_err",
667         "rx_match_fault",
668         "rx_nodesc_drop_cnt",
669         "tx_octets",
670         "tx_pkts",
671         "tx_unicst_pkts",
672         "tx_multicst_pkts",
673         "tx_brdcst_pkts",
674         "tx_pause_pkts",
675         "tx_le_64_pkts",
676         "tx_65_to_127_pkts",
677         "tx_128_to_255_pkts",
678         "tx_256_to_511_pkts",
679         "tx_512_to_1023_pkts",
680         "tx_1024_to_15xx_pkts",
681         "tx_ge_15xx_pkts",
682         "tx_errors",
683         "tx_sgl_col_pkts",
684         "tx_mult_col_pkts",
685         "tx_ex_col_pkts",
686         "tx_late_col_pkts",
687         "tx_def_pkts",
688         "tx_ex_def_pkts",
689         "pm_trunc_bb_overflow",
690         "pm_discard_bb_overflow",
691         "pm_trunc_vfifo_full",
692         "pm_discard_vfifo_full",
693         "pm_trunc_qbb",
694         "pm_discard_qbb",
695         "pm_discard_mapping",
696         "rxdp_q_disabled_pkts",
697         "rxdp_di_dropped_pkts",
698         "rxdp_streaming_pkts",
699         "rxdp_hlb_fetch",
700         "rxdp_hlb_wait",
701         "vadapter_rx_unicast_packets",
702         "vadapter_rx_unicast_bytes",
703         "vadapter_rx_multicast_packets",
704         "vadapter_rx_multicast_bytes",
705         "vadapter_rx_broadcast_packets",
706         "vadapter_rx_broadcast_bytes",
707         "vadapter_rx_bad_packets",
708         "vadapter_rx_bad_bytes",
709         "vadapter_rx_overflow",
710         "vadapter_tx_unicast_packets",
711         "vadapter_tx_unicast_bytes",
712         "vadapter_tx_multicast_packets",
713         "vadapter_tx_multicast_bytes",
714         "vadapter_tx_broadcast_packets",
715         "vadapter_tx_broadcast_bytes",
716         "vadapter_tx_bad_packets",
717         "vadapter_tx_bad_bytes",
718         "vadapter_tx_overflow",
719 };
720 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
721
722         __checkReturn                   const char *
723 efx_mac_stat_name(
724         __in                            efx_nic_t *enp,
725         __in                            unsigned int id)
726 {
727         _NOTE(ARGUNUSED(enp))
728         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
729
730         EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
731         return (__efx_mac_stat_name[id]);
732 }
733
734 #endif  /* EFSYS_OPT_NAMES */
735
736         __checkReturn                   int
737 efx_mac_stats_upload(
738         __in                            efx_nic_t *enp,
739         __in                            efsys_mem_t *esmp)
740 {
741         efx_port_t *epp = &(enp->en_port);
742         efx_mac_ops_t *emop = epp->ep_emop;
743         int rc;
744
745         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
746         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
747         EFSYS_ASSERT(emop != NULL);
748
749         /*
750          * Don't assert !ep_mac_stats_pending, because the client might
751          * have failed to finalise statistics when previously stopping
752          * the port.
753          */
754         if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
755                 goto fail1;
756
757         epp->ep_mac_stats_pending = B_TRUE;
758
759         return (0);
760
761 fail1:
762         EFSYS_PROBE1(fail1, int, rc);
763
764         return (rc);
765 }
766
767         __checkReturn                   int
768 efx_mac_stats_periodic(
769         __in                            efx_nic_t *enp,
770         __in                            efsys_mem_t *esmp,
771         __in                            uint16_t period_ms,
772         __in                            boolean_t events)
773 {
774         efx_port_t *epp = &(enp->en_port);
775         efx_mac_ops_t *emop = epp->ep_emop;
776         int rc;
777
778         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
779         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
780
781         EFSYS_ASSERT(emop != NULL);
782
783         if (emop->emo_stats_periodic == NULL) {
784                 rc = EINVAL;
785                 goto fail1;
786         }
787
788         if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
789                 goto fail2;
790
791         return (0);
792
793 fail2:
794         EFSYS_PROBE(fail2);
795 fail1:
796         EFSYS_PROBE1(fail1, int, rc);
797
798         return (rc);
799 }
800
801
802         __checkReturn                   int
803 efx_mac_stats_update(
804         __in                            efx_nic_t *enp,
805         __in                            efsys_mem_t *esmp,
806         __inout_ecount(EFX_MAC_NSTATS)  efsys_stat_t *essp,
807         __out_opt                       uint32_t *generationp)
808 {
809         efx_port_t *epp = &(enp->en_port);
810         efx_mac_ops_t *emop = epp->ep_emop;
811         int rc;
812
813         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
814         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
815         EFSYS_ASSERT(emop != NULL);
816
817         rc = emop->emo_stats_update(enp, esmp, essp, generationp);
818         if (rc == 0)
819                 epp->ep_mac_stats_pending = B_FALSE;
820
821         return (rc);
822 }
823
824 #endif  /* EFSYS_OPT_MAC_STATS */
825
826         __checkReturn                   int
827 efx_mac_select(
828         __in                            efx_nic_t *enp)
829 {
830         efx_port_t *epp = &(enp->en_port);
831         efx_mac_type_t type = EFX_MAC_INVALID;
832         efx_mac_ops_t *emop;
833         int rc = EINVAL;
834
835 #if EFSYS_OPT_HUNTINGTON
836         if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
837                 type = EFX_MAC_HUNTINGTON;
838                 goto chosen;
839         }
840 #endif
841
842 #if EFSYS_OPT_SIENA
843         if (enp->en_family == EFX_FAMILY_SIENA) {
844                 type = EFX_MAC_SIENA;
845                 goto chosen;
846         }
847 #endif
848
849 #if EFSYS_OPT_FALCON
850         switch (epp->ep_link_mode) {
851 #if EFSYS_OPT_MAC_FALCON_GMAC
852         case EFX_LINK_100HDX:
853         case EFX_LINK_100FDX:
854         case EFX_LINK_1000HDX:
855         case EFX_LINK_1000FDX:
856                 type = EFX_MAC_FALCON_GMAC;
857                 goto chosen;
858 #endif  /* EFSYS_OPT_FALCON_GMAC */
859
860 #if EFSYS_OPT_MAC_FALCON_XMAC
861         case EFX_LINK_10000FDX:
862                 type = EFX_MAC_FALCON_XMAC;
863                 goto chosen;
864 #endif  /* EFSYS_OPT_FALCON_XMAC */
865
866         default:
867 #if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
868                 /* Only initialise a MAC supported by the PHY */
869                 if (epp->ep_phy_cap_mask &
870                     ((1 << EFX_PHY_CAP_1000FDX) |
871                     (1 << EFX_PHY_CAP_1000HDX) |
872                     (1 << EFX_PHY_CAP_100FDX) |
873                     (1 << EFX_PHY_CAP_100HDX) |
874                     (1 << EFX_PHY_CAP_10FDX) |
875                     (1 << EFX_PHY_CAP_10FDX)))
876                         type = EFX_MAC_FALCON_GMAC;
877                 else
878                         type = EFX_MAC_FALCON_XMAC;
879 #elif EFSYS_OPT_MAC_FALCON_GMAC
880                 type = EFX_MAC_FALCON_GMAC;
881 #else
882                 type = EFX_MAC_FALCON_XMAC;
883 #endif
884                 goto chosen;
885         }
886 #endif  /* EFSYS_OPT_FALCON */
887
888 chosen:
889         EFSYS_ASSERT(type != EFX_MAC_INVALID);
890         EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
891         emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
892         EFSYS_ASSERT(emop != NULL);
893
894         epp->ep_mac_type = type;
895
896         if (emop->emo_reset != NULL) {
897                 if ((rc = emop->emo_reset(enp)) != 0)
898                         goto fail1;
899
900                 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
901                 enp->en_reset_flags &= ~EFX_RESET_MAC;
902         }
903
904         return (0);
905
906 fail1:
907         EFSYS_PROBE1(fail1, int, rc);
908
909         return (rc);
910 }
911
912
913 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
914
915 /* Compute the multicast hash as used on Falcon and Siena. */
916 static  void
917 falconsiena_mac_multicast_hash_compute(
918         __in_ecount(6*count)            uint8_t const *addrs,
919         __in                            int count,
920         __out                           efx_oword_t *hash_low,
921         __out                           efx_oword_t *hash_high)
922 {
923         uint32_t crc, index;
924         int i;
925
926         EFSYS_ASSERT(hash_low != NULL);
927         EFSYS_ASSERT(hash_high != NULL);
928
929         EFX_ZERO_OWORD(*hash_low);
930         EFX_ZERO_OWORD(*hash_high);
931
932         for (i = 0; i < count; i++) {
933                 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
934                 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
935                 index = crc % EFX_MAC_HASH_BITS;
936                 if (index < 128) {
937                         EFX_SET_OWORD_BIT(*hash_low, index);
938                 } else {
939                         EFX_SET_OWORD_BIT(*hash_high, index - 128);
940                 }
941
942                 addrs += EFX_MAC_ADDR_LEN;
943         }
944 }
945
946 static  __checkReturn   int
947 falconsiena_mac_multicast_list_set(
948         __in                    efx_nic_t *enp)
949 {
950         efx_port_t *epp = &(enp->en_port);
951         efx_mac_ops_t *emop = epp->ep_emop;
952         efx_oword_t old_hash[2];
953         int rc;
954
955         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
956         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
957
958         memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
959
960         falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list,
961                                 epp->ep_mulcst_addr_count,
962                                 &epp->ep_multicst_hash[0],
963                                 &epp->ep_multicst_hash[1]);
964
965         if ((rc = emop->emo_reconfigure(enp)) != 0)
966                 goto fail1;
967
968         return (0);
969
970 fail1:
971         EFSYS_PROBE1(fail1, int, rc);
972
973         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
974
975         return (rc);
976 }
977
978 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */