efx_mac.c revision 299609
156638Srwatson/*-
2196123Srwatson * Copyright (c) 2007-2015 Solarflare Communications Inc.
356638Srwatson * All rights reserved.
456638Srwatson *
556638Srwatson * Redistribution and use in source and binary forms, with or without
656638Srwatson * modification, are permitted provided that the following conditions are met:
756638Srwatson *
856638Srwatson * 1. Redistributions of source code must retain the above copyright notice,
956638Srwatson *    this list of conditions and the following disclaimer.
1056638Srwatson * 2. Redistributions in binary form must reproduce the above copyright notice,
1156638Srwatson *    this list of conditions and the following disclaimer in the documentation
1256638Srwatson *    and/or other materials provided with the distribution.
1356638Srwatson *
1456638Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1556638Srwatson * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1656638Srwatson * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1756638Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1856638Srwatson * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1956638Srwatson * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2056638Srwatson * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2156638Srwatson * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2256638Srwatson * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2356638Srwatson * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2456638Srwatson * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2556638Srwatson *
2667035Srwatson * The views and conclusions contained in the software and documentation are
2756638Srwatson * those of the authors and should not be interpreted as representing official
28196123Srwatson * policies, either expressed or implied, of the FreeBSD Project.
2956638Srwatson */
3079531Sru
3156638Srwatson#include <sys/cdefs.h>
3256791Smpp__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_mac.c 299609 2016-05-13 07:15:02Z arybchik $");
3356791Smpp
3459514Sphantom#include "efx.h"
3575222Sru#include "efx_impl.h"
3656638Srwatson
3784306Sru#if EFSYS_OPT_SIENA
3884306Sru
39105671Srwatsonstatic	__checkReturn	efx_rc_t
4056638Srwatsonsiena_mac_multicast_list_set(
41196123Srwatson	__in		efx_nic_t *enp);
42196123Srwatson
43196123Srwatson#endif /* EFSYS_OPT_SIENA */
44196123Srwatson
45196123Srwatson#if EFSYS_OPT_SIENA
4670481Srustatic const efx_mac_ops_t	__efx_siena_mac_ops = {
47106432Srwatson	NULL,					/* emo_reset */
48196123Srwatson	siena_mac_poll,				/* emo_poll */
49196123Srwatson	siena_mac_up,				/* emo_up */
50196123Srwatson	siena_mac_reconfigure,			/* emo_addr_set */
51196123Srwatson	siena_mac_reconfigure,			/* emo_pdu_set */
52196123Srwatson	siena_mac_reconfigure,			/* emo_reconfigure */
53196123Srwatson	siena_mac_multicast_list_set,		/* emo_multicast_list_set */
5470481Sru	NULL,					/* emo_filter_set_default_rxq */
55196123Srwatson	NULL,				/* emo_filter_default_rxq_clear */
56196123Srwatson#if EFSYS_OPT_LOOPBACK
57196123Srwatson	siena_mac_loopback_set,			/* emo_loopback_set */
58196123Srwatson#endif	/* EFSYS_OPT_LOOPBACK */
59106432Srwatson#if EFSYS_OPT_MAC_STATS
60196123Srwatson	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
61196123Srwatson	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
62196123Srwatson	siena_mac_stats_update			/* emo_stats_update */
63196123Srwatson#endif	/* EFSYS_OPT_MAC_STATS */
64196123Srwatson};
65196123Srwatson#endif	/* EFSYS_OPT_SIENA */
66196123Srwatson
67196123Srwatson#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
6856638Srwatsonstatic const efx_mac_ops_t	__efx_ef10_mac_ops = {
69196123Srwatson	NULL,					/* emo_reset */
70105829Schris	ef10_mac_poll,				/* emo_poll */
71196123Srwatson	ef10_mac_up,				/* emo_up */
72196123Srwatson	ef10_mac_addr_set,			/* emo_addr_set */
73196123Srwatson	ef10_mac_pdu_set,			/* emo_pdu_set */
74196123Srwatson	ef10_mac_reconfigure,			/* emo_reconfigure */
75196123Srwatson	ef10_mac_multicast_list_set,		/* emo_multicast_list_set */
76105829Schris	ef10_mac_filter_default_rxq_set,	/* emo_filter_default_rxq_set */
77196123Srwatson	ef10_mac_filter_default_rxq_clear,
78196123Srwatson					/* emo_filter_default_rxq_clear */
79106432Srwatson#if EFSYS_OPT_LOOPBACK
80196123Srwatson	ef10_mac_loopback_set,			/* emo_loopback_set */
81196123Srwatson#endif	/* EFSYS_OPT_LOOPBACK */
82196123Srwatson#if EFSYS_OPT_MAC_STATS
83196123Srwatson	efx_mcdi_mac_stats_upload,		/* emo_stats_upload */
84196123Srwatson	efx_mcdi_mac_stats_periodic,		/* emo_stats_periodic */
85196123Srwatson	ef10_mac_stats_update			/* emo_stats_update */
8656638Srwatson#endif	/* EFSYS_OPT_MAC_STATS */
87196123Srwatson};
88196123Srwatson#endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
89107826Sru
9056638Srwatson
91196123Srwatson	__checkReturn			efx_rc_t
92192410Sbruefferefx_mac_pdu_set(
93101554Srwatson	__in				efx_nic_t *enp,
94196123Srwatson	__in				size_t pdu)
95196123Srwatson{
96196123Srwatson	efx_port_t *epp = &(enp->en_port);
97196123Srwatson	const efx_mac_ops_t *emop = epp->ep_emop;
9856638Srwatson	uint32_t old_pdu;
99105671Srwatson	efx_rc_t rc;
100105671Srwatson
10156638Srwatson	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
102105829Schris	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
10356638Srwatson	EFSYS_ASSERT(emop != NULL);
10456791Smpp
105106432Srwatson	if (pdu < EFX_MAC_PDU_MIN) {
106196123Srwatson		rc = EINVAL;
107106432Srwatson		goto fail1;
10856638Srwatson	}
10983327Sru
11083327Sru	if (pdu > EFX_MAC_PDU_MAX) {
11183327Sru		rc = EINVAL;
11256791Smpp		goto fail2;
113	}
114
115	old_pdu = epp->ep_mac_pdu;
116	epp->ep_mac_pdu = (uint32_t)pdu;
117	if ((rc = emop->emo_pdu_set(enp)) != 0)
118		goto fail3;
119
120	return (0);
121
122fail3:
123	EFSYS_PROBE(fail3);
124
125	epp->ep_mac_pdu = old_pdu;
126
127fail2:
128	EFSYS_PROBE(fail2);
129fail1:
130	EFSYS_PROBE1(fail1, efx_rc_t, rc);
131
132	return (rc);
133}
134
135	__checkReturn			efx_rc_t
136efx_mac_addr_set(
137	__in				efx_nic_t *enp,
138	__in				uint8_t *addr)
139{
140	efx_port_t *epp = &(enp->en_port);
141	const efx_mac_ops_t *emop = epp->ep_emop;
142	uint8_t old_addr[6];
143	uint32_t oui;
144	efx_rc_t rc;
145
146	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
148
149	if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
150		rc = EINVAL;
151		goto fail1;
152	}
153
154	oui = addr[0] << 16 | addr[1] << 8 | addr[2];
155	if (oui == 0x000000) {
156		rc = EINVAL;
157		goto fail2;
158	}
159
160	EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
161	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
162	if ((rc = emop->emo_addr_set(enp)) != 0)
163		goto fail3;
164
165	return (0);
166
167fail3:
168	EFSYS_PROBE(fail3);
169
170	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
171
172fail2:
173	EFSYS_PROBE(fail2);
174fail1:
175	EFSYS_PROBE1(fail1, efx_rc_t, rc);
176
177	return (rc);
178}
179
180	__checkReturn			efx_rc_t
181efx_mac_filter_set(
182	__in				efx_nic_t *enp,
183	__in				boolean_t all_unicst,
184	__in				boolean_t mulcst,
185	__in				boolean_t all_mulcst,
186	__in				boolean_t brdcst)
187{
188	efx_port_t *epp = &(enp->en_port);
189	const efx_mac_ops_t *emop = epp->ep_emop;
190	boolean_t old_all_unicst;
191	boolean_t old_mulcst;
192	boolean_t old_all_mulcst;
193	boolean_t old_brdcst;
194	efx_rc_t rc;
195
196	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
197	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
198
199	old_all_unicst = epp->ep_all_unicst;
200	old_mulcst = epp->ep_mulcst;
201	old_all_mulcst = epp->ep_all_mulcst;
202	old_brdcst = epp->ep_brdcst;
203
204	epp->ep_all_unicst = all_unicst;
205	epp->ep_mulcst = mulcst;
206	epp->ep_all_mulcst = all_mulcst;
207	epp->ep_brdcst = brdcst;
208
209	if ((rc = emop->emo_reconfigure(enp)) != 0)
210		goto fail1;
211
212	return (0);
213
214fail1:
215	EFSYS_PROBE1(fail1, efx_rc_t, rc);
216
217	epp->ep_all_unicst = old_all_unicst;
218	epp->ep_mulcst = old_mulcst;
219	epp->ep_all_mulcst = old_all_mulcst;
220	epp->ep_brdcst = old_brdcst;
221
222	return (rc);
223}
224
225	__checkReturn			efx_rc_t
226efx_mac_drain(
227	__in				efx_nic_t *enp,
228	__in				boolean_t enabled)
229{
230	efx_port_t *epp = &(enp->en_port);
231	const efx_mac_ops_t *emop = epp->ep_emop;
232	efx_rc_t rc;
233
234	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
235	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
236	EFSYS_ASSERT(emop != NULL);
237
238	if (epp->ep_mac_drain == enabled)
239		return (0);
240
241	epp->ep_mac_drain = enabled;
242
243	if (enabled && emop->emo_reset != NULL) {
244		if ((rc = emop->emo_reset(enp)) != 0)
245			goto fail1;
246
247		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
248		enp->en_reset_flags &= ~EFX_RESET_PHY;
249	}
250
251	if ((rc = emop->emo_reconfigure(enp)) != 0)
252		goto fail2;
253
254	return (0);
255
256fail2:
257	EFSYS_PROBE(fail2);
258fail1:
259	EFSYS_PROBE1(fail1, efx_rc_t, rc);
260
261	return (rc);
262}
263
264	__checkReturn	efx_rc_t
265efx_mac_up(
266	__in		efx_nic_t *enp,
267	__out		boolean_t *mac_upp)
268{
269	efx_port_t *epp = &(enp->en_port);
270	const efx_mac_ops_t *emop = epp->ep_emop;
271	efx_rc_t rc;
272
273	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
274	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
275
276	if ((rc = emop->emo_up(enp, mac_upp)) != 0)
277		goto fail1;
278
279	return (0);
280
281fail1:
282	EFSYS_PROBE1(fail1, efx_rc_t, rc);
283
284	return (rc);
285}
286
287	__checkReturn			efx_rc_t
288efx_mac_fcntl_set(
289	__in				efx_nic_t *enp,
290	__in				unsigned int fcntl,
291	__in				boolean_t autoneg)
292{
293	efx_port_t *epp = &(enp->en_port);
294	const efx_mac_ops_t *emop = epp->ep_emop;
295	const efx_phy_ops_t *epop = epp->ep_epop;
296	unsigned int old_fcntl;
297	boolean_t old_autoneg;
298	unsigned int old_adv_cap;
299	efx_rc_t rc;
300
301	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
302	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
303
304	if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
305		rc = EINVAL;
306		goto fail1;
307	}
308
309	/*
310	 * Ignore a request to set flow control auto-negotiation
311	 * if the PHY doesn't support it.
312	 */
313	if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
314		autoneg = B_FALSE;
315
316	old_fcntl = epp->ep_fcntl;
317	old_autoneg = epp->ep_fcntl_autoneg;
318	old_adv_cap = epp->ep_adv_cap_mask;
319
320	epp->ep_fcntl = fcntl;
321	epp->ep_fcntl_autoneg = autoneg;
322
323	/*
324	 * Always encode the flow control settings in the advertised
325	 * capabilities even if we are not trying to auto-negotiate
326	 * them and reconfigure both the PHY and the MAC.
327	 */
328	if (fcntl & EFX_FCNTL_RESPOND)
329		epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
330					    1 << EFX_PHY_CAP_ASYM);
331	else
332		epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
333					    1 << EFX_PHY_CAP_ASYM);
334
335	if (fcntl & EFX_FCNTL_GENERATE)
336		epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
337
338	if ((rc = epop->epo_reconfigure(enp)) != 0)
339		goto fail2;
340
341	if ((rc = emop->emo_reconfigure(enp)) != 0)
342		goto fail3;
343
344	return (0);
345
346fail3:
347	EFSYS_PROBE(fail3);
348
349fail2:
350	EFSYS_PROBE(fail2);
351
352	epp->ep_fcntl = old_fcntl;
353	epp->ep_fcntl_autoneg = old_autoneg;
354	epp->ep_adv_cap_mask = old_adv_cap;
355
356fail1:
357	EFSYS_PROBE1(fail1, efx_rc_t, rc);
358
359	return (rc);
360}
361
362			void
363efx_mac_fcntl_get(
364	__in		efx_nic_t *enp,
365	__out		unsigned int *fcntl_wantedp,
366	__out		unsigned int *fcntl_linkp)
367{
368	efx_port_t *epp = &(enp->en_port);
369	unsigned int wanted = 0;
370
371	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
372	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
373
374	/*
375	 * Decode the requested flow control settings from the PHY
376	 * advertised capabilities.
377	 */
378	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
379		wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
380	if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
381		wanted ^= EFX_FCNTL_GENERATE;
382
383	*fcntl_linkp = epp->ep_fcntl;
384	*fcntl_wantedp = wanted;
385}
386
387	__checkReturn	efx_rc_t
388efx_mac_multicast_list_set(
389	__in				efx_nic_t *enp,
390	__in_ecount(6*count)		uint8_t const *addrs,
391	__in				int count)
392{
393	efx_port_t *epp = &(enp->en_port);
394	const efx_mac_ops_t *emop = epp->ep_emop;
395	uint8_t	*old_mulcst_addr_list = NULL;
396	uint32_t old_mulcst_addr_count;
397	efx_rc_t rc;
398
399	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
400	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
401
402	if (count > EFX_MAC_MULTICAST_LIST_MAX) {
403		rc = EINVAL;
404		goto fail1;
405	}
406
407	old_mulcst_addr_count = epp->ep_mulcst_addr_count;
408	if (old_mulcst_addr_count > 0) {
409		/* Allocate memory to store old list (instead of using stack) */
410		EFSYS_KMEM_ALLOC(enp->en_esip,
411				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
412				old_mulcst_addr_list);
413		if (old_mulcst_addr_list == NULL) {
414			rc = ENOMEM;
415			goto fail2;
416		}
417
418		/* Save the old list in case we need to rollback */
419		memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
420			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
421	}
422
423	/* Store the new list */
424	memcpy(epp->ep_mulcst_addr_list, addrs,
425		count * EFX_MAC_ADDR_LEN);
426	epp->ep_mulcst_addr_count = count;
427
428	if ((rc = emop->emo_multicast_list_set(enp)) != 0)
429		goto fail3;
430
431	if (old_mulcst_addr_count > 0) {
432		EFSYS_KMEM_FREE(enp->en_esip,
433				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
434				old_mulcst_addr_list);
435	}
436
437	return (0);
438
439fail3:
440	EFSYS_PROBE(fail3);
441
442	/* Restore original list on failure */
443	epp->ep_mulcst_addr_count = old_mulcst_addr_count;
444	if (old_mulcst_addr_count > 0) {
445		memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
446			old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
447
448		EFSYS_KMEM_FREE(enp->en_esip,
449				old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
450				old_mulcst_addr_list);
451	}
452
453fail2:
454	EFSYS_PROBE(fail2);
455
456fail1:
457	EFSYS_PROBE1(fail1, efx_rc_t, rc);
458
459	return (rc);
460
461}
462
463	__checkReturn	efx_rc_t
464efx_mac_filter_default_rxq_set(
465	__in		efx_nic_t *enp,
466	__in		efx_rxq_t *erp,
467	__in		boolean_t using_rss)
468{
469	efx_port_t *epp = &(enp->en_port);
470	const efx_mac_ops_t *emop = epp->ep_emop;
471	efx_rc_t rc;
472
473	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
474	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
475
476	if (emop->emo_filter_default_rxq_set != NULL) {
477		rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
478		if (rc != 0)
479			goto fail1;
480	}
481
482	return (0);
483
484fail1:
485	EFSYS_PROBE1(fail1, efx_rc_t, rc);
486
487	return (rc);
488}
489
490			void
491efx_mac_filter_default_rxq_clear(
492	__in		efx_nic_t *enp)
493{
494	efx_port_t *epp = &(enp->en_port);
495	const efx_mac_ops_t *emop = epp->ep_emop;
496
497	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
498	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
499
500	if (emop->emo_filter_default_rxq_clear != NULL)
501		emop->emo_filter_default_rxq_clear(enp);
502}
503
504
505#if EFSYS_OPT_MAC_STATS
506
507#if EFSYS_OPT_NAMES
508
509/* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
510static const char 	*__efx_mac_stat_name[] = {
511	"rx_octets",
512	"rx_pkts",
513	"rx_unicst_pkts",
514	"rx_multicst_pkts",
515	"rx_brdcst_pkts",
516	"rx_pause_pkts",
517	"rx_le_64_pkts",
518	"rx_65_to_127_pkts",
519	"rx_128_to_255_pkts",
520	"rx_256_to_511_pkts",
521	"rx_512_to_1023_pkts",
522	"rx_1024_to_15xx_pkts",
523	"rx_ge_15xx_pkts",
524	"rx_errors",
525	"rx_fcs_errors",
526	"rx_drop_events",
527	"rx_false_carrier_errors",
528	"rx_symbol_errors",
529	"rx_align_errors",
530	"rx_internal_errors",
531	"rx_jabber_pkts",
532	"rx_lane0_char_err",
533	"rx_lane1_char_err",
534	"rx_lane2_char_err",
535	"rx_lane3_char_err",
536	"rx_lane0_disp_err",
537	"rx_lane1_disp_err",
538	"rx_lane2_disp_err",
539	"rx_lane3_disp_err",
540	"rx_match_fault",
541	"rx_nodesc_drop_cnt",
542	"tx_octets",
543	"tx_pkts",
544	"tx_unicst_pkts",
545	"tx_multicst_pkts",
546	"tx_brdcst_pkts",
547	"tx_pause_pkts",
548	"tx_le_64_pkts",
549	"tx_65_to_127_pkts",
550	"tx_128_to_255_pkts",
551	"tx_256_to_511_pkts",
552	"tx_512_to_1023_pkts",
553	"tx_1024_to_15xx_pkts",
554	"tx_ge_15xx_pkts",
555	"tx_errors",
556	"tx_sgl_col_pkts",
557	"tx_mult_col_pkts",
558	"tx_ex_col_pkts",
559	"tx_late_col_pkts",
560	"tx_def_pkts",
561	"tx_ex_def_pkts",
562	"pm_trunc_bb_overflow",
563	"pm_discard_bb_overflow",
564	"pm_trunc_vfifo_full",
565	"pm_discard_vfifo_full",
566	"pm_trunc_qbb",
567	"pm_discard_qbb",
568	"pm_discard_mapping",
569	"rxdp_q_disabled_pkts",
570	"rxdp_di_dropped_pkts",
571	"rxdp_streaming_pkts",
572	"rxdp_hlb_fetch",
573	"rxdp_hlb_wait",
574	"vadapter_rx_unicast_packets",
575	"vadapter_rx_unicast_bytes",
576	"vadapter_rx_multicast_packets",
577	"vadapter_rx_multicast_bytes",
578	"vadapter_rx_broadcast_packets",
579	"vadapter_rx_broadcast_bytes",
580	"vadapter_rx_bad_packets",
581	"vadapter_rx_bad_bytes",
582	"vadapter_rx_overflow",
583	"vadapter_tx_unicast_packets",
584	"vadapter_tx_unicast_bytes",
585	"vadapter_tx_multicast_packets",
586	"vadapter_tx_multicast_bytes",
587	"vadapter_tx_broadcast_packets",
588	"vadapter_tx_broadcast_bytes",
589	"vadapter_tx_bad_packets",
590	"vadapter_tx_bad_bytes",
591	"vadapter_tx_overflow",
592};
593/* END MKCONFIG GENERATED EfxMacStatNamesBlock */
594
595	__checkReturn			const char *
596efx_mac_stat_name(
597	__in				efx_nic_t *enp,
598	__in				unsigned int id)
599{
600	_NOTE(ARGUNUSED(enp))
601	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
602
603	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
604	return (__efx_mac_stat_name[id]);
605}
606
607#endif	/* EFSYS_OPT_NAMES */
608
609	__checkReturn			efx_rc_t
610efx_mac_stats_upload(
611	__in				efx_nic_t *enp,
612	__in				efsys_mem_t *esmp)
613{
614	efx_port_t *epp = &(enp->en_port);
615	const efx_mac_ops_t *emop = epp->ep_emop;
616	efx_rc_t rc;
617
618	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
619	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
620	EFSYS_ASSERT(emop != NULL);
621
622	/*
623	 * Don't assert !ep_mac_stats_pending, because the client might
624	 * have failed to finalise statistics when previously stopping
625	 * the port.
626	 */
627	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
628		goto fail1;
629
630	epp->ep_mac_stats_pending = B_TRUE;
631
632	return (0);
633
634fail1:
635	EFSYS_PROBE1(fail1, efx_rc_t, rc);
636
637	return (rc);
638}
639
640	__checkReturn			efx_rc_t
641efx_mac_stats_periodic(
642	__in				efx_nic_t *enp,
643	__in				efsys_mem_t *esmp,
644	__in				uint16_t period_ms,
645	__in				boolean_t events)
646{
647	efx_port_t *epp = &(enp->en_port);
648	const efx_mac_ops_t *emop = epp->ep_emop;
649	efx_rc_t rc;
650
651	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
652	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
653
654	EFSYS_ASSERT(emop != NULL);
655
656	if (emop->emo_stats_periodic == NULL) {
657		rc = EINVAL;
658		goto fail1;
659	}
660
661	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
662		goto fail2;
663
664	return (0);
665
666fail2:
667	EFSYS_PROBE(fail2);
668fail1:
669	EFSYS_PROBE1(fail1, efx_rc_t, rc);
670
671	return (rc);
672}
673
674
675	__checkReturn			efx_rc_t
676efx_mac_stats_update(
677	__in				efx_nic_t *enp,
678	__in				efsys_mem_t *esmp,
679	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
680	__inout_opt			uint32_t *generationp)
681{
682	efx_port_t *epp = &(enp->en_port);
683	const efx_mac_ops_t *emop = epp->ep_emop;
684	efx_rc_t rc;
685
686	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
687	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
688	EFSYS_ASSERT(emop != NULL);
689
690	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
691	if (rc == 0)
692		epp->ep_mac_stats_pending = B_FALSE;
693
694	return (rc);
695}
696
697#endif	/* EFSYS_OPT_MAC_STATS */
698
699	__checkReturn			efx_rc_t
700efx_mac_select(
701	__in				efx_nic_t *enp)
702{
703	efx_port_t *epp = &(enp->en_port);
704	efx_mac_type_t type = EFX_MAC_INVALID;
705	const efx_mac_ops_t *emop;
706	int rc = EINVAL;
707
708	switch (enp->en_family) {
709#if EFSYS_OPT_SIENA
710	case EFX_FAMILY_SIENA:
711		emop = &__efx_siena_mac_ops;
712		type = EFX_MAC_SIENA;
713		break;
714#endif /* EFSYS_OPT_SIENA */
715
716#if EFSYS_OPT_HUNTINGTON
717	case EFX_FAMILY_HUNTINGTON:
718		emop = &__efx_ef10_mac_ops;
719		type = EFX_MAC_HUNTINGTON;
720		break;
721#endif /* EFSYS_OPT_HUNTINGTON */
722
723#if EFSYS_OPT_MEDFORD
724	case EFX_FAMILY_MEDFORD:
725		emop = &__efx_ef10_mac_ops;
726		type = EFX_MAC_MEDFORD;
727		break;
728#endif /* EFSYS_OPT_MEDFORD */
729
730	default:
731		rc = EINVAL;
732		goto fail1;
733	}
734
735	EFSYS_ASSERT(type != EFX_MAC_INVALID);
736	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
737	EFSYS_ASSERT(emop != NULL);
738
739	epp->ep_emop = emop;
740	epp->ep_mac_type = type;
741
742	if (emop->emo_reset != NULL) {
743		if ((rc = emop->emo_reset(enp)) != 0)
744			goto fail2;
745
746		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
747		enp->en_reset_flags &= ~EFX_RESET_MAC;
748	}
749
750	return (0);
751
752fail2:
753	EFSYS_PROBE(fail2);
754fail1:
755	EFSYS_PROBE1(fail1, efx_rc_t, rc);
756
757	return (rc);
758}
759
760
761#if EFSYS_OPT_SIENA
762
763#define	EFX_MAC_HASH_BITS	(1 << 8)
764
765/* Compute the multicast hash as used on Falcon and Siena. */
766static	void
767siena_mac_multicast_hash_compute(
768	__in_ecount(6*count)		uint8_t const *addrs,
769	__in				int count,
770	__out				efx_oword_t *hash_low,
771	__out				efx_oword_t *hash_high)
772{
773	uint32_t crc, index;
774	int i;
775
776	EFSYS_ASSERT(hash_low != NULL);
777	EFSYS_ASSERT(hash_high != NULL);
778
779	EFX_ZERO_OWORD(*hash_low);
780	EFX_ZERO_OWORD(*hash_high);
781
782	for (i = 0; i < count; i++) {
783		/* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
784		crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
785		index = crc % EFX_MAC_HASH_BITS;
786		if (index < 128) {
787			EFX_SET_OWORD_BIT(*hash_low, index);
788		} else {
789			EFX_SET_OWORD_BIT(*hash_high, index - 128);
790		}
791
792		addrs += EFX_MAC_ADDR_LEN;
793	}
794}
795
796static	__checkReturn	efx_rc_t
797siena_mac_multicast_list_set(
798	__in		efx_nic_t *enp)
799{
800	efx_port_t *epp = &(enp->en_port);
801	const efx_mac_ops_t *emop = epp->ep_emop;
802	efx_oword_t old_hash[2];
803	efx_rc_t rc;
804
805	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
806	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
807
808	memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
809
810	siena_mac_multicast_hash_compute(
811	    epp->ep_mulcst_addr_list,
812	    epp->ep_mulcst_addr_count,
813	    &epp->ep_multicst_hash[0],
814	    &epp->ep_multicst_hash[1]);
815
816	if ((rc = emop->emo_reconfigure(enp)) != 0)
817		goto fail1;
818
819	return (0);
820
821fail1:
822	EFSYS_PROBE1(fail1, efx_rc_t, rc);
823
824	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
825
826	return (rc);
827}
828
829#endif /* EFSYS_OPT_SIENA */
830