1 /*-
2 * Copyright (c) 2007-2016 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/efx_mac.c 342508 2018-12-26 10:17:44Z arybchik $");
33
34 #include "efx.h"
35 #include "efx_impl.h"
36
37 #if EFSYS_OPT_SIENA
38
39 static __checkReturn efx_rc_t
40 siena_mac_multicast_list_set(
41 __in efx_nic_t *enp);
42
43 #endif /* EFSYS_OPT_SIENA */
44
45 #if EFSYS_OPT_SIENA
46 static const efx_mac_ops_t __efx_mac_siena_ops = {
47 siena_mac_poll, /* emo_poll */
48 siena_mac_up, /* emo_up */
49 siena_mac_reconfigure, /* emo_addr_set */
50 siena_mac_reconfigure, /* emo_pdu_set */
51 siena_mac_pdu_get, /* emo_pdu_get */
52 siena_mac_reconfigure, /* emo_reconfigure */
53 siena_mac_multicast_list_set, /* emo_multicast_list_set */
54 NULL, /* emo_filter_set_default_rxq */
55 NULL, /* emo_filter_default_rxq_clear */
56 #if EFSYS_OPT_LOOPBACK
57 siena_mac_loopback_set, /* emo_loopback_set */
58 #endif /* EFSYS_OPT_LOOPBACK */
59 #if EFSYS_OPT_MAC_STATS
60 siena_mac_stats_get_mask, /* emo_stats_get_mask */
61 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
62 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
63 siena_mac_stats_update /* emo_stats_update */
64 #endif /* EFSYS_OPT_MAC_STATS */
65 };
66 #endif /* EFSYS_OPT_SIENA */
67
68 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
69 static const efx_mac_ops_t __efx_mac_ef10_ops = {
70 ef10_mac_poll, /* emo_poll */
71 ef10_mac_up, /* emo_up */
72 ef10_mac_addr_set, /* emo_addr_set */
73 ef10_mac_pdu_set, /* emo_pdu_set */
74 ef10_mac_pdu_get, /* emo_pdu_get */
75 ef10_mac_reconfigure, /* emo_reconfigure */
76 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
77 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
78 ef10_mac_filter_default_rxq_clear,
79 /* emo_filter_default_rxq_clear */
80 #if EFSYS_OPT_LOOPBACK
81 ef10_mac_loopback_set, /* emo_loopback_set */
82 #endif /* EFSYS_OPT_LOOPBACK */
83 #if EFSYS_OPT_MAC_STATS
84 ef10_mac_stats_get_mask, /* emo_stats_get_mask */
85 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
86 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
87 ef10_mac_stats_update /* emo_stats_update */
88 #endif /* EFSYS_OPT_MAC_STATS */
89 };
90 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
91
92 __checkReturn efx_rc_t
efx_mac_pdu_set(__in efx_nic_t * enp,__in size_t pdu)93 efx_mac_pdu_set(
94 __in efx_nic_t *enp,
95 __in size_t pdu)
96 {
97 efx_port_t *epp = &(enp->en_port);
98 const efx_mac_ops_t *emop = epp->ep_emop;
99 uint32_t old_pdu;
100 efx_rc_t rc;
101
102 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
103 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
104 EFSYS_ASSERT(emop != NULL);
105
106 if (pdu < EFX_MAC_PDU_MIN) {
107 rc = EINVAL;
108 goto fail1;
109 }
110
111 if (pdu > EFX_MAC_PDU_MAX) {
112 rc = EINVAL;
113 goto fail2;
114 }
115
116 old_pdu = epp->ep_mac_pdu;
117 epp->ep_mac_pdu = (uint32_t)pdu;
118 if ((rc = emop->emo_pdu_set(enp)) != 0)
119 goto fail3;
120
121 return (0);
122
123 fail3:
124 EFSYS_PROBE(fail3);
125
126 epp->ep_mac_pdu = old_pdu;
127
128 fail2:
129 EFSYS_PROBE(fail2);
130 fail1:
131 EFSYS_PROBE1(fail1, efx_rc_t, rc);
132
133 return (rc);
134 }
135
136 __checkReturn efx_rc_t
efx_mac_pdu_get(__in efx_nic_t * enp,__out size_t * pdu)137 efx_mac_pdu_get(
138 __in efx_nic_t *enp,
139 __out size_t *pdu)
140 {
141 efx_port_t *epp = &(enp->en_port);
142 const efx_mac_ops_t *emop = epp->ep_emop;
143 efx_rc_t rc;
144
145 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
146 goto fail1;
147
148 return (0);
149
150 fail1:
151 EFSYS_PROBE1(fail1, efx_rc_t, rc);
152
153 return (rc);
154 }
155
156 __checkReturn efx_rc_t
efx_mac_addr_set(__in efx_nic_t * enp,__in uint8_t * addr)157 efx_mac_addr_set(
158 __in efx_nic_t *enp,
159 __in uint8_t *addr)
160 {
161 efx_port_t *epp = &(enp->en_port);
162 const efx_mac_ops_t *emop = epp->ep_emop;
163 uint8_t old_addr[6];
164 uint32_t oui;
165 efx_rc_t rc;
166
167 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
168 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
169
170 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
171 rc = EINVAL;
172 goto fail1;
173 }
174
175 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
176 if (oui == 0x000000) {
177 rc = EINVAL;
178 goto fail2;
179 }
180
181 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
182 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
183 if ((rc = emop->emo_addr_set(enp)) != 0)
184 goto fail3;
185
186 return (0);
187
188 fail3:
189 EFSYS_PROBE(fail3);
190
191 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
192
193 fail2:
194 EFSYS_PROBE(fail2);
195 fail1:
196 EFSYS_PROBE1(fail1, efx_rc_t, rc);
197
198 return (rc);
199 }
200
201 __checkReturn efx_rc_t
efx_mac_filter_set(__in efx_nic_t * enp,__in boolean_t all_unicst,__in boolean_t mulcst,__in boolean_t all_mulcst,__in boolean_t brdcst)202 efx_mac_filter_set(
203 __in efx_nic_t *enp,
204 __in boolean_t all_unicst,
205 __in boolean_t mulcst,
206 __in boolean_t all_mulcst,
207 __in boolean_t brdcst)
208 {
209 efx_port_t *epp = &(enp->en_port);
210 const efx_mac_ops_t *emop = epp->ep_emop;
211 boolean_t old_all_unicst;
212 boolean_t old_mulcst;
213 boolean_t old_all_mulcst;
214 boolean_t old_brdcst;
215 efx_rc_t rc;
216
217 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
218 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
219
220 old_all_unicst = epp->ep_all_unicst;
221 old_mulcst = epp->ep_mulcst;
222 old_all_mulcst = epp->ep_all_mulcst;
223 old_brdcst = epp->ep_brdcst;
224
225 epp->ep_all_unicst = all_unicst;
226 epp->ep_mulcst = mulcst;
227 epp->ep_all_mulcst = all_mulcst;
228 epp->ep_brdcst = brdcst;
229
230 if ((rc = emop->emo_reconfigure(enp)) != 0)
231 goto fail1;
232
233 return (0);
234
235 fail1:
236 EFSYS_PROBE1(fail1, efx_rc_t, rc);
237
238 epp->ep_all_unicst = old_all_unicst;
239 epp->ep_mulcst = old_mulcst;
240 epp->ep_all_mulcst = old_all_mulcst;
241 epp->ep_brdcst = old_brdcst;
242
243 return (rc);
244 }
245
246 __checkReturn efx_rc_t
efx_mac_drain(__in efx_nic_t * enp,__in boolean_t enabled)247 efx_mac_drain(
248 __in efx_nic_t *enp,
249 __in boolean_t enabled)
250 {
251 efx_port_t *epp = &(enp->en_port);
252 const efx_mac_ops_t *emop = epp->ep_emop;
253 efx_rc_t rc;
254
255 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
256 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
257 EFSYS_ASSERT(emop != NULL);
258
259 if (epp->ep_mac_drain == enabled)
260 return (0);
261
262 epp->ep_mac_drain = enabled;
263
264 if ((rc = emop->emo_reconfigure(enp)) != 0)
265 goto fail1;
266
267 return (0);
268
269 fail1:
270 EFSYS_PROBE1(fail1, efx_rc_t, rc);
271
272 return (rc);
273 }
274
275 __checkReturn efx_rc_t
efx_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)276 efx_mac_up(
277 __in efx_nic_t *enp,
278 __out boolean_t *mac_upp)
279 {
280 efx_port_t *epp = &(enp->en_port);
281 const efx_mac_ops_t *emop = epp->ep_emop;
282 efx_rc_t rc;
283
284 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
285 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
286
287 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
288 goto fail1;
289
290 return (0);
291
292 fail1:
293 EFSYS_PROBE1(fail1, efx_rc_t, rc);
294
295 return (rc);
296 }
297
298 __checkReturn efx_rc_t
efx_mac_fcntl_set(__in efx_nic_t * enp,__in unsigned int fcntl,__in boolean_t autoneg)299 efx_mac_fcntl_set(
300 __in efx_nic_t *enp,
301 __in unsigned int fcntl,
302 __in boolean_t autoneg)
303 {
304 efx_port_t *epp = &(enp->en_port);
305 const efx_mac_ops_t *emop = epp->ep_emop;
306 const efx_phy_ops_t *epop = epp->ep_epop;
307 unsigned int old_fcntl;
308 boolean_t old_autoneg;
309 unsigned int old_adv_cap;
310 efx_rc_t rc;
311
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
314
315 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
316 rc = EINVAL;
317 goto fail1;
318 }
319
320 /*
321 * Ignore a request to set flow control auto-negotiation
322 * if the PHY doesn't support it.
323 */
324 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
325 autoneg = B_FALSE;
326
327 old_fcntl = epp->ep_fcntl;
328 old_autoneg = epp->ep_fcntl_autoneg;
329 old_adv_cap = epp->ep_adv_cap_mask;
330
331 epp->ep_fcntl = fcntl;
332 epp->ep_fcntl_autoneg = autoneg;
333
334 /*
335 * Always encode the flow control settings in the advertised
336 * capabilities even if we are not trying to auto-negotiate
337 * them and reconfigure both the PHY and the MAC.
338 */
339 if (fcntl & EFX_FCNTL_RESPOND)
340 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
341 1 << EFX_PHY_CAP_ASYM);
342 else
343 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
344 1 << EFX_PHY_CAP_ASYM);
345
346 if (fcntl & EFX_FCNTL_GENERATE)
347 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
348
349 if ((rc = epop->epo_reconfigure(enp)) != 0)
350 goto fail2;
351
352 if ((rc = emop->emo_reconfigure(enp)) != 0)
353 goto fail3;
354
355 return (0);
356
357 fail3:
358 EFSYS_PROBE(fail3);
359
360 fail2:
361 EFSYS_PROBE(fail2);
362
363 epp->ep_fcntl = old_fcntl;
364 epp->ep_fcntl_autoneg = old_autoneg;
365 epp->ep_adv_cap_mask = old_adv_cap;
366
367 fail1:
368 EFSYS_PROBE1(fail1, efx_rc_t, rc);
369
370 return (rc);
371 }
372
373 void
efx_mac_fcntl_get(__in efx_nic_t * enp,__out unsigned int * fcntl_wantedp,__out unsigned int * fcntl_linkp)374 efx_mac_fcntl_get(
375 __in efx_nic_t *enp,
376 __out unsigned int *fcntl_wantedp,
377 __out unsigned int *fcntl_linkp)
378 {
379 efx_port_t *epp = &(enp->en_port);
380 unsigned int wanted = 0;
381
382 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
383 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
384
385 /*
386 * Decode the requested flow control settings from the PHY
387 * advertised capabilities.
388 */
389 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
390 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
391 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
392 wanted ^= EFX_FCNTL_GENERATE;
393
394 *fcntl_linkp = epp->ep_fcntl;
395 *fcntl_wantedp = wanted;
396 }
397
398 __checkReturn efx_rc_t
399 efx_mac_multicast_list_set(
400 __in efx_nic_t *enp,
401 __in_ecount(6*count) uint8_t const *addrs,
402 __in int count)
403 {
404 efx_port_t *epp = &(enp->en_port);
405 const efx_mac_ops_t *emop = epp->ep_emop;
406 uint8_t *old_mulcst_addr_list = NULL;
407 uint32_t old_mulcst_addr_count;
408 efx_rc_t rc;
409
410 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
411 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
412
413 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
414 rc = EINVAL;
415 goto fail1;
416 }
417
418 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
419 if (old_mulcst_addr_count > 0) {
420 /* Allocate memory to store old list (instead of using stack) */
421 EFSYS_KMEM_ALLOC(enp->en_esip,
422 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
423 old_mulcst_addr_list);
424 if (old_mulcst_addr_list == NULL) {
425 rc = ENOMEM;
426 goto fail2;
427 }
428
429 /* Save the old list in case we need to rollback */
430 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
431 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
432 }
433
434 /* Store the new list */
435 memcpy(epp->ep_mulcst_addr_list, addrs,
436 count * EFX_MAC_ADDR_LEN);
437 epp->ep_mulcst_addr_count = count;
438
439 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
440 goto fail3;
441
442 if (old_mulcst_addr_count > 0) {
443 EFSYS_KMEM_FREE(enp->en_esip,
444 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
445 old_mulcst_addr_list);
446 }
447
448 return (0);
449
450 fail3:
451 EFSYS_PROBE(fail3);
452
453 /* Restore original list on failure */
454 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
455 if (old_mulcst_addr_count > 0) {
456 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
457 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
458
459 EFSYS_KMEM_FREE(enp->en_esip,
460 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
461 old_mulcst_addr_list);
462 }
463
464 fail2:
465 EFSYS_PROBE(fail2);
466
467 fail1:
468 EFSYS_PROBE1(fail1, efx_rc_t, rc);
469
470 return (rc);
471
472 }
473
474 __checkReturn efx_rc_t
efx_mac_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)475 efx_mac_filter_default_rxq_set(
476 __in efx_nic_t *enp,
477 __in efx_rxq_t *erp,
478 __in boolean_t using_rss)
479 {
480 efx_port_t *epp = &(enp->en_port);
481 const efx_mac_ops_t *emop = epp->ep_emop;
482 efx_rc_t rc;
483
484 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
485 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
486
487 if (emop->emo_filter_default_rxq_set != NULL) {
488 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
489 if (rc != 0)
490 goto fail1;
491 }
492
493 return (0);
494
495 fail1:
496 EFSYS_PROBE1(fail1, efx_rc_t, rc);
497
498 return (rc);
499 }
500
501 void
efx_mac_filter_default_rxq_clear(__in efx_nic_t * enp)502 efx_mac_filter_default_rxq_clear(
503 __in efx_nic_t *enp)
504 {
505 efx_port_t *epp = &(enp->en_port);
506 const efx_mac_ops_t *emop = epp->ep_emop;
507
508 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
509 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
510
511 if (emop->emo_filter_default_rxq_clear != NULL)
512 emop->emo_filter_default_rxq_clear(enp);
513 }
514
515
516 #if EFSYS_OPT_MAC_STATS
517
518 #if EFSYS_OPT_NAMES
519
520 /* START MKCONFIG GENERATED EfxMacStatNamesBlock c11b91b42f922516 */
521 static const char * const __efx_mac_stat_name[] = {
522 "rx_octets",
523 "rx_pkts",
524 "rx_unicst_pkts",
525 "rx_multicst_pkts",
526 "rx_brdcst_pkts",
527 "rx_pause_pkts",
528 "rx_le_64_pkts",
529 "rx_65_to_127_pkts",
530 "rx_128_to_255_pkts",
531 "rx_256_to_511_pkts",
532 "rx_512_to_1023_pkts",
533 "rx_1024_to_15xx_pkts",
534 "rx_ge_15xx_pkts",
535 "rx_errors",
536 "rx_fcs_errors",
537 "rx_drop_events",
538 "rx_false_carrier_errors",
539 "rx_symbol_errors",
540 "rx_align_errors",
541 "rx_internal_errors",
542 "rx_jabber_pkts",
543 "rx_lane0_char_err",
544 "rx_lane1_char_err",
545 "rx_lane2_char_err",
546 "rx_lane3_char_err",
547 "rx_lane0_disp_err",
548 "rx_lane1_disp_err",
549 "rx_lane2_disp_err",
550 "rx_lane3_disp_err",
551 "rx_match_fault",
552 "rx_nodesc_drop_cnt",
553 "tx_octets",
554 "tx_pkts",
555 "tx_unicst_pkts",
556 "tx_multicst_pkts",
557 "tx_brdcst_pkts",
558 "tx_pause_pkts",
559 "tx_le_64_pkts",
560 "tx_65_to_127_pkts",
561 "tx_128_to_255_pkts",
562 "tx_256_to_511_pkts",
563 "tx_512_to_1023_pkts",
564 "tx_1024_to_15xx_pkts",
565 "tx_ge_15xx_pkts",
566 "tx_errors",
567 "tx_sgl_col_pkts",
568 "tx_mult_col_pkts",
569 "tx_ex_col_pkts",
570 "tx_late_col_pkts",
571 "tx_def_pkts",
572 "tx_ex_def_pkts",
573 "pm_trunc_bb_overflow",
574 "pm_discard_bb_overflow",
575 "pm_trunc_vfifo_full",
576 "pm_discard_vfifo_full",
577 "pm_trunc_qbb",
578 "pm_discard_qbb",
579 "pm_discard_mapping",
580 "rxdp_q_disabled_pkts",
581 "rxdp_di_dropped_pkts",
582 "rxdp_streaming_pkts",
583 "rxdp_hlb_fetch",
584 "rxdp_hlb_wait",
585 "vadapter_rx_unicast_packets",
586 "vadapter_rx_unicast_bytes",
587 "vadapter_rx_multicast_packets",
588 "vadapter_rx_multicast_bytes",
589 "vadapter_rx_broadcast_packets",
590 "vadapter_rx_broadcast_bytes",
591 "vadapter_rx_bad_packets",
592 "vadapter_rx_bad_bytes",
593 "vadapter_rx_overflow",
594 "vadapter_tx_unicast_packets",
595 "vadapter_tx_unicast_bytes",
596 "vadapter_tx_multicast_packets",
597 "vadapter_tx_multicast_bytes",
598 "vadapter_tx_broadcast_packets",
599 "vadapter_tx_broadcast_bytes",
600 "vadapter_tx_bad_packets",
601 "vadapter_tx_bad_bytes",
602 "vadapter_tx_overflow",
603 };
604 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
605
606 __checkReturn const char *
efx_mac_stat_name(__in efx_nic_t * enp,__in unsigned int id)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
efx_mac_stats_mask_add_range(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in const struct efx_mac_stats_range * rngp)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
efx_mac_stats_mask_add_ranges(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in_ecount (rng_count)const struct efx_mac_stats_range * rngp,__in unsigned int rng_count)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
efx_mac_stats_get_mask(__in efx_nic_t * enp,__out_bcount (mask_size)uint32_t * maskp,__in size_t mask_size)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
efx_mac_stats_upload(__in efx_nic_t * enp,__in efsys_mem_t * esmp)720 efx_mac_stats_upload(
721 __in efx_nic_t *enp,
722 __in efsys_mem_t *esmp)
723 {
724 efx_port_t *epp = &(enp->en_port);
725 const efx_mac_ops_t *emop = epp->ep_emop;
726 efx_rc_t rc;
727
728 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
729 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
730 EFSYS_ASSERT(emop != NULL);
731
732 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
733 goto fail1;
734
735 return (0);
736
737 fail1:
738 EFSYS_PROBE1(fail1, efx_rc_t, rc);
739
740 return (rc);
741 }
742
743 __checkReturn efx_rc_t
efx_mac_stats_periodic(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint16_t period_ms,__in boolean_t events)744 efx_mac_stats_periodic(
745 __in efx_nic_t *enp,
746 __in efsys_mem_t *esmp,
747 __in uint16_t period_ms,
748 __in boolean_t events)
749 {
750 efx_port_t *epp = &(enp->en_port);
751 const efx_mac_ops_t *emop = epp->ep_emop;
752 efx_rc_t rc;
753
754 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
755 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
756
757 EFSYS_ASSERT(emop != NULL);
758
759 if (emop->emo_stats_periodic == NULL) {
760 rc = EINVAL;
761 goto fail1;
762 }
763
764 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
765 goto fail2;
766
767 return (0);
768
769 fail2:
770 EFSYS_PROBE(fail2);
771 fail1:
772 EFSYS_PROBE1(fail1, efx_rc_t, rc);
773
774 return (rc);
775 }
776
777
778 __checkReturn efx_rc_t
efx_mac_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MAC_NSTATS)efsys_stat_t * essp,__inout_opt uint32_t * generationp)779 efx_mac_stats_update(
780 __in efx_nic_t *enp,
781 __in efsys_mem_t *esmp,
782 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
783 __inout_opt uint32_t *generationp)
784 {
785 efx_port_t *epp = &(enp->en_port);
786 const efx_mac_ops_t *emop = epp->ep_emop;
787 efx_rc_t rc;
788
789 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
790 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
791 EFSYS_ASSERT(emop != NULL);
792
793 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
794
795 return (rc);
796 }
797
798 #endif /* EFSYS_OPT_MAC_STATS */
799
800 __checkReturn efx_rc_t
efx_mac_select(__in efx_nic_t * enp)801 efx_mac_select(
802 __in efx_nic_t *enp)
803 {
804 efx_port_t *epp = &(enp->en_port);
805 efx_mac_type_t type = EFX_MAC_INVALID;
806 const efx_mac_ops_t *emop;
807 int rc = EINVAL;
808
809 switch (enp->en_family) {
810 #if EFSYS_OPT_SIENA
811 case EFX_FAMILY_SIENA:
812 emop = &__efx_mac_siena_ops;
813 type = EFX_MAC_SIENA;
814 break;
815 #endif /* EFSYS_OPT_SIENA */
816
817 #if EFSYS_OPT_HUNTINGTON
818 case EFX_FAMILY_HUNTINGTON:
819 emop = &__efx_mac_ef10_ops;
820 type = EFX_MAC_HUNTINGTON;
821 break;
822 #endif /* EFSYS_OPT_HUNTINGTON */
823
824 #if EFSYS_OPT_MEDFORD
825 case EFX_FAMILY_MEDFORD:
826 emop = &__efx_mac_ef10_ops;
827 type = EFX_MAC_MEDFORD;
828 break;
829 #endif /* EFSYS_OPT_MEDFORD */
830
831 default:
832 rc = EINVAL;
833 goto fail1;
834 }
835
836 EFSYS_ASSERT(type != EFX_MAC_INVALID);
837 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
838 EFSYS_ASSERT(emop != NULL);
839
840 epp->ep_emop = emop;
841 epp->ep_mac_type = type;
842
843 return (0);
844
845 fail1:
846 EFSYS_PROBE1(fail1, efx_rc_t, rc);
847
848 return (rc);
849 }
850
851
852 #if EFSYS_OPT_SIENA
853
854 #define EFX_MAC_HASH_BITS (1 << 8)
855
856 /* Compute the multicast hash as used on Falcon and Siena. */
857 static void
858 siena_mac_multicast_hash_compute(
859 __in_ecount(6*count) uint8_t const *addrs,
860 __in int count,
861 __out efx_oword_t *hash_low,
862 __out efx_oword_t *hash_high)
863 {
864 uint32_t crc, index;
865 int i;
866
867 EFSYS_ASSERT(hash_low != NULL);
868 EFSYS_ASSERT(hash_high != NULL);
869
870 EFX_ZERO_OWORD(*hash_low);
871 EFX_ZERO_OWORD(*hash_high);
872
873 for (i = 0; i < count; i++) {
874 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
875 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
876 index = crc % EFX_MAC_HASH_BITS;
877 if (index < 128) {
878 EFX_SET_OWORD_BIT(*hash_low, index);
879 } else {
880 EFX_SET_OWORD_BIT(*hash_high, index - 128);
881 }
882
883 addrs += EFX_MAC_ADDR_LEN;
884 }
885 }
886
887 static __checkReturn efx_rc_t
siena_mac_multicast_list_set(__in efx_nic_t * enp)888 siena_mac_multicast_list_set(
889 __in efx_nic_t *enp)
890 {
891 efx_port_t *epp = &(enp->en_port);
892 const efx_mac_ops_t *emop = epp->ep_emop;
893 efx_oword_t old_hash[2];
894 efx_rc_t rc;
895
896 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
897 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
898
899 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
900
901 siena_mac_multicast_hash_compute(
902 epp->ep_mulcst_addr_list,
903 epp->ep_mulcst_addr_count,
904 &epp->ep_multicst_hash[0],
905 &epp->ep_multicst_hash[1]);
906
907 if ((rc = emop->emo_reconfigure(enp)) != 0)
908 goto fail1;
909
910 return (0);
911
912 fail1:
913 EFSYS_PROBE1(fail1, efx_rc_t, rc);
914
915 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
916
917 return (rc);
918 }
919
920 #endif /* EFSYS_OPT_SIENA */
921