efx_mac.c revision 293814
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 293814 2016-01-13 07:25:51Z arybchik $");
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
47static	__checkReturn	efx_rc_t
48falconsiena_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
54static 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
75static 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
96static 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
117static 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
138static 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
168efx_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
198fail3:
199	EFSYS_PROBE(fail3);
200
201	epp->ep_mac_pdu = old_pdu;
202
203fail2:
204	EFSYS_PROBE(fail2);
205fail1:
206	EFSYS_PROBE1(fail1, efx_rc_t, rc);
207
208	return (rc);
209}
210
211	__checkReturn			efx_rc_t
212efx_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
243fail3:
244	EFSYS_PROBE(fail3);
245
246	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
247
248fail2:
249	EFSYS_PROBE(fail2);
250fail1:
251	EFSYS_PROBE1(fail1, efx_rc_t, rc);
252
253	return (rc);
254}
255
256	__checkReturn			efx_rc_t
257efx_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
290fail1:
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
302efx_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
332fail2:
333	EFSYS_PROBE(fail2);
334fail1:
335	EFSYS_PROBE1(fail1, efx_rc_t, rc);
336
337	return (rc);
338}
339
340	__checkReturn	efx_rc_t
341efx_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
357fail1:
358	EFSYS_PROBE1(fail1, efx_rc_t, rc);
359
360	return (rc);
361}
362
363	__checkReturn			efx_rc_t
364efx_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
422fail3:
423	EFSYS_PROBE(fail3);
424
425fail2:
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
432fail1:
433	EFSYS_PROBE1(fail1, efx_rc_t, rc);
434
435	return (rc);
436}
437
438			void
439efx_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
464efx_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
515fail3:
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
529fail2:
530	EFSYS_PROBE(fail2);
531
532fail1:
533	EFSYS_PROBE1(fail1, efx_rc_t, rc);
534
535	return (rc);
536
537}
538
539	__checkReturn	efx_rc_t
540efx_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
560fail1:
561	EFSYS_PROBE1(fail1, efx_rc_t, rc);
562
563	return (rc);
564}
565
566			void
567efx_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 */
586static 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 *
672efx_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
686efx_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
710fail1:
711	EFSYS_PROBE1(fail1, efx_rc_t, rc);
712
713	return (rc);
714}
715
716	__checkReturn			efx_rc_t
717efx_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
742fail2:
743	EFSYS_PROBE(fail2);
744fail1:
745	EFSYS_PROBE1(fail1, efx_rc_t, rc);
746
747	return (rc);
748}
749
750
751	__checkReturn			efx_rc_t
752efx_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
776efx_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
837chosen:
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
855fail1:
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. */
867static	void
868falconsiena_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
897static	__checkReturn	efx_rc_t
898falconsiena_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
921fail1:
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