]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_mac.c
sfxge(4): fix SAL annotation for input buffers
[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
520 #if EFSYS_OPT_MAC_STATS
521
522 #if EFSYS_OPT_NAMES
523
524 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 1a45a82fcfb30c1b */
525 static const char * const __efx_mac_stat_name[] = {
526         "rx_octets",
527         "rx_pkts",
528         "rx_unicst_pkts",
529         "rx_multicst_pkts",
530         "rx_brdcst_pkts",
531         "rx_pause_pkts",
532         "rx_le_64_pkts",
533         "rx_65_to_127_pkts",
534         "rx_128_to_255_pkts",
535         "rx_256_to_511_pkts",
536         "rx_512_to_1023_pkts",
537         "rx_1024_to_15xx_pkts",
538         "rx_ge_15xx_pkts",
539         "rx_errors",
540         "rx_fcs_errors",
541         "rx_drop_events",
542         "rx_false_carrier_errors",
543         "rx_symbol_errors",
544         "rx_align_errors",
545         "rx_internal_errors",
546         "rx_jabber_pkts",
547         "rx_lane0_char_err",
548         "rx_lane1_char_err",
549         "rx_lane2_char_err",
550         "rx_lane3_char_err",
551         "rx_lane0_disp_err",
552         "rx_lane1_disp_err",
553         "rx_lane2_disp_err",
554         "rx_lane3_disp_err",
555         "rx_match_fault",
556         "rx_nodesc_drop_cnt",
557         "tx_octets",
558         "tx_pkts",
559         "tx_unicst_pkts",
560         "tx_multicst_pkts",
561         "tx_brdcst_pkts",
562         "tx_pause_pkts",
563         "tx_le_64_pkts",
564         "tx_65_to_127_pkts",
565         "tx_128_to_255_pkts",
566         "tx_256_to_511_pkts",
567         "tx_512_to_1023_pkts",
568         "tx_1024_to_15xx_pkts",
569         "tx_ge_15xx_pkts",
570         "tx_errors",
571         "tx_sgl_col_pkts",
572         "tx_mult_col_pkts",
573         "tx_ex_col_pkts",
574         "tx_late_col_pkts",
575         "tx_def_pkts",
576         "tx_ex_def_pkts",
577         "pm_trunc_bb_overflow",
578         "pm_discard_bb_overflow",
579         "pm_trunc_vfifo_full",
580         "pm_discard_vfifo_full",
581         "pm_trunc_qbb",
582         "pm_discard_qbb",
583         "pm_discard_mapping",
584         "rxdp_q_disabled_pkts",
585         "rxdp_di_dropped_pkts",
586         "rxdp_streaming_pkts",
587         "rxdp_hlb_fetch",
588         "rxdp_hlb_wait",
589         "vadapter_rx_unicast_packets",
590         "vadapter_rx_unicast_bytes",
591         "vadapter_rx_multicast_packets",
592         "vadapter_rx_multicast_bytes",
593         "vadapter_rx_broadcast_packets",
594         "vadapter_rx_broadcast_bytes",
595         "vadapter_rx_bad_packets",
596         "vadapter_rx_bad_bytes",
597         "vadapter_rx_overflow",
598         "vadapter_tx_unicast_packets",
599         "vadapter_tx_unicast_bytes",
600         "vadapter_tx_multicast_packets",
601         "vadapter_tx_multicast_bytes",
602         "vadapter_tx_broadcast_packets",
603         "vadapter_tx_broadcast_bytes",
604         "vadapter_tx_bad_packets",
605         "vadapter_tx_bad_bytes",
606         "vadapter_tx_overflow",
607         "fec_uncorrected_errors",
608         "fec_corrected_errors",
609         "fec_corrected_symbols_lane0",
610         "fec_corrected_symbols_lane1",
611         "fec_corrected_symbols_lane2",
612         "fec_corrected_symbols_lane3",
613         "ctpio_vi_busy_fallback",
614         "ctpio_long_write_success",
615         "ctpio_missing_dbell_fail",
616         "ctpio_overflow_fail",
617         "ctpio_underflow_fail",
618         "ctpio_timeout_fail",
619         "ctpio_noncontig_wr_fail",
620         "ctpio_frm_clobber_fail",
621         "ctpio_invalid_wr_fail",
622         "ctpio_vi_clobber_fallback",
623         "ctpio_unqualified_fallback",
624         "ctpio_runt_fallback",
625         "ctpio_success",
626         "ctpio_fallback",
627         "ctpio_poison",
628         "ctpio_erase",
629         "rxdp_scatter_disabled_trunc",
630         "rxdp_hlb_idle",
631         "rxdp_hlb_timeout",
632 };
633 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
634
635         __checkReturn                   const char *
636 efx_mac_stat_name(
637         __in                            efx_nic_t *enp,
638         __in                            unsigned int id)
639 {
640         _NOTE(ARGUNUSED(enp))
641         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
642
643         EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
644         return (__efx_mac_stat_name[id]);
645 }
646
647 #endif  /* EFSYS_OPT_NAMES */
648
649 static                                  efx_rc_t
650 efx_mac_stats_mask_add_range(
651         __inout_bcount(mask_size)       uint32_t *maskp,
652         __in                            size_t mask_size,
653         __in                            const struct efx_mac_stats_range *rngp)
654 {
655         unsigned int mask_npages = mask_size / sizeof (*maskp);
656         unsigned int el;
657         unsigned int el_min;
658         unsigned int el_max;
659         unsigned int low;
660         unsigned int high;
661         unsigned int width;
662         efx_rc_t rc;
663
664         if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
665             (unsigned int)rngp->last) {
666                 rc = EINVAL;
667                 goto fail1;
668         }
669
670         EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
671         EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
672
673         for (el = 0; el < mask_npages; ++el) {
674                 el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
675                 el_max =
676                     el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
677                 if ((unsigned int)rngp->first > el_max ||
678                     (unsigned int)rngp->last < el_min)
679                         continue;
680                 low = MAX((unsigned int)rngp->first, el_min);
681                 high = MIN((unsigned int)rngp->last, el_max);
682                 width = high - low + 1;
683                 maskp[el] |=
684                     (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
685                     (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
686         }
687
688         return (0);
689
690 fail1:
691         EFSYS_PROBE1(fail1, efx_rc_t, rc);
692
693         return (rc);
694 }
695
696                                         efx_rc_t
697 efx_mac_stats_mask_add_ranges(
698         __inout_bcount(mask_size)       uint32_t *maskp,
699         __in                            size_t mask_size,
700         __in_ecount(rng_count)          const struct efx_mac_stats_range *rngp,
701         __in                            unsigned int rng_count)
702 {
703         unsigned int i;
704         efx_rc_t rc;
705
706         for (i = 0; i < rng_count; ++i) {
707                 if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
708                     &rngp[i])) != 0)
709                         goto fail1;
710         }
711
712         return (0);
713
714 fail1:
715         EFSYS_PROBE1(fail1, efx_rc_t, rc);
716
717         return (rc);
718 }
719
720         __checkReturn                   efx_rc_t
721 efx_mac_stats_get_mask(
722         __in                            efx_nic_t *enp,
723         __out_bcount(mask_size)         uint32_t *maskp,
724         __in                            size_t mask_size)
725 {
726         efx_port_t *epp = &(enp->en_port);
727         const efx_mac_ops_t *emop = epp->ep_emop;
728         efx_rc_t rc;
729
730         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
731         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
732         EFSYS_ASSERT(maskp != NULL);
733         EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
734
735         (void) memset(maskp, 0, mask_size);
736
737         if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
738                 goto fail1;
739
740         return (0);
741
742 fail1:
743         EFSYS_PROBE1(fail1, efx_rc_t, rc);
744
745         return (rc);
746 }
747
748         __checkReturn                   efx_rc_t
749 efx_mac_stats_clear(
750         __in                            efx_nic_t *enp)
751 {
752         efx_port_t *epp = &(enp->en_port);
753         const efx_mac_ops_t *emop = epp->ep_emop;
754         efx_rc_t rc;
755
756         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
757         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
758         EFSYS_ASSERT(emop != NULL);
759
760         if ((rc = emop->emo_stats_clear(enp)) != 0)
761                 goto fail1;
762
763         return (0);
764
765 fail1:
766         EFSYS_PROBE1(fail1, efx_rc_t, rc);
767
768         return (rc);
769 }
770
771         __checkReturn                   efx_rc_t
772 efx_mac_stats_upload(
773         __in                            efx_nic_t *enp,
774         __in                            efsys_mem_t *esmp)
775 {
776         efx_port_t *epp = &(enp->en_port);
777         const efx_mac_ops_t *emop = epp->ep_emop;
778         efx_rc_t rc;
779
780         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
781         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
782         EFSYS_ASSERT(emop != NULL);
783
784         if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
785                 goto fail1;
786
787         return (0);
788
789 fail1:
790         EFSYS_PROBE1(fail1, efx_rc_t, rc);
791
792         return (rc);
793 }
794
795         __checkReturn                   efx_rc_t
796 efx_mac_stats_periodic(
797         __in                            efx_nic_t *enp,
798         __in                            efsys_mem_t *esmp,
799         __in                            uint16_t period_ms,
800         __in                            boolean_t events)
801 {
802         efx_port_t *epp = &(enp->en_port);
803         const efx_mac_ops_t *emop = epp->ep_emop;
804         efx_rc_t rc;
805
806         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
807         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
808
809         EFSYS_ASSERT(emop != NULL);
810
811         if (emop->emo_stats_periodic == NULL) {
812                 rc = EINVAL;
813                 goto fail1;
814         }
815
816         if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
817                 goto fail2;
818
819         return (0);
820
821 fail2:
822         EFSYS_PROBE(fail2);
823 fail1:
824         EFSYS_PROBE1(fail1, efx_rc_t, rc);
825
826         return (rc);
827 }
828
829
830         __checkReturn                   efx_rc_t
831 efx_mac_stats_update(
832         __in                            efx_nic_t *enp,
833         __in                            efsys_mem_t *esmp,
834         __inout_ecount(EFX_MAC_NSTATS)  efsys_stat_t *essp,
835         __inout_opt                     uint32_t *generationp)
836 {
837         efx_port_t *epp = &(enp->en_port);
838         const efx_mac_ops_t *emop = epp->ep_emop;
839         efx_rc_t rc;
840
841         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
842         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
843         EFSYS_ASSERT(emop != NULL);
844
845         rc = emop->emo_stats_update(enp, esmp, essp, generationp);
846
847         return (rc);
848 }
849
850 #endif  /* EFSYS_OPT_MAC_STATS */
851
852         __checkReturn                   efx_rc_t
853 efx_mac_select(
854         __in                            efx_nic_t *enp)
855 {
856         efx_port_t *epp = &(enp->en_port);
857         efx_mac_type_t type = EFX_MAC_INVALID;
858         const efx_mac_ops_t *emop;
859         int rc = EINVAL;
860
861         switch (enp->en_family) {
862 #if EFSYS_OPT_SIENA
863         case EFX_FAMILY_SIENA:
864                 emop = &__efx_mac_siena_ops;
865                 type = EFX_MAC_SIENA;
866                 break;
867 #endif /* EFSYS_OPT_SIENA */
868
869 #if EFSYS_OPT_HUNTINGTON
870         case EFX_FAMILY_HUNTINGTON:
871                 emop = &__efx_mac_ef10_ops;
872                 type = EFX_MAC_HUNTINGTON;
873                 break;
874 #endif /* EFSYS_OPT_HUNTINGTON */
875
876 #if EFSYS_OPT_MEDFORD
877         case EFX_FAMILY_MEDFORD:
878                 emop = &__efx_mac_ef10_ops;
879                 type = EFX_MAC_MEDFORD;
880                 break;
881 #endif /* EFSYS_OPT_MEDFORD */
882
883 #if EFSYS_OPT_MEDFORD2
884         case EFX_FAMILY_MEDFORD2:
885                 emop = &__efx_mac_ef10_ops;
886                 type = EFX_MAC_MEDFORD2;
887                 break;
888 #endif /* EFSYS_OPT_MEDFORD2 */
889
890         default:
891                 rc = EINVAL;
892                 goto fail1;
893         }
894
895         EFSYS_ASSERT(type != EFX_MAC_INVALID);
896         EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
897         EFSYS_ASSERT(emop != NULL);
898
899         epp->ep_emop = emop;
900         epp->ep_mac_type = type;
901
902         return (0);
903
904 fail1:
905         EFSYS_PROBE1(fail1, efx_rc_t, rc);
906
907         return (rc);
908 }
909
910
911 #if EFSYS_OPT_SIENA
912
913 #define EFX_MAC_HASH_BITS       (1 << 8)
914
915 /* Compute the multicast hash as used on Falcon and Siena. */
916 static  void
917 siena_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   efx_rc_t
947 siena_mac_multicast_list_set(
948         __in            efx_nic_t *enp)
949 {
950         efx_port_t *epp = &(enp->en_port);
951         const efx_mac_ops_t *emop = epp->ep_emop;
952         efx_oword_t old_hash[2];
953         efx_rc_t 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         siena_mac_multicast_hash_compute(
961             epp->ep_mulcst_addr_list,
962             epp->ep_mulcst_addr_count,
963             &epp->ep_multicst_hash[0],
964             &epp->ep_multicst_hash[1]);
965
966         if ((rc = emop->emo_reconfigure(enp)) != 0)
967                 goto fail1;
968
969         return (0);
970
971 fail1:
972         EFSYS_PROBE1(fail1, efx_rc_t, rc);
973
974         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
975
976         return (rc);
977 }
978
979 #endif /* EFSYS_OPT_SIENA */