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