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