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