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