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