efx_mac.c revision 291397
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: head/sys/dev/sfxge/common/efx_mac.c 291397 2015-11-27 16:21:14Z arybchik $");
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
49static	__checkReturn	int
50falconsiena_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
56static 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
77static 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
98static 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
119static 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
140static 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
170efx_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
200fail3:
201	EFSYS_PROBE(fail3);
202
203	epp->ep_mac_pdu = old_pdu;
204
205fail2:
206	EFSYS_PROBE(fail2);
207fail1:
208	EFSYS_PROBE1(fail1, int, rc);
209
210	return (rc);
211}
212
213	__checkReturn			int
214efx_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
245fail3:
246	EFSYS_PROBE(fail3);
247
248	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
249
250fail2:
251	EFSYS_PROBE(fail2);
252fail1:
253	EFSYS_PROBE1(fail1, int, rc);
254
255	return (rc);
256}
257
258	__checkReturn			int
259efx_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
292fail1:
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
304efx_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
334fail2:
335	EFSYS_PROBE(fail2);
336fail1:
337	EFSYS_PROBE1(fail1, int, rc);
338
339	return (rc);
340}
341
342	__checkReturn	int
343efx_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
359fail1:
360	EFSYS_PROBE1(fail1, int, rc);
361
362	return (rc);
363}
364
365	__checkReturn			int
366efx_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
424fail3:
425	EFSYS_PROBE(fail3);
426
427fail2:
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
434fail1:
435	EFSYS_PROBE1(fail1, int, rc);
436
437	return (rc);
438}
439
440			void
441efx_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
472efx_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
506fail1:
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
515efx_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
566fail3:
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
580fail2:
581	EFSYS_PROBE(fail2);
582
583fail1:
584	EFSYS_PROBE1(fail1, int, rc);
585
586	return (rc);
587
588}
589
590	__checkReturn	int
591efx_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
611fail1:
612	EFSYS_PROBE1(fail1, int, rc);
613
614	return (rc);
615}
616
617			void
618efx_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 */
637static 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 *
723efx_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
737efx_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
761fail1:
762	EFSYS_PROBE1(fail1, int, rc);
763
764	return (rc);
765}
766
767	__checkReturn			int
768efx_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
793fail2:
794	EFSYS_PROBE(fail2);
795fail1:
796	EFSYS_PROBE1(fail1, int, rc);
797
798	return (rc);
799}
800
801
802	__checkReturn			int
803efx_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	__inout_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
827efx_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
888chosen:
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
906fail1:
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. */
916static	void
917falconsiena_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
946static	__checkReturn	int
947falconsiena_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
970fail1:
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