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