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