]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_mac.c
sys/dev: further adoption of SPDX licensing ID tags.
[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_siena_mac_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_upload,              /* emo_stats_upload */
64         efx_mcdi_mac_stats_periodic,            /* emo_stats_periodic */
65         siena_mac_stats_update                  /* emo_stats_update */
66 #endif  /* EFSYS_OPT_MAC_STATS */
67 };
68 #endif  /* EFSYS_OPT_SIENA */
69
70 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
71 static const efx_mac_ops_t      __efx_ef10_mac_ops = {
72         ef10_mac_poll,                          /* emo_poll */
73         ef10_mac_up,                            /* emo_up */
74         ef10_mac_addr_set,                      /* emo_addr_set */
75         ef10_mac_pdu_set,                       /* emo_pdu_set */
76         ef10_mac_pdu_get,                       /* emo_pdu_get */
77         ef10_mac_reconfigure,                   /* emo_reconfigure */
78         ef10_mac_multicast_list_set,            /* emo_multicast_list_set */
79         ef10_mac_filter_default_rxq_set,        /* emo_filter_default_rxq_set */
80         ef10_mac_filter_default_rxq_clear,
81                                         /* emo_filter_default_rxq_clear */
82 #if EFSYS_OPT_LOOPBACK
83         ef10_mac_loopback_set,                  /* emo_loopback_set */
84 #endif  /* EFSYS_OPT_LOOPBACK */
85 #if EFSYS_OPT_MAC_STATS
86         ef10_mac_stats_get_mask,                /* emo_stats_get_mask */
87         efx_mcdi_mac_stats_upload,              /* emo_stats_upload */
88         efx_mcdi_mac_stats_periodic,            /* emo_stats_periodic */
89         ef10_mac_stats_update                   /* emo_stats_update */
90 #endif  /* EFSYS_OPT_MAC_STATS */
91 };
92 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
93
94         __checkReturn                   efx_rc_t
95 efx_mac_pdu_set(
96         __in                            efx_nic_t *enp,
97         __in                            size_t pdu)
98 {
99         efx_port_t *epp = &(enp->en_port);
100         const efx_mac_ops_t *emop = epp->ep_emop;
101         uint32_t old_pdu;
102         efx_rc_t rc;
103
104         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
105         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
106         EFSYS_ASSERT(emop != NULL);
107
108         if (pdu < EFX_MAC_PDU_MIN) {
109                 rc = EINVAL;
110                 goto fail1;
111         }
112
113         if (pdu > EFX_MAC_PDU_MAX) {
114                 rc = EINVAL;
115                 goto fail2;
116         }
117
118         old_pdu = epp->ep_mac_pdu;
119         epp->ep_mac_pdu = (uint32_t)pdu;
120         if ((rc = emop->emo_pdu_set(enp)) != 0)
121                 goto fail3;
122
123         return (0);
124
125 fail3:
126         EFSYS_PROBE(fail3);
127
128         epp->ep_mac_pdu = old_pdu;
129
130 fail2:
131         EFSYS_PROBE(fail2);
132 fail1:
133         EFSYS_PROBE1(fail1, efx_rc_t, rc);
134
135         return (rc);
136 }
137
138         __checkReturn   efx_rc_t
139 efx_mac_pdu_get(
140         __in            efx_nic_t *enp,
141         __out           size_t *pdu)
142 {
143         efx_port_t *epp = &(enp->en_port);
144         const efx_mac_ops_t *emop = epp->ep_emop;
145         efx_rc_t rc;
146
147         if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
148                 goto fail1;
149
150         return (0);
151
152 fail1:
153         EFSYS_PROBE1(fail1, efx_rc_t, rc);
154
155         return (rc);
156 }
157
158         __checkReturn                   efx_rc_t
159 efx_mac_addr_set(
160         __in                            efx_nic_t *enp,
161         __in                            uint8_t *addr)
162 {
163         efx_port_t *epp = &(enp->en_port);
164         const efx_mac_ops_t *emop = epp->ep_emop;
165         uint8_t old_addr[6];
166         uint32_t oui;
167         efx_rc_t rc;
168
169         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
170         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
171
172         if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
173                 rc = EINVAL;
174                 goto fail1;
175         }
176
177         oui = addr[0] << 16 | addr[1] << 8 | addr[2];
178         if (oui == 0x000000) {
179                 rc = EINVAL;
180                 goto fail2;
181         }
182
183         EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
184         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
185         if ((rc = emop->emo_addr_set(enp)) != 0)
186                 goto fail3;
187
188         return (0);
189
190 fail3:
191         EFSYS_PROBE(fail3);
192
193         EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
194
195 fail2:
196         EFSYS_PROBE(fail2);
197 fail1:
198         EFSYS_PROBE1(fail1, efx_rc_t, rc);
199
200         return (rc);
201 }
202
203         __checkReturn                   efx_rc_t
204 efx_mac_filter_set(
205         __in                            efx_nic_t *enp,
206         __in                            boolean_t all_unicst,
207         __in                            boolean_t mulcst,
208         __in                            boolean_t all_mulcst,
209         __in                            boolean_t brdcst)
210 {
211         efx_port_t *epp = &(enp->en_port);
212         const efx_mac_ops_t *emop = epp->ep_emop;
213         boolean_t old_all_unicst;
214         boolean_t old_mulcst;
215         boolean_t old_all_mulcst;
216         boolean_t old_brdcst;
217         efx_rc_t rc;
218
219         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
220         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
221
222         old_all_unicst = epp->ep_all_unicst;
223         old_mulcst = epp->ep_mulcst;
224         old_all_mulcst = epp->ep_all_mulcst;
225         old_brdcst = epp->ep_brdcst;
226
227         epp->ep_all_unicst = all_unicst;
228         epp->ep_mulcst = mulcst;
229         epp->ep_all_mulcst = all_mulcst;
230         epp->ep_brdcst = brdcst;
231
232         if ((rc = emop->emo_reconfigure(enp)) != 0)
233                 goto fail1;
234
235         return (0);
236
237 fail1:
238         EFSYS_PROBE1(fail1, efx_rc_t, rc);
239
240         epp->ep_all_unicst = old_all_unicst;
241         epp->ep_mulcst = old_mulcst;
242         epp->ep_all_mulcst = old_all_mulcst;
243         epp->ep_brdcst = old_brdcst;
244
245         return (rc);
246 }
247
248         __checkReturn                   efx_rc_t
249 efx_mac_drain(
250         __in                            efx_nic_t *enp,
251         __in                            boolean_t enabled)
252 {
253         efx_port_t *epp = &(enp->en_port);
254         const efx_mac_ops_t *emop = epp->ep_emop;
255         efx_rc_t rc;
256
257         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
258         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
259         EFSYS_ASSERT(emop != NULL);
260
261         if (epp->ep_mac_drain == enabled)
262                 return (0);
263
264         epp->ep_mac_drain = enabled;
265
266         if ((rc = emop->emo_reconfigure(enp)) != 0)
267                 goto fail1;
268
269         return (0);
270
271 fail1:
272         EFSYS_PROBE1(fail1, efx_rc_t, rc);
273
274         return (rc);
275 }
276
277         __checkReturn   efx_rc_t
278 efx_mac_up(
279         __in            efx_nic_t *enp,
280         __out           boolean_t *mac_upp)
281 {
282         efx_port_t *epp = &(enp->en_port);
283         const efx_mac_ops_t *emop = epp->ep_emop;
284         efx_rc_t rc;
285
286         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
288
289         if ((rc = emop->emo_up(enp, mac_upp)) != 0)
290                 goto fail1;
291
292         return (0);
293
294 fail1:
295         EFSYS_PROBE1(fail1, efx_rc_t, rc);
296
297         return (rc);
298 }
299
300         __checkReturn                   efx_rc_t
301 efx_mac_fcntl_set(
302         __in                            efx_nic_t *enp,
303         __in                            unsigned int fcntl,
304         __in                            boolean_t autoneg)
305 {
306         efx_port_t *epp = &(enp->en_port);
307         const efx_mac_ops_t *emop = epp->ep_emop;
308         const efx_phy_ops_t *epop = epp->ep_epop;
309         unsigned int old_fcntl;
310         boolean_t old_autoneg;
311         unsigned int old_adv_cap;
312         efx_rc_t rc;
313
314         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
315         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
316
317         if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
318                 rc = EINVAL;
319                 goto fail1;
320         }
321
322         /*
323          * Ignore a request to set flow control auto-negotiation
324          * if the PHY doesn't support it.
325          */
326         if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
327                 autoneg = B_FALSE;
328
329         old_fcntl = epp->ep_fcntl;
330         old_autoneg = epp->ep_fcntl_autoneg;
331         old_adv_cap = epp->ep_adv_cap_mask;
332
333         epp->ep_fcntl = fcntl;
334         epp->ep_fcntl_autoneg = autoneg;
335
336         /*
337          * Always encode the flow control settings in the advertised
338          * capabilities even if we are not trying to auto-negotiate
339          * them and reconfigure both the PHY and the MAC.
340          */
341         if (fcntl & EFX_FCNTL_RESPOND)
342                 epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
343                                             1 << EFX_PHY_CAP_ASYM);
344         else
345                 epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
346                                             1 << EFX_PHY_CAP_ASYM);
347
348         if (fcntl & EFX_FCNTL_GENERATE)
349                 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
350
351         if ((rc = epop->epo_reconfigure(enp)) != 0)
352                 goto fail2;
353
354         if ((rc = emop->emo_reconfigure(enp)) != 0)
355                 goto fail3;
356
357         return (0);
358
359 fail3:
360         EFSYS_PROBE(fail3);
361
362 fail2:
363         EFSYS_PROBE(fail2);
364
365         epp->ep_fcntl = old_fcntl;
366         epp->ep_fcntl_autoneg = old_autoneg;
367         epp->ep_adv_cap_mask = old_adv_cap;
368
369 fail1:
370         EFSYS_PROBE1(fail1, efx_rc_t, rc);
371
372         return (rc);
373 }
374
375                         void
376 efx_mac_fcntl_get(
377         __in            efx_nic_t *enp,
378         __out           unsigned int *fcntl_wantedp,
379         __out           unsigned int *fcntl_linkp)
380 {
381         efx_port_t *epp = &(enp->en_port);
382         unsigned int wanted = 0;
383
384         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
385         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
386
387         /*
388          * Decode the requested flow control settings from the PHY
389          * advertised capabilities.
390          */
391         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
392                 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
393         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
394                 wanted ^= EFX_FCNTL_GENERATE;
395
396         *fcntl_linkp = epp->ep_fcntl;
397         *fcntl_wantedp = wanted;
398 }
399
400         __checkReturn   efx_rc_t
401 efx_mac_multicast_list_set(
402         __in                            efx_nic_t *enp,
403         __in_ecount(6*count)            uint8_t const *addrs,
404         __in                            int count)
405 {
406         efx_port_t *epp = &(enp->en_port);
407         const efx_mac_ops_t *emop = epp->ep_emop;
408         uint8_t *old_mulcst_addr_list = NULL;
409         uint32_t old_mulcst_addr_count;
410         efx_rc_t rc;
411
412         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
413         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
414
415         if (count > EFX_MAC_MULTICAST_LIST_MAX) {
416                 rc = EINVAL;
417                 goto fail1;
418         }
419
420         old_mulcst_addr_count = epp->ep_mulcst_addr_count;
421         if (old_mulcst_addr_count > 0) {
422                 /* Allocate memory to store old list (instead of using stack) */
423                 EFSYS_KMEM_ALLOC(enp->en_esip,
424                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
425                                 old_mulcst_addr_list);
426                 if (old_mulcst_addr_list == NULL) {
427                         rc = ENOMEM;
428                         goto fail2;
429                 }
430
431                 /* Save the old list in case we need to rollback */
432                 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
433                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
434         }
435
436         /* Store the new list */
437         memcpy(epp->ep_mulcst_addr_list, addrs,
438                 count * EFX_MAC_ADDR_LEN);
439         epp->ep_mulcst_addr_count = count;
440
441         if ((rc = emop->emo_multicast_list_set(enp)) != 0)
442                 goto fail3;
443
444         if (old_mulcst_addr_count > 0) {
445                 EFSYS_KMEM_FREE(enp->en_esip,
446                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
447                                 old_mulcst_addr_list);
448         }
449
450         return (0);
451
452 fail3:
453         EFSYS_PROBE(fail3);
454
455         /* Restore original list on failure */
456         epp->ep_mulcst_addr_count = old_mulcst_addr_count;
457         if (old_mulcst_addr_count > 0) {
458                 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
459                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
460
461                 EFSYS_KMEM_FREE(enp->en_esip,
462                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
463                                 old_mulcst_addr_list);
464         }
465
466 fail2:
467         EFSYS_PROBE(fail2);
468
469 fail1:
470         EFSYS_PROBE1(fail1, efx_rc_t, rc);
471
472         return (rc);
473
474 }
475
476         __checkReturn   efx_rc_t
477 efx_mac_filter_default_rxq_set(
478         __in            efx_nic_t *enp,
479         __in            efx_rxq_t *erp,
480         __in            boolean_t using_rss)
481 {
482         efx_port_t *epp = &(enp->en_port);
483         const efx_mac_ops_t *emop = epp->ep_emop;
484         efx_rc_t rc;
485
486         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
487         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
488
489         if (emop->emo_filter_default_rxq_set != NULL) {
490                 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
491                 if (rc != 0)
492                         goto fail1;
493         }
494
495         return (0);
496
497 fail1:
498         EFSYS_PROBE1(fail1, efx_rc_t, rc);
499
500         return (rc);
501 }
502
503                         void
504 efx_mac_filter_default_rxq_clear(
505         __in            efx_nic_t *enp)
506 {
507         efx_port_t *epp = &(enp->en_port);
508         const efx_mac_ops_t *emop = epp->ep_emop;
509
510         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
511         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
512
513         if (emop->emo_filter_default_rxq_clear != NULL)
514                 emop->emo_filter_default_rxq_clear(enp);
515 }
516
517
518 #if EFSYS_OPT_MAC_STATS
519
520 #if EFSYS_OPT_NAMES
521
522 /* START MKCONFIG GENERATED EfxMacStatNamesBlock c11b91b42f922516 */
523 static const char * const __efx_mac_stat_name[] = {
524         "rx_octets",
525         "rx_pkts",
526         "rx_unicst_pkts",
527         "rx_multicst_pkts",
528         "rx_brdcst_pkts",
529         "rx_pause_pkts",
530         "rx_le_64_pkts",
531         "rx_65_to_127_pkts",
532         "rx_128_to_255_pkts",
533         "rx_256_to_511_pkts",
534         "rx_512_to_1023_pkts",
535         "rx_1024_to_15xx_pkts",
536         "rx_ge_15xx_pkts",
537         "rx_errors",
538         "rx_fcs_errors",
539         "rx_drop_events",
540         "rx_false_carrier_errors",
541         "rx_symbol_errors",
542         "rx_align_errors",
543         "rx_internal_errors",
544         "rx_jabber_pkts",
545         "rx_lane0_char_err",
546         "rx_lane1_char_err",
547         "rx_lane2_char_err",
548         "rx_lane3_char_err",
549         "rx_lane0_disp_err",
550         "rx_lane1_disp_err",
551         "rx_lane2_disp_err",
552         "rx_lane3_disp_err",
553         "rx_match_fault",
554         "rx_nodesc_drop_cnt",
555         "tx_octets",
556         "tx_pkts",
557         "tx_unicst_pkts",
558         "tx_multicst_pkts",
559         "tx_brdcst_pkts",
560         "tx_pause_pkts",
561         "tx_le_64_pkts",
562         "tx_65_to_127_pkts",
563         "tx_128_to_255_pkts",
564         "tx_256_to_511_pkts",
565         "tx_512_to_1023_pkts",
566         "tx_1024_to_15xx_pkts",
567         "tx_ge_15xx_pkts",
568         "tx_errors",
569         "tx_sgl_col_pkts",
570         "tx_mult_col_pkts",
571         "tx_ex_col_pkts",
572         "tx_late_col_pkts",
573         "tx_def_pkts",
574         "tx_ex_def_pkts",
575         "pm_trunc_bb_overflow",
576         "pm_discard_bb_overflow",
577         "pm_trunc_vfifo_full",
578         "pm_discard_vfifo_full",
579         "pm_trunc_qbb",
580         "pm_discard_qbb",
581         "pm_discard_mapping",
582         "rxdp_q_disabled_pkts",
583         "rxdp_di_dropped_pkts",
584         "rxdp_streaming_pkts",
585         "rxdp_hlb_fetch",
586         "rxdp_hlb_wait",
587         "vadapter_rx_unicast_packets",
588         "vadapter_rx_unicast_bytes",
589         "vadapter_rx_multicast_packets",
590         "vadapter_rx_multicast_bytes",
591         "vadapter_rx_broadcast_packets",
592         "vadapter_rx_broadcast_bytes",
593         "vadapter_rx_bad_packets",
594         "vadapter_rx_bad_bytes",
595         "vadapter_rx_overflow",
596         "vadapter_tx_unicast_packets",
597         "vadapter_tx_unicast_bytes",
598         "vadapter_tx_multicast_packets",
599         "vadapter_tx_multicast_bytes",
600         "vadapter_tx_broadcast_packets",
601         "vadapter_tx_broadcast_bytes",
602         "vadapter_tx_bad_packets",
603         "vadapter_tx_bad_bytes",
604         "vadapter_tx_overflow",
605 };
606 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
607
608         __checkReturn                   const char *
609 efx_mac_stat_name(
610         __in                            efx_nic_t *enp,
611         __in                            unsigned int id)
612 {
613         _NOTE(ARGUNUSED(enp))
614         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
615
616         EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
617         return (__efx_mac_stat_name[id]);
618 }
619
620 #endif  /* EFSYS_OPT_NAMES */
621
622 static                                  efx_rc_t
623 efx_mac_stats_mask_add_range(
624         __inout_bcount(mask_size)       uint32_t *maskp,
625         __in                            size_t mask_size,
626         __in                            const struct efx_mac_stats_range *rngp)
627 {
628         unsigned int mask_npages = mask_size / sizeof (*maskp);
629         unsigned int el;
630         unsigned int el_min;
631         unsigned int el_max;
632         unsigned int low;
633         unsigned int high;
634         unsigned int width;
635         efx_rc_t rc;
636
637         if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
638             (unsigned int)rngp->last) {
639                 rc = EINVAL;
640                 goto fail1;
641         }
642
643         EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
644         EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
645
646         for (el = 0; el < mask_npages; ++el) {
647                 el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
648                 el_max =
649                     el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
650                 if ((unsigned int)rngp->first > el_max ||
651                     (unsigned int)rngp->last < el_min)
652                         continue;
653                 low = MAX((unsigned int)rngp->first, el_min);
654                 high = MIN((unsigned int)rngp->last, el_max);
655                 width = high - low + 1;
656                 maskp[el] |=
657                     (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
658                     (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
659         }
660
661         return (0);
662
663 fail1:
664         EFSYS_PROBE1(fail1, efx_rc_t, rc);
665
666         return (rc);
667 }
668
669                                         efx_rc_t
670 efx_mac_stats_mask_add_ranges(
671         __inout_bcount(mask_size)       uint32_t *maskp,
672         __in                            size_t mask_size,
673         __in_ecount(rng_count)          const struct efx_mac_stats_range *rngp,
674         __in                            unsigned int rng_count)
675 {
676         unsigned int i;
677         efx_rc_t rc;
678
679         for (i = 0; i < rng_count; ++i) {
680                 if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
681                     &rngp[i])) != 0)
682                         goto fail1;
683         }
684
685         return (0);
686
687 fail1:
688         EFSYS_PROBE1(fail1, efx_rc_t, rc);
689
690         return (rc);
691 }
692
693         __checkReturn                   efx_rc_t
694 efx_mac_stats_get_mask(
695         __in                            efx_nic_t *enp,
696         __out_bcount(mask_size)         uint32_t *maskp,
697         __in                            size_t mask_size)
698 {
699         efx_port_t *epp = &(enp->en_port);
700         const efx_mac_ops_t *emop = epp->ep_emop;
701         efx_rc_t rc;
702
703         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
704         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
705         EFSYS_ASSERT(maskp != NULL);
706         EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
707
708         (void) memset(maskp, 0, mask_size);
709
710         if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
711                 goto fail1;
712
713         return (0);
714
715 fail1:
716         EFSYS_PROBE1(fail1, efx_rc_t, rc);
717
718         return (rc);
719 }
720
721         __checkReturn                   efx_rc_t
722 efx_mac_stats_upload(
723         __in                            efx_nic_t *enp,
724         __in                            efsys_mem_t *esmp)
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_PORT);
732         EFSYS_ASSERT(emop != NULL);
733
734         /*
735          * Don't assert !ep_mac_stats_pending, because the client might
736          * have failed to finalise statistics when previously stopping
737          * the port.
738          */
739         if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
740                 goto fail1;
741
742         epp->ep_mac_stats_pending = B_TRUE;
743
744         return (0);
745
746 fail1:
747         EFSYS_PROBE1(fail1, efx_rc_t, rc);
748
749         return (rc);
750 }
751
752         __checkReturn                   efx_rc_t
753 efx_mac_stats_periodic(
754         __in                            efx_nic_t *enp,
755         __in                            efsys_mem_t *esmp,
756         __in                            uint16_t period_ms,
757         __in                            boolean_t events)
758 {
759         efx_port_t *epp = &(enp->en_port);
760         const efx_mac_ops_t *emop = epp->ep_emop;
761         efx_rc_t rc;
762
763         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
764         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
765
766         EFSYS_ASSERT(emop != NULL);
767
768         if (emop->emo_stats_periodic == NULL) {
769                 rc = EINVAL;
770                 goto fail1;
771         }
772
773         if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
774                 goto fail2;
775
776         return (0);
777
778 fail2:
779         EFSYS_PROBE(fail2);
780 fail1:
781         EFSYS_PROBE1(fail1, efx_rc_t, rc);
782
783         return (rc);
784 }
785
786
787         __checkReturn                   efx_rc_t
788 efx_mac_stats_update(
789         __in                            efx_nic_t *enp,
790         __in                            efsys_mem_t *esmp,
791         __inout_ecount(EFX_MAC_NSTATS)  efsys_stat_t *essp,
792         __inout_opt                     uint32_t *generationp)
793 {
794         efx_port_t *epp = &(enp->en_port);
795         const efx_mac_ops_t *emop = epp->ep_emop;
796         efx_rc_t rc;
797
798         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
799         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
800         EFSYS_ASSERT(emop != NULL);
801
802         rc = emop->emo_stats_update(enp, esmp, essp, generationp);
803         if (rc == 0)
804                 epp->ep_mac_stats_pending = B_FALSE;
805
806         return (rc);
807 }
808
809 #endif  /* EFSYS_OPT_MAC_STATS */
810
811         __checkReturn                   efx_rc_t
812 efx_mac_select(
813         __in                            efx_nic_t *enp)
814 {
815         efx_port_t *epp = &(enp->en_port);
816         efx_mac_type_t type = EFX_MAC_INVALID;
817         const efx_mac_ops_t *emop;
818         int rc = EINVAL;
819
820         switch (enp->en_family) {
821 #if EFSYS_OPT_SIENA
822         case EFX_FAMILY_SIENA:
823                 emop = &__efx_siena_mac_ops;
824                 type = EFX_MAC_SIENA;
825                 break;
826 #endif /* EFSYS_OPT_SIENA */
827
828 #if EFSYS_OPT_HUNTINGTON
829         case EFX_FAMILY_HUNTINGTON:
830                 emop = &__efx_ef10_mac_ops;
831                 type = EFX_MAC_HUNTINGTON;
832                 break;
833 #endif /* EFSYS_OPT_HUNTINGTON */
834
835 #if EFSYS_OPT_MEDFORD
836         case EFX_FAMILY_MEDFORD:
837                 emop = &__efx_ef10_mac_ops;
838                 type = EFX_MAC_MEDFORD;
839                 break;
840 #endif /* EFSYS_OPT_MEDFORD */
841
842         default:
843                 rc = EINVAL;
844                 goto fail1;
845         }
846
847         EFSYS_ASSERT(type != EFX_MAC_INVALID);
848         EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
849         EFSYS_ASSERT(emop != NULL);
850
851         epp->ep_emop = emop;
852         epp->ep_mac_type = type;
853
854         return (0);
855
856 fail1:
857         EFSYS_PROBE1(fail1, efx_rc_t, rc);
858
859         return (rc);
860 }
861
862
863 #if EFSYS_OPT_SIENA
864
865 #define EFX_MAC_HASH_BITS       (1 << 8)
866
867 /* Compute the multicast hash as used on Falcon and Siena. */
868 static  void
869 siena_mac_multicast_hash_compute(
870         __in_ecount(6*count)            uint8_t const *addrs,
871         __in                            int count,
872         __out                           efx_oword_t *hash_low,
873         __out                           efx_oword_t *hash_high)
874 {
875         uint32_t crc, index;
876         int i;
877
878         EFSYS_ASSERT(hash_low != NULL);
879         EFSYS_ASSERT(hash_high != NULL);
880
881         EFX_ZERO_OWORD(*hash_low);
882         EFX_ZERO_OWORD(*hash_high);
883
884         for (i = 0; i < count; i++) {
885                 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
886                 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
887                 index = crc % EFX_MAC_HASH_BITS;
888                 if (index < 128) {
889                         EFX_SET_OWORD_BIT(*hash_low, index);
890                 } else {
891                         EFX_SET_OWORD_BIT(*hash_high, index - 128);
892                 }
893
894                 addrs += EFX_MAC_ADDR_LEN;
895         }
896 }
897
898 static  __checkReturn   efx_rc_t
899 siena_mac_multicast_list_set(
900         __in            efx_nic_t *enp)
901 {
902         efx_port_t *epp = &(enp->en_port);
903         const efx_mac_ops_t *emop = epp->ep_emop;
904         efx_oword_t old_hash[2];
905         efx_rc_t rc;
906
907         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
908         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
909
910         memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
911
912         siena_mac_multicast_hash_compute(
913             epp->ep_mulcst_addr_list,
914             epp->ep_mulcst_addr_count,
915             &epp->ep_multicst_hash[0],
916             &epp->ep_multicst_hash[1]);
917
918         if ((rc = emop->emo_reconfigure(enp)) != 0)
919                 goto fail1;
920
921         return (0);
922
923 fail1:
924         EFSYS_PROBE1(fail1, efx_rc_t, rc);
925
926         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
927
928         return (rc);
929 }
930
931 #endif /* EFSYS_OPT_SIENA */