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