]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/sfc/base/efx_mac.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / 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 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 __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 */