xref: /freebsd/sys/dev/sfxge/common/efx_mac.c (revision 079171874c9bf263b69e3af10784ad2bcd1fe699)
1 /*-
2  * Copyright (c) 2007-2015 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$");
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_siena_mac_ops = {
47 	NULL,					/* emo_reset */
48 	siena_mac_poll,				/* emo_poll */
49 	siena_mac_up,				/* emo_up */
50 	siena_mac_reconfigure,			/* emo_addr_set */
51 	siena_mac_reconfigure,			/* emo_pdu_set */
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 	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
61 	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
62 	siena_mac_stats_update			/* emo_stats_update */
63 #endif	/* EFSYS_OPT_MAC_STATS */
64 };
65 #endif	/* EFSYS_OPT_SIENA */
66 
67 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
68 static const efx_mac_ops_t	__efx_ef10_mac_ops = {
69 	NULL,					/* emo_reset */
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_reconfigure,			/* emo_reconfigure */
75 	ef10_mac_multicast_list_set,		/* emo_multicast_list_set */
76 	ef10_mac_filter_default_rxq_set,	/* emo_filter_default_rxq_set */
77 	ef10_mac_filter_default_rxq_clear,
78 					/* emo_filter_default_rxq_clear */
79 #if EFSYS_OPT_LOOPBACK
80 	ef10_mac_loopback_set,			/* emo_loopback_set */
81 #endif	/* EFSYS_OPT_LOOPBACK */
82 #if EFSYS_OPT_MAC_STATS
83 	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
84 	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
85 	ef10_mac_stats_update			/* emo_stats_update */
86 #endif	/* EFSYS_OPT_MAC_STATS */
87 };
88 #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
89 
90 
91 	__checkReturn			efx_rc_t
92 efx_mac_pdu_set(
93 	__in				efx_nic_t *enp,
94 	__in				size_t pdu)
95 {
96 	efx_port_t *epp = &(enp->en_port);
97 	const efx_mac_ops_t *emop = epp->ep_emop;
98 	uint32_t old_pdu;
99 	efx_rc_t rc;
100 
101 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
102 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
103 	EFSYS_ASSERT(emop != NULL);
104 
105 	if (pdu < EFX_MAC_PDU_MIN) {
106 		rc = EINVAL;
107 		goto fail1;
108 	}
109 
110 	if (pdu > EFX_MAC_PDU_MAX) {
111 		rc = EINVAL;
112 		goto fail2;
113 	}
114 
115 	old_pdu = epp->ep_mac_pdu;
116 	epp->ep_mac_pdu = (uint32_t)pdu;
117 	if ((rc = emop->emo_pdu_set(enp)) != 0)
118 		goto fail3;
119 
120 	return (0);
121 
122 fail3:
123 	EFSYS_PROBE(fail3);
124 
125 	epp->ep_mac_pdu = old_pdu;
126 
127 fail2:
128 	EFSYS_PROBE(fail2);
129 fail1:
130 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
131 
132 	return (rc);
133 }
134 
135 	__checkReturn			efx_rc_t
136 efx_mac_addr_set(
137 	__in				efx_nic_t *enp,
138 	__in				uint8_t *addr)
139 {
140 	efx_port_t *epp = &(enp->en_port);
141 	const efx_mac_ops_t *emop = epp->ep_emop;
142 	uint8_t old_addr[6];
143 	uint32_t oui;
144 	efx_rc_t rc;
145 
146 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
148 
149 	if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
150 		rc = EINVAL;
151 		goto fail1;
152 	}
153 
154 	oui = addr[0] << 16 | addr[1] << 8 | addr[2];
155 	if (oui == 0x000000) {
156 		rc = EINVAL;
157 		goto fail2;
158 	}
159 
160 	EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
161 	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
162 	if ((rc = emop->emo_addr_set(enp)) != 0)
163 		goto fail3;
164 
165 	return (0);
166 
167 fail3:
168 	EFSYS_PROBE(fail3);
169 
170 	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
171 
172 fail2:
173 	EFSYS_PROBE(fail2);
174 fail1:
175 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
176 
177 	return (rc);
178 }
179 
180 	__checkReturn			efx_rc_t
181 efx_mac_filter_set(
182 	__in				efx_nic_t *enp,
183 	__in				boolean_t all_unicst,
184 	__in				boolean_t mulcst,
185 	__in				boolean_t all_mulcst,
186 	__in				boolean_t brdcst)
187 {
188 	efx_port_t *epp = &(enp->en_port);
189 	const efx_mac_ops_t *emop = epp->ep_emop;
190 	boolean_t old_all_unicst;
191 	boolean_t old_mulcst;
192 	boolean_t old_all_mulcst;
193 	boolean_t old_brdcst;
194 	efx_rc_t rc;
195 
196 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
198 
199 	old_all_unicst = epp->ep_all_unicst;
200 	old_mulcst = epp->ep_mulcst;
201 	old_all_mulcst = epp->ep_all_mulcst;
202 	old_brdcst = epp->ep_brdcst;
203 
204 	epp->ep_all_unicst = all_unicst;
205 	epp->ep_mulcst = mulcst;
206 	epp->ep_all_mulcst = all_mulcst;
207 	epp->ep_brdcst = brdcst;
208 
209 	if ((rc = emop->emo_reconfigure(enp)) != 0)
210 		goto fail1;
211 
212 	return (0);
213 
214 fail1:
215 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
216 
217 	epp->ep_all_unicst = old_all_unicst;
218 	epp->ep_mulcst = old_mulcst;
219 	epp->ep_all_mulcst = old_all_mulcst;
220 	epp->ep_brdcst = old_brdcst;
221 
222 	return (rc);
223 }
224 
225 	__checkReturn			efx_rc_t
226 efx_mac_drain(
227 	__in				efx_nic_t *enp,
228 	__in				boolean_t enabled)
229 {
230 	efx_port_t *epp = &(enp->en_port);
231 	const efx_mac_ops_t *emop = epp->ep_emop;
232 	efx_rc_t rc;
233 
234 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
235 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
236 	EFSYS_ASSERT(emop != NULL);
237 
238 	if (epp->ep_mac_drain == enabled)
239 		return (0);
240 
241 	epp->ep_mac_drain = enabled;
242 
243 	if (enabled && emop->emo_reset != NULL) {
244 		if ((rc = emop->emo_reset(enp)) != 0)
245 			goto fail1;
246 
247 		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
248 		enp->en_reset_flags &= ~EFX_RESET_PHY;
249 	}
250 
251 	if ((rc = emop->emo_reconfigure(enp)) != 0)
252 		goto fail2;
253 
254 	return (0);
255 
256 fail2:
257 	EFSYS_PROBE(fail2);
258 fail1:
259 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
260 
261 	return (rc);
262 }
263 
264 	__checkReturn	efx_rc_t
265 efx_mac_up(
266 	__in		efx_nic_t *enp,
267 	__out		boolean_t *mac_upp)
268 {
269 	efx_port_t *epp = &(enp->en_port);
270 	const efx_mac_ops_t *emop = epp->ep_emop;
271 	efx_rc_t rc;
272 
273 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
274 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
275 
276 	if ((rc = emop->emo_up(enp, mac_upp)) != 0)
277 		goto fail1;
278 
279 	return (0);
280 
281 fail1:
282 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
283 
284 	return (rc);
285 }
286 
287 	__checkReturn			efx_rc_t
288 efx_mac_fcntl_set(
289 	__in				efx_nic_t *enp,
290 	__in				unsigned int fcntl,
291 	__in				boolean_t autoneg)
292 {
293 	efx_port_t *epp = &(enp->en_port);
294 	const efx_mac_ops_t *emop = epp->ep_emop;
295 	const efx_phy_ops_t *epop = epp->ep_epop;
296 	unsigned int old_fcntl;
297 	boolean_t old_autoneg;
298 	unsigned int old_adv_cap;
299 	efx_rc_t rc;
300 
301 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
302 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
303 
304 	if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
305 		rc = EINVAL;
306 		goto fail1;
307 	}
308 
309 	/*
310 	 * Ignore a request to set flow control auto-negotiation
311 	 * if the PHY doesn't support it.
312 	 */
313 	if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
314 		autoneg = B_FALSE;
315 
316 	old_fcntl = epp->ep_fcntl;
317 	old_autoneg = epp->ep_fcntl_autoneg;
318 	old_adv_cap = epp->ep_adv_cap_mask;
319 
320 	epp->ep_fcntl = fcntl;
321 	epp->ep_fcntl_autoneg = autoneg;
322 
323 	/*
324 	 * Always encode the flow control settings in the advertised
325 	 * capabilities even if we are not trying to auto-negotiate
326 	 * them and reconfigure both the PHY and the MAC.
327 	 */
328 	if (fcntl & EFX_FCNTL_RESPOND)
329 		epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
330 					    1 << EFX_PHY_CAP_ASYM);
331 	else
332 		epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
333 					    1 << EFX_PHY_CAP_ASYM);
334 
335 	if (fcntl & EFX_FCNTL_GENERATE)
336 		epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
337 
338 	if ((rc = epop->epo_reconfigure(enp)) != 0)
339 		goto fail2;
340 
341 	if ((rc = emop->emo_reconfigure(enp)) != 0)
342 		goto fail3;
343 
344 	return (0);
345 
346 fail3:
347 	EFSYS_PROBE(fail3);
348 
349 fail2:
350 	EFSYS_PROBE(fail2);
351 
352 	epp->ep_fcntl = old_fcntl;
353 	epp->ep_fcntl_autoneg = old_autoneg;
354 	epp->ep_adv_cap_mask = old_adv_cap;
355 
356 fail1:
357 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
358 
359 	return (rc);
360 }
361 
362 			void
363 efx_mac_fcntl_get(
364 	__in		efx_nic_t *enp,
365 	__out		unsigned int *fcntl_wantedp,
366 	__out		unsigned int *fcntl_linkp)
367 {
368 	efx_port_t *epp = &(enp->en_port);
369 	unsigned int wanted = 0;
370 
371 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
372 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
373 
374 	/*
375 	 * Decode the requested flow control settings from the PHY
376 	 * advertised capabilities.
377 	 */
378 	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
379 		wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
380 	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
381 		wanted ^= EFX_FCNTL_GENERATE;
382 
383 	*fcntl_linkp = epp->ep_fcntl;
384 	*fcntl_wantedp = wanted;
385 }
386 
387 	__checkReturn	efx_rc_t
388 efx_mac_multicast_list_set(
389 	__in				efx_nic_t *enp,
390 	__in_ecount(6*count)		uint8_t const *addrs,
391 	__in				int count)
392 {
393 	efx_port_t *epp = &(enp->en_port);
394 	const efx_mac_ops_t *emop = epp->ep_emop;
395 	uint8_t	*old_mulcst_addr_list = NULL;
396 	uint32_t old_mulcst_addr_count;
397 	efx_rc_t rc;
398 
399 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
400 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
401 
402 	if (count > EFX_MAC_MULTICAST_LIST_MAX) {
403 		rc = EINVAL;
404 		goto fail1;
405 	}
406 
407 	old_mulcst_addr_count = epp->ep_mulcst_addr_count;
408 	if (old_mulcst_addr_count > 0) {
409 		/* Allocate memory to store old list (instead of using stack) */
410 		EFSYS_KMEM_ALLOC(enp->en_esip,
411 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
412 				old_mulcst_addr_list);
413 		if (old_mulcst_addr_list == NULL) {
414 			rc = ENOMEM;
415 			goto fail2;
416 		}
417 
418 		/* Save the old list in case we need to rollback */
419 		memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
420 			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
421 	}
422 
423 	/* Store the new list */
424 	memcpy(epp->ep_mulcst_addr_list, addrs,
425 		count * EFX_MAC_ADDR_LEN);
426 	epp->ep_mulcst_addr_count = count;
427 
428 	if ((rc = emop->emo_multicast_list_set(enp)) != 0)
429 		goto fail3;
430 
431 	if (old_mulcst_addr_count > 0) {
432 		EFSYS_KMEM_FREE(enp->en_esip,
433 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
434 				old_mulcst_addr_list);
435 	}
436 
437 	return (0);
438 
439 fail3:
440 	EFSYS_PROBE(fail3);
441 
442 	/* Restore original list on failure */
443 	epp->ep_mulcst_addr_count = old_mulcst_addr_count;
444 	if (old_mulcst_addr_count > 0) {
445 		memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
446 			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
447 
448 		EFSYS_KMEM_FREE(enp->en_esip,
449 				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
450 				old_mulcst_addr_list);
451 	}
452 
453 fail2:
454 	EFSYS_PROBE(fail2);
455 
456 fail1:
457 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
458 
459 	return (rc);
460 
461 }
462 
463 	__checkReturn	efx_rc_t
464 efx_mac_filter_default_rxq_set(
465 	__in		efx_nic_t *enp,
466 	__in		efx_rxq_t *erp,
467 	__in		boolean_t using_rss)
468 {
469 	efx_port_t *epp = &(enp->en_port);
470 	const efx_mac_ops_t *emop = epp->ep_emop;
471 	efx_rc_t rc;
472 
473 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
474 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
475 
476 	if (emop->emo_filter_default_rxq_set != NULL) {
477 		rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
478 		if (rc != 0)
479 			goto fail1;
480 	}
481 
482 	return (0);
483 
484 fail1:
485 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
486 
487 	return (rc);
488 }
489 
490 			void
491 efx_mac_filter_default_rxq_clear(
492 	__in		efx_nic_t *enp)
493 {
494 	efx_port_t *epp = &(enp->en_port);
495 	const efx_mac_ops_t *emop = epp->ep_emop;
496 
497 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
498 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
499 
500 	if (emop->emo_filter_default_rxq_clear != NULL)
501 		emop->emo_filter_default_rxq_clear(enp);
502 }
503 
504 
505 #if EFSYS_OPT_MAC_STATS
506 
507 #if EFSYS_OPT_NAMES
508 
509 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
510 static const char 	*__efx_mac_stat_name[] = {
511 	"rx_octets",
512 	"rx_pkts",
513 	"rx_unicst_pkts",
514 	"rx_multicst_pkts",
515 	"rx_brdcst_pkts",
516 	"rx_pause_pkts",
517 	"rx_le_64_pkts",
518 	"rx_65_to_127_pkts",
519 	"rx_128_to_255_pkts",
520 	"rx_256_to_511_pkts",
521 	"rx_512_to_1023_pkts",
522 	"rx_1024_to_15xx_pkts",
523 	"rx_ge_15xx_pkts",
524 	"rx_errors",
525 	"rx_fcs_errors",
526 	"rx_drop_events",
527 	"rx_false_carrier_errors",
528 	"rx_symbol_errors",
529 	"rx_align_errors",
530 	"rx_internal_errors",
531 	"rx_jabber_pkts",
532 	"rx_lane0_char_err",
533 	"rx_lane1_char_err",
534 	"rx_lane2_char_err",
535 	"rx_lane3_char_err",
536 	"rx_lane0_disp_err",
537 	"rx_lane1_disp_err",
538 	"rx_lane2_disp_err",
539 	"rx_lane3_disp_err",
540 	"rx_match_fault",
541 	"rx_nodesc_drop_cnt",
542 	"tx_octets",
543 	"tx_pkts",
544 	"tx_unicst_pkts",
545 	"tx_multicst_pkts",
546 	"tx_brdcst_pkts",
547 	"tx_pause_pkts",
548 	"tx_le_64_pkts",
549 	"tx_65_to_127_pkts",
550 	"tx_128_to_255_pkts",
551 	"tx_256_to_511_pkts",
552 	"tx_512_to_1023_pkts",
553 	"tx_1024_to_15xx_pkts",
554 	"tx_ge_15xx_pkts",
555 	"tx_errors",
556 	"tx_sgl_col_pkts",
557 	"tx_mult_col_pkts",
558 	"tx_ex_col_pkts",
559 	"tx_late_col_pkts",
560 	"tx_def_pkts",
561 	"tx_ex_def_pkts",
562 	"pm_trunc_bb_overflow",
563 	"pm_discard_bb_overflow",
564 	"pm_trunc_vfifo_full",
565 	"pm_discard_vfifo_full",
566 	"pm_trunc_qbb",
567 	"pm_discard_qbb",
568 	"pm_discard_mapping",
569 	"rxdp_q_disabled_pkts",
570 	"rxdp_di_dropped_pkts",
571 	"rxdp_streaming_pkts",
572 	"rxdp_hlb_fetch",
573 	"rxdp_hlb_wait",
574 	"vadapter_rx_unicast_packets",
575 	"vadapter_rx_unicast_bytes",
576 	"vadapter_rx_multicast_packets",
577 	"vadapter_rx_multicast_bytes",
578 	"vadapter_rx_broadcast_packets",
579 	"vadapter_rx_broadcast_bytes",
580 	"vadapter_rx_bad_packets",
581 	"vadapter_rx_bad_bytes",
582 	"vadapter_rx_overflow",
583 	"vadapter_tx_unicast_packets",
584 	"vadapter_tx_unicast_bytes",
585 	"vadapter_tx_multicast_packets",
586 	"vadapter_tx_multicast_bytes",
587 	"vadapter_tx_broadcast_packets",
588 	"vadapter_tx_broadcast_bytes",
589 	"vadapter_tx_bad_packets",
590 	"vadapter_tx_bad_bytes",
591 	"vadapter_tx_overflow",
592 };
593 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
594 
595 	__checkReturn			const char *
596 efx_mac_stat_name(
597 	__in				efx_nic_t *enp,
598 	__in				unsigned int id)
599 {
600 	_NOTE(ARGUNUSED(enp))
601 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
602 
603 	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
604 	return (__efx_mac_stat_name[id]);
605 }
606 
607 #endif	/* EFSYS_OPT_NAMES */
608 
609 	__checkReturn			efx_rc_t
610 efx_mac_stats_upload(
611 	__in				efx_nic_t *enp,
612 	__in				efsys_mem_t *esmp)
613 {
614 	efx_port_t *epp = &(enp->en_port);
615 	const efx_mac_ops_t *emop = epp->ep_emop;
616 	efx_rc_t rc;
617 
618 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
619 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
620 	EFSYS_ASSERT(emop != NULL);
621 
622 	/*
623 	 * Don't assert !ep_mac_stats_pending, because the client might
624 	 * have failed to finalise statistics when previously stopping
625 	 * the port.
626 	 */
627 	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
628 		goto fail1;
629 
630 	epp->ep_mac_stats_pending = B_TRUE;
631 
632 	return (0);
633 
634 fail1:
635 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
636 
637 	return (rc);
638 }
639 
640 	__checkReturn			efx_rc_t
641 efx_mac_stats_periodic(
642 	__in				efx_nic_t *enp,
643 	__in				efsys_mem_t *esmp,
644 	__in				uint16_t period_ms,
645 	__in				boolean_t events)
646 {
647 	efx_port_t *epp = &(enp->en_port);
648 	const efx_mac_ops_t *emop = epp->ep_emop;
649 	efx_rc_t rc;
650 
651 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
652 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
653 
654 	EFSYS_ASSERT(emop != NULL);
655 
656 	if (emop->emo_stats_periodic == NULL) {
657 		rc = EINVAL;
658 		goto fail1;
659 	}
660 
661 	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
662 		goto fail2;
663 
664 	return (0);
665 
666 fail2:
667 	EFSYS_PROBE(fail2);
668 fail1:
669 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
670 
671 	return (rc);
672 }
673 
674 
675 	__checkReturn			efx_rc_t
676 efx_mac_stats_update(
677 	__in				efx_nic_t *enp,
678 	__in				efsys_mem_t *esmp,
679 	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
680 	__inout_opt			uint32_t *generationp)
681 {
682 	efx_port_t *epp = &(enp->en_port);
683 	const efx_mac_ops_t *emop = epp->ep_emop;
684 	efx_rc_t rc;
685 
686 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
687 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
688 	EFSYS_ASSERT(emop != NULL);
689 
690 	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
691 	if (rc == 0)
692 		epp->ep_mac_stats_pending = B_FALSE;
693 
694 	return (rc);
695 }
696 
697 #endif	/* EFSYS_OPT_MAC_STATS */
698 
699 	__checkReturn			efx_rc_t
700 efx_mac_select(
701 	__in				efx_nic_t *enp)
702 {
703 	efx_port_t *epp = &(enp->en_port);
704 	efx_mac_type_t type = EFX_MAC_INVALID;
705 	const efx_mac_ops_t *emop;
706 	int rc = EINVAL;
707 
708 	switch (enp->en_family) {
709 #if EFSYS_OPT_SIENA
710 	case EFX_FAMILY_SIENA:
711 		emop = &__efx_siena_mac_ops;
712 		type = EFX_MAC_SIENA;
713 		break;
714 #endif /* EFSYS_OPT_SIENA */
715 
716 #if EFSYS_OPT_HUNTINGTON
717 	case EFX_FAMILY_HUNTINGTON:
718 		emop = &__efx_ef10_mac_ops;
719 		type = EFX_MAC_HUNTINGTON;
720 		break;
721 #endif /* EFSYS_OPT_HUNTINGTON */
722 
723 #if EFSYS_OPT_MEDFORD
724 	case EFX_FAMILY_MEDFORD:
725 		emop = &__efx_ef10_mac_ops;
726 		type = EFX_MAC_MEDFORD;
727 		break;
728 #endif /* EFSYS_OPT_MEDFORD */
729 
730 	default:
731 		rc = EINVAL;
732 		goto fail1;
733 	}
734 
735 	EFSYS_ASSERT(type != EFX_MAC_INVALID);
736 	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
737 	EFSYS_ASSERT(emop != NULL);
738 
739 	epp->ep_emop = emop;
740 	epp->ep_mac_type = type;
741 
742 	if (emop->emo_reset != NULL) {
743 		if ((rc = emop->emo_reset(enp)) != 0)
744 			goto fail2;
745 
746 		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
747 		enp->en_reset_flags &= ~EFX_RESET_MAC;
748 	}
749 
750 	return (0);
751 
752 fail2:
753 	EFSYS_PROBE(fail2);
754 fail1:
755 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
756 
757 	return (rc);
758 }
759 
760 
761 #if EFSYS_OPT_SIENA
762 
763 #define	EFX_MAC_HASH_BITS	(1 << 8)
764 
765 /* Compute the multicast hash as used on Falcon and Siena. */
766 static	void
767 siena_mac_multicast_hash_compute(
768 	__in_ecount(6*count)		uint8_t const *addrs,
769 	__in				int count,
770 	__out				efx_oword_t *hash_low,
771 	__out				efx_oword_t *hash_high)
772 {
773 	uint32_t crc, index;
774 	int i;
775 
776 	EFSYS_ASSERT(hash_low != NULL);
777 	EFSYS_ASSERT(hash_high != NULL);
778 
779 	EFX_ZERO_OWORD(*hash_low);
780 	EFX_ZERO_OWORD(*hash_high);
781 
782 	for (i = 0; i < count; i++) {
783 		/* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
784 		crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
785 		index = crc % EFX_MAC_HASH_BITS;
786 		if (index < 128) {
787 			EFX_SET_OWORD_BIT(*hash_low, index);
788 		} else {
789 			EFX_SET_OWORD_BIT(*hash_high, index - 128);
790 		}
791 
792 		addrs += EFX_MAC_ADDR_LEN;
793 	}
794 }
795 
796 static	__checkReturn	efx_rc_t
797 siena_mac_multicast_list_set(
798 	__in		efx_nic_t *enp)
799 {
800 	efx_port_t *epp = &(enp->en_port);
801 	const efx_mac_ops_t *emop = epp->ep_emop;
802 	efx_oword_t old_hash[2];
803 	efx_rc_t rc;
804 
805 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
806 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
807 
808 	memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
809 
810 	siena_mac_multicast_hash_compute(
811 	    epp->ep_mulcst_addr_list,
812 	    epp->ep_mulcst_addr_count,
813 	    &epp->ep_multicst_hash[0],
814 	    &epp->ep_multicst_hash[1]);
815 
816 	if ((rc = emop->emo_reconfigure(enp)) != 0)
817 		goto fail1;
818 
819 	return (0);
820 
821 fail1:
822 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
823 
824 	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
825 
826 	return (rc);
827 }
828 
829 #endif /* EFSYS_OPT_SIENA */
830