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