]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/sfc/base/efx_mac.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / 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 */