New upstream version 18.08
[deb_dpdk.git] / drivers / net / sfc / base / efx_mac.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2007-2018 Solarflare Communications Inc.
4  * All rights reserved.
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 EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
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  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
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         __checkReturn                   efx_rc_t
222 efx_mac_drain(
223         __in                            efx_nic_t *enp,
224         __in                            boolean_t enabled)
225 {
226         efx_port_t *epp = &(enp->en_port);
227         const efx_mac_ops_t *emop = epp->ep_emop;
228         efx_rc_t rc;
229
230         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
231         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
232         EFSYS_ASSERT(emop != NULL);
233
234         if (epp->ep_mac_drain == enabled)
235                 return (0);
236
237         epp->ep_mac_drain = enabled;
238
239         if ((rc = emop->emo_reconfigure(enp)) != 0)
240                 goto fail1;
241
242         return (0);
243
244 fail1:
245         EFSYS_PROBE1(fail1, efx_rc_t, rc);
246
247         return (rc);
248 }
249
250         __checkReturn   efx_rc_t
251 efx_mac_up(
252         __in            efx_nic_t *enp,
253         __out           boolean_t *mac_upp)
254 {
255         efx_port_t *epp = &(enp->en_port);
256         const efx_mac_ops_t *emop = epp->ep_emop;
257         efx_rc_t rc;
258
259         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
260         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
261
262         if ((rc = emop->emo_up(enp, mac_upp)) != 0)
263                 goto fail1;
264
265         return (0);
266
267 fail1:
268         EFSYS_PROBE1(fail1, efx_rc_t, rc);
269
270         return (rc);
271 }
272
273         __checkReturn                   efx_rc_t
274 efx_mac_fcntl_set(
275         __in                            efx_nic_t *enp,
276         __in                            unsigned int fcntl,
277         __in                            boolean_t autoneg)
278 {
279         efx_port_t *epp = &(enp->en_port);
280         const efx_mac_ops_t *emop = epp->ep_emop;
281         const efx_phy_ops_t *epop = epp->ep_epop;
282         unsigned int old_fcntl;
283         boolean_t old_autoneg;
284         unsigned int old_adv_cap;
285         efx_rc_t rc;
286
287         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
288         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
289
290         if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
291                 rc = EINVAL;
292                 goto fail1;
293         }
294
295         /*
296          * Ignore a request to set flow control auto-negotiation
297          * if the PHY doesn't support it.
298          */
299         if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
300                 autoneg = B_FALSE;
301
302         old_fcntl = epp->ep_fcntl;
303         old_autoneg = epp->ep_fcntl_autoneg;
304         old_adv_cap = epp->ep_adv_cap_mask;
305
306         epp->ep_fcntl = fcntl;
307         epp->ep_fcntl_autoneg = autoneg;
308
309         /*
310          * Always encode the flow control settings in the advertised
311          * capabilities even if we are not trying to auto-negotiate
312          * them and reconfigure both the PHY and the MAC.
313          */
314         if (fcntl & EFX_FCNTL_RESPOND)
315                 epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
316                                             1 << EFX_PHY_CAP_ASYM);
317         else
318                 epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
319                                             1 << EFX_PHY_CAP_ASYM);
320
321         if (fcntl & EFX_FCNTL_GENERATE)
322                 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
323
324         if ((rc = epop->epo_reconfigure(enp)) != 0)
325                 goto fail2;
326
327         if ((rc = emop->emo_reconfigure(enp)) != 0)
328                 goto fail3;
329
330         return (0);
331
332 fail3:
333         EFSYS_PROBE(fail3);
334
335 fail2:
336         EFSYS_PROBE(fail2);
337
338         epp->ep_fcntl = old_fcntl;
339         epp->ep_fcntl_autoneg = old_autoneg;
340         epp->ep_adv_cap_mask = old_adv_cap;
341
342 fail1:
343         EFSYS_PROBE1(fail1, efx_rc_t, rc);
344
345         return (rc);
346 }
347
348                         void
349 efx_mac_fcntl_get(
350         __in            efx_nic_t *enp,
351         __out           unsigned int *fcntl_wantedp,
352         __out           unsigned int *fcntl_linkp)
353 {
354         efx_port_t *epp = &(enp->en_port);
355         unsigned int wanted = 0;
356
357         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
358         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
359
360         /*
361          * Decode the requested flow control settings from the PHY
362          * advertised capabilities.
363          */
364         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
365                 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
366         if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
367                 wanted ^= EFX_FCNTL_GENERATE;
368
369         *fcntl_linkp = epp->ep_fcntl;
370         *fcntl_wantedp = wanted;
371 }
372
373         __checkReturn   efx_rc_t
374 efx_mac_multicast_list_set(
375         __in                            efx_nic_t *enp,
376         __in_ecount(6*count)            uint8_t const *addrs,
377         __in                            int count)
378 {
379         efx_port_t *epp = &(enp->en_port);
380         const efx_mac_ops_t *emop = epp->ep_emop;
381         uint8_t *old_mulcst_addr_list = NULL;
382         uint32_t old_mulcst_addr_count;
383         efx_rc_t rc;
384
385         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
386         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
387
388         if (count > EFX_MAC_MULTICAST_LIST_MAX) {
389                 rc = EINVAL;
390                 goto fail1;
391         }
392
393         old_mulcst_addr_count = epp->ep_mulcst_addr_count;
394         if (old_mulcst_addr_count > 0) {
395                 /* Allocate memory to store old list (instead of using stack) */
396                 EFSYS_KMEM_ALLOC(enp->en_esip,
397                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
398                                 old_mulcst_addr_list);
399                 if (old_mulcst_addr_list == NULL) {
400                         rc = ENOMEM;
401                         goto fail2;
402                 }
403
404                 /* Save the old list in case we need to rollback */
405                 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
406                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
407         }
408
409         /* Store the new list */
410         memcpy(epp->ep_mulcst_addr_list, addrs,
411                 count * EFX_MAC_ADDR_LEN);
412         epp->ep_mulcst_addr_count = count;
413
414         if ((rc = emop->emo_multicast_list_set(enp)) != 0)
415                 goto fail3;
416
417         if (old_mulcst_addr_count > 0) {
418                 EFSYS_KMEM_FREE(enp->en_esip,
419                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
420                                 old_mulcst_addr_list);
421         }
422
423         return (0);
424
425 fail3:
426         EFSYS_PROBE(fail3);
427
428         /* Restore original list on failure */
429         epp->ep_mulcst_addr_count = old_mulcst_addr_count;
430         if (old_mulcst_addr_count > 0) {
431                 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
432                         old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
433
434                 EFSYS_KMEM_FREE(enp->en_esip,
435                                 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
436                                 old_mulcst_addr_list);
437         }
438
439 fail2:
440         EFSYS_PROBE(fail2);
441
442 fail1:
443         EFSYS_PROBE1(fail1, efx_rc_t, rc);
444
445         return (rc);
446
447 }
448
449         __checkReturn   efx_rc_t
450 efx_mac_filter_default_rxq_set(
451         __in            efx_nic_t *enp,
452         __in            efx_rxq_t *erp,
453         __in            boolean_t using_rss)
454 {
455         efx_port_t *epp = &(enp->en_port);
456         const efx_mac_ops_t *emop = epp->ep_emop;
457         efx_rc_t rc;
458
459         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
460         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
461
462         if (emop->emo_filter_default_rxq_set != NULL) {
463                 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
464                 if (rc != 0)
465                         goto fail1;
466         }
467
468         return (0);
469
470 fail1:
471         EFSYS_PROBE1(fail1, efx_rc_t, rc);
472
473         return (rc);
474 }
475
476                         void
477 efx_mac_filter_default_rxq_clear(
478         __in            efx_nic_t *enp)
479 {
480         efx_port_t *epp = &(enp->en_port);
481         const efx_mac_ops_t *emop = epp->ep_emop;
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_clear != NULL)
487                 emop->emo_filter_default_rxq_clear(enp);
488 }
489
490
491 #if EFSYS_OPT_MAC_STATS
492
493 #if EFSYS_OPT_NAMES
494
495 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 1a45a82fcfb30c1b */
496 static const char * const __efx_mac_stat_name[] = {
497         "rx_octets",
498         "rx_pkts",
499         "rx_unicst_pkts",
500         "rx_multicst_pkts",
501         "rx_brdcst_pkts",
502         "rx_pause_pkts",
503         "rx_le_64_pkts",
504         "rx_65_to_127_pkts",
505         "rx_128_to_255_pkts",
506         "rx_256_to_511_pkts",
507         "rx_512_to_1023_pkts",
508         "rx_1024_to_15xx_pkts",
509         "rx_ge_15xx_pkts",
510         "rx_errors",
511         "rx_fcs_errors",
512         "rx_drop_events",
513         "rx_false_carrier_errors",
514         "rx_symbol_errors",
515         "rx_align_errors",
516         "rx_internal_errors",
517         "rx_jabber_pkts",
518         "rx_lane0_char_err",
519         "rx_lane1_char_err",
520         "rx_lane2_char_err",
521         "rx_lane3_char_err",
522         "rx_lane0_disp_err",
523         "rx_lane1_disp_err",
524         "rx_lane2_disp_err",
525         "rx_lane3_disp_err",
526         "rx_match_fault",
527         "rx_nodesc_drop_cnt",
528         "tx_octets",
529         "tx_pkts",
530         "tx_unicst_pkts",
531         "tx_multicst_pkts",
532         "tx_brdcst_pkts",
533         "tx_pause_pkts",
534         "tx_le_64_pkts",
535         "tx_65_to_127_pkts",
536         "tx_128_to_255_pkts",
537         "tx_256_to_511_pkts",
538         "tx_512_to_1023_pkts",
539         "tx_1024_to_15xx_pkts",
540         "tx_ge_15xx_pkts",
541         "tx_errors",
542         "tx_sgl_col_pkts",
543         "tx_mult_col_pkts",
544         "tx_ex_col_pkts",
545         "tx_late_col_pkts",
546         "tx_def_pkts",
547         "tx_ex_def_pkts",
548         "pm_trunc_bb_overflow",
549         "pm_discard_bb_overflow",
550         "pm_trunc_vfifo_full",
551         "pm_discard_vfifo_full",
552         "pm_trunc_qbb",
553         "pm_discard_qbb",
554         "pm_discard_mapping",
555         "rxdp_q_disabled_pkts",
556         "rxdp_di_dropped_pkts",
557         "rxdp_streaming_pkts",
558         "rxdp_hlb_fetch",
559         "rxdp_hlb_wait",
560         "vadapter_rx_unicast_packets",
561         "vadapter_rx_unicast_bytes",
562         "vadapter_rx_multicast_packets",
563         "vadapter_rx_multicast_bytes",
564         "vadapter_rx_broadcast_packets",
565         "vadapter_rx_broadcast_bytes",
566         "vadapter_rx_bad_packets",
567         "vadapter_rx_bad_bytes",
568         "vadapter_rx_overflow",
569         "vadapter_tx_unicast_packets",
570         "vadapter_tx_unicast_bytes",
571         "vadapter_tx_multicast_packets",
572         "vadapter_tx_multicast_bytes",
573         "vadapter_tx_broadcast_packets",
574         "vadapter_tx_broadcast_bytes",
575         "vadapter_tx_bad_packets",
576         "vadapter_tx_bad_bytes",
577         "vadapter_tx_overflow",
578         "fec_uncorrected_errors",
579         "fec_corrected_errors",
580         "fec_corrected_symbols_lane0",
581         "fec_corrected_symbols_lane1",
582         "fec_corrected_symbols_lane2",
583         "fec_corrected_symbols_lane3",
584         "ctpio_vi_busy_fallback",
585         "ctpio_long_write_success",
586         "ctpio_missing_dbell_fail",
587         "ctpio_overflow_fail",
588         "ctpio_underflow_fail",
589         "ctpio_timeout_fail",
590         "ctpio_noncontig_wr_fail",
591         "ctpio_frm_clobber_fail",
592         "ctpio_invalid_wr_fail",
593         "ctpio_vi_clobber_fallback",
594         "ctpio_unqualified_fallback",
595         "ctpio_runt_fallback",
596         "ctpio_success",
597         "ctpio_fallback",
598         "ctpio_poison",
599         "ctpio_erase",
600         "rxdp_scatter_disabled_trunc",
601         "rxdp_hlb_idle",
602         "rxdp_hlb_timeout",
603 };
604 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
605
606         __checkReturn                   const char *
607 efx_mac_stat_name(
608         __in                            efx_nic_t *enp,
609         __in                            unsigned int id)
610 {
611         _NOTE(ARGUNUSED(enp))
612         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
613
614         EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
615         return (__efx_mac_stat_name[id]);
616 }
617
618 #endif  /* EFSYS_OPT_NAMES */
619
620 static                                  efx_rc_t
621 efx_mac_stats_mask_add_range(
622         __inout_bcount(mask_size)       uint32_t *maskp,
623         __in                            size_t mask_size,
624         __in                            const struct efx_mac_stats_range *rngp)
625 {
626         unsigned int mask_npages = mask_size / sizeof (*maskp);
627         unsigned int el;
628         unsigned int el_min;
629         unsigned int el_max;
630         unsigned int low;
631         unsigned int high;
632         unsigned int width;
633         efx_rc_t rc;
634
635         if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
636             (unsigned int)rngp->last) {
637                 rc = EINVAL;
638                 goto fail1;
639         }
640
641         EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
642         EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
643
644         for (el = 0; el < mask_npages; ++el) {
645                 el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
646                 el_max =
647                     el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
648                 if ((unsigned int)rngp->first > el_max ||
649                     (unsigned int)rngp->last < el_min)
650                         continue;
651                 low = MAX((unsigned int)rngp->first, el_min);
652                 high = MIN((unsigned int)rngp->last, el_max);
653                 width = high - low + 1;
654                 maskp[el] |=
655                     (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
656                     (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
657         }
658
659         return (0);
660
661 fail1:
662         EFSYS_PROBE1(fail1, efx_rc_t, rc);
663
664         return (rc);
665 }
666
667                                         efx_rc_t
668 efx_mac_stats_mask_add_ranges(
669         __inout_bcount(mask_size)       uint32_t *maskp,
670         __in                            size_t mask_size,
671         __in_ecount(rng_count)          const struct efx_mac_stats_range *rngp,
672         __in                            unsigned int rng_count)
673 {
674         unsigned int i;
675         efx_rc_t rc;
676
677         for (i = 0; i < rng_count; ++i) {
678                 if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
679                     &rngp[i])) != 0)
680                         goto fail1;
681         }
682
683         return (0);
684
685 fail1:
686         EFSYS_PROBE1(fail1, efx_rc_t, rc);
687
688         return (rc);
689 }
690
691         __checkReturn                   efx_rc_t
692 efx_mac_stats_get_mask(
693         __in                            efx_nic_t *enp,
694         __out_bcount(mask_size)         uint32_t *maskp,
695         __in                            size_t mask_size)
696 {
697         efx_port_t *epp = &(enp->en_port);
698         const efx_mac_ops_t *emop = epp->ep_emop;
699         efx_rc_t rc;
700
701         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
702         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
703         EFSYS_ASSERT(maskp != NULL);
704         EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
705
706         (void) memset(maskp, 0, mask_size);
707
708         if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
709                 goto fail1;
710
711         return (0);
712
713 fail1:
714         EFSYS_PROBE1(fail1, efx_rc_t, rc);
715
716         return (rc);
717 }
718
719         __checkReturn                   efx_rc_t
720 efx_mac_stats_clear(
721         __in                            efx_nic_t *enp)
722 {
723         efx_port_t *epp = &(enp->en_port);
724         const efx_mac_ops_t *emop = epp->ep_emop;
725         efx_rc_t rc;
726
727         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
728         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
729         EFSYS_ASSERT(emop != NULL);
730
731         if ((rc = emop->emo_stats_clear(enp)) != 0)
732                 goto fail1;
733
734         return (0);
735
736 fail1:
737         EFSYS_PROBE1(fail1, efx_rc_t, rc);
738
739         return (rc);
740 }
741
742         __checkReturn                   efx_rc_t
743 efx_mac_stats_upload(
744         __in                            efx_nic_t *enp,
745         __in                            efsys_mem_t *esmp)
746 {
747         efx_port_t *epp = &(enp->en_port);
748         const efx_mac_ops_t *emop = epp->ep_emop;
749         efx_rc_t rc;
750
751         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
752         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
753         EFSYS_ASSERT(emop != NULL);
754
755         if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
756                 goto fail1;
757
758         return (0);
759
760 fail1:
761         EFSYS_PROBE1(fail1, efx_rc_t, rc);
762
763         return (rc);
764 }
765
766         __checkReturn                   efx_rc_t
767 efx_mac_stats_periodic(
768         __in                            efx_nic_t *enp,
769         __in                            efsys_mem_t *esmp,
770         __in                            uint16_t period_ms,
771         __in                            boolean_t events)
772 {
773         efx_port_t *epp = &(enp->en_port);
774         const efx_mac_ops_t *emop = epp->ep_emop;
775         efx_rc_t rc;
776
777         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
778         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
779
780         EFSYS_ASSERT(emop != NULL);
781
782         if (emop->emo_stats_periodic == NULL) {
783                 rc = EINVAL;
784                 goto fail1;
785         }
786
787         if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
788                 goto fail2;
789
790         return (0);
791
792 fail2:
793         EFSYS_PROBE(fail2);
794 fail1:
795         EFSYS_PROBE1(fail1, efx_rc_t, rc);
796
797         return (rc);
798 }
799
800
801         __checkReturn                   efx_rc_t
802 efx_mac_stats_update(
803         __in                            efx_nic_t *enp,
804         __in                            efsys_mem_t *esmp,
805         __inout_ecount(EFX_MAC_NSTATS)  efsys_stat_t *essp,
806         __inout_opt                     uint32_t *generationp)
807 {
808         efx_port_t *epp = &(enp->en_port);
809         const efx_mac_ops_t *emop = epp->ep_emop;
810         efx_rc_t rc;
811
812         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
813         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
814         EFSYS_ASSERT(emop != NULL);
815
816         rc = emop->emo_stats_update(enp, esmp, essp, generationp);
817
818         return (rc);
819 }
820
821 #endif  /* EFSYS_OPT_MAC_STATS */
822
823         __checkReturn                   efx_rc_t
824 efx_mac_select(
825         __in                            efx_nic_t *enp)
826 {
827         efx_port_t *epp = &(enp->en_port);
828         efx_mac_type_t type = EFX_MAC_INVALID;
829         const efx_mac_ops_t *emop;
830         int rc = EINVAL;
831
832         switch (enp->en_family) {
833 #if EFSYS_OPT_SIENA
834         case EFX_FAMILY_SIENA:
835                 emop = &__efx_mac_siena_ops;
836                 type = EFX_MAC_SIENA;
837                 break;
838 #endif /* EFSYS_OPT_SIENA */
839
840 #if EFSYS_OPT_HUNTINGTON
841         case EFX_FAMILY_HUNTINGTON:
842                 emop = &__efx_mac_ef10_ops;
843                 type = EFX_MAC_HUNTINGTON;
844                 break;
845 #endif /* EFSYS_OPT_HUNTINGTON */
846
847 #if EFSYS_OPT_MEDFORD
848         case EFX_FAMILY_MEDFORD:
849                 emop = &__efx_mac_ef10_ops;
850                 type = EFX_MAC_MEDFORD;
851                 break;
852 #endif /* EFSYS_OPT_MEDFORD */
853
854 #if EFSYS_OPT_MEDFORD2
855         case EFX_FAMILY_MEDFORD2:
856                 emop = &__efx_mac_ef10_ops;
857                 type = EFX_MAC_MEDFORD2;
858                 break;
859 #endif /* EFSYS_OPT_MEDFORD2 */
860
861         default:
862                 rc = EINVAL;
863                 goto fail1;
864         }
865
866         EFSYS_ASSERT(type != EFX_MAC_INVALID);
867         EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
868         EFSYS_ASSERT(emop != NULL);
869
870         epp->ep_emop = emop;
871         epp->ep_mac_type = type;
872
873         return (0);
874
875 fail1:
876         EFSYS_PROBE1(fail1, efx_rc_t, rc);
877
878         return (rc);
879 }
880
881
882 #if EFSYS_OPT_SIENA
883
884 #define EFX_MAC_HASH_BITS       (1 << 8)
885
886 /* Compute the multicast hash as used on Falcon and Siena. */
887 static  void
888 siena_mac_multicast_hash_compute(
889         __in_ecount(6*count)            uint8_t const *addrs,
890         __in                            int count,
891         __out                           efx_oword_t *hash_low,
892         __out                           efx_oword_t *hash_high)
893 {
894         uint32_t crc, index;
895         int i;
896
897         EFSYS_ASSERT(hash_low != NULL);
898         EFSYS_ASSERT(hash_high != NULL);
899
900         EFX_ZERO_OWORD(*hash_low);
901         EFX_ZERO_OWORD(*hash_high);
902
903         for (i = 0; i < count; i++) {
904                 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
905                 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
906                 index = crc % EFX_MAC_HASH_BITS;
907                 if (index < 128) {
908                         EFX_SET_OWORD_BIT(*hash_low, index);
909                 } else {
910                         EFX_SET_OWORD_BIT(*hash_high, index - 128);
911                 }
912
913                 addrs += EFX_MAC_ADDR_LEN;
914         }
915 }
916
917 static  __checkReturn   efx_rc_t
918 siena_mac_multicast_list_set(
919         __in            efx_nic_t *enp)
920 {
921         efx_port_t *epp = &(enp->en_port);
922         const efx_mac_ops_t *emop = epp->ep_emop;
923         efx_oword_t old_hash[2];
924         efx_rc_t rc;
925
926         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
927         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
928
929         memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
930
931         siena_mac_multicast_hash_compute(
932             epp->ep_mulcst_addr_list,
933             epp->ep_mulcst_addr_count,
934             &epp->ep_multicst_hash[0],
935             &epp->ep_multicst_hash[1]);
936
937         if ((rc = emop->emo_reconfigure(enp)) != 0)
938                 goto fail1;
939
940         return (0);
941
942 fail1:
943         EFSYS_PROBE1(fail1, efx_rc_t, rc);
944
945         memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
946
947         return (rc);
948 }
949
950 #endif /* EFSYS_OPT_SIENA */