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