1/*-
2 * Copyright 2007-2009 Solarflare Communications Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include "efsys.h"
27#include "efx.h"
28#include "efx_types.h"
29#include "efx_impl.h"
30
31#if EFSYS_OPT_MAC_FALCON_GMAC
32#include "falcon_gmac.h"
33#endif
34
35#if EFSYS_OPT_MAC_FALCON_XMAC
36#include "falcon_xmac.h"
37#endif
38
39#if EFSYS_OPT_MAC_FALCON_GMAC
40static efx_mac_ops_t	__cs __efx_falcon_gmac_ops = {
41	falcon_gmac_reset,		/* emo_reset */
42	falcon_mac_poll,		/* emo_poll */
43	falcon_mac_up,			/* emo_up */
44	falcon_gmac_reconfigure,	/* emo_reconfigure */
45#if EFSYS_OPT_LOOPBACK
46	falcon_mac_loopback_set,	/* emo_loopback_set */
47#endif	/* EFSYS_OPT_LOOPBACK */
48#if EFSYS_OPT_MAC_STATS
49	falcon_mac_stats_upload,	/* emo_stats_upload */
50	NULL,				/* emo_stats_periodic */
51	falcon_gmac_stats_update	/* emo_stats_update */
52#endif	/* EFSYS_OPT_MAC_STATS */
53};
54#endif	/* EFSYS_OPT_MAC_FALCON_GMAC */
55
56#if EFSYS_OPT_MAC_FALCON_XMAC
57static efx_mac_ops_t	__cs __efx_falcon_xmac_ops = {
58	falcon_xmac_reset,		/* emo_reset */
59	falcon_mac_poll,		/* emo_poll */
60	falcon_mac_up,			/* emo_up */
61	falcon_xmac_reconfigure,	/* emo_reconfigure */
62#if EFSYS_OPT_LOOPBACK
63	falcon_mac_loopback_set,	/* emo_loopback_set */
64#endif	/* EFSYS_OPT_LOOPBACK */
65#if EFSYS_OPT_MAC_STATS
66	falcon_mac_stats_upload,	/* emo_stats_upload */
67	NULL,				/* emo_stats_periodic */
68	falcon_xmac_stats_update	/* emo_stats_update */
69#endif	/* EFSYS_OPT_MAC_STATS */
70};
71#endif	/* EFSYS_OPT_MAC_FALCON_XMAC */
72
73#if EFSYS_OPT_SIENA
74static efx_mac_ops_t	__cs __efx_siena_mac_ops = {
75	NULL,				/* emo_reset */
76	siena_mac_poll,			/* emo_poll */
77	siena_mac_up,			/* emo_up */
78	siena_mac_reconfigure,		/* emo_reconfigure */
79#if EFSYS_OPT_LOOPBACK
80	siena_mac_loopback_set,		/* emo_loopback_set */
81#endif	/* EFSYS_OPT_LOOPBACK */
82#if EFSYS_OPT_MAC_STATS
83	siena_mac_stats_upload,		/* emo_stats_upload */
84	siena_mac_stats_periodic,	/* emo_stats_periodic */
85	siena_mac_stats_update		/* emo_stats_update */
86#endif	/* EFSYS_OPT_MAC_STATS */
87};
88#endif	/* EFSYS_OPT_SIENA */
89
90static efx_mac_ops_t	__cs * __cs __efx_mac_ops[] = {
91	NULL,
92#if EFSYS_OPT_MAC_FALCON_GMAC
93	&__efx_falcon_gmac_ops,
94#else
95	NULL,
96#endif	/* EFSYS_OPT_MAC_FALCON_GMAC */
97#if EFSYS_OPT_MAC_FALCON_XMAC
98	&__efx_falcon_xmac_ops,
99#else
100	NULL,
101#endif	/* EFSYS_OPT_MAC_FALCON_XMAC */
102#if EFSYS_OPT_SIENA
103	&__efx_siena_mac_ops,
104#else
105	NULL,
106#endif	/* EFSYS_OPT_SIENA */
107};
108
109	__checkReturn			int
110efx_mac_pdu_set(
111	__in				efx_nic_t *enp,
112	__in				size_t pdu)
113{
114	efx_port_t *epp = &(enp->en_port);
115	efx_mac_ops_t *emop = epp->ep_emop;
116	uint32_t old_pdu;
117	int rc;
118
119	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
120	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
121	EFSYS_ASSERT(emop != NULL);
122
123	if (pdu < EFX_MAC_PDU_MIN) {
124		rc = EINVAL;
125		goto fail1;
126	}
127
128	if (pdu > EFX_MAC_PDU_MAX) {
129		rc = EINVAL;
130		goto fail2;
131	}
132
133	old_pdu = epp->ep_mac_pdu;
134	epp->ep_mac_pdu = (uint32_t)pdu;
135	if ((rc = emop->emo_reconfigure(enp)) != 0)
136		goto fail3;
137
138	return (0);
139
140fail3:
141	EFSYS_PROBE(fail3);
142
143	epp->ep_mac_pdu = old_pdu;
144
145fail2:
146	EFSYS_PROBE(fail2);
147fail1:
148	EFSYS_PROBE1(fail1, int, rc);
149
150	return (rc);
151}
152
153	__checkReturn			int
154efx_mac_addr_set(
155	__in				efx_nic_t *enp,
156	__in				uint8_t *addr)
157{
158	efx_port_t *epp = &(enp->en_port);
159	efx_mac_ops_t *emop = epp->ep_emop;
160	uint8_t old_addr[6];
161	uint32_t oui;
162	int rc;
163
164	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
165	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
166
167	if (addr[0] & 0x01) {
168		rc = EINVAL;
169		goto fail1;
170	}
171
172	oui = addr[0] << 16 | addr[1] << 8 | addr[2];
173	if (oui == 0x000000) {
174		rc = EINVAL;
175		goto fail2;
176	}
177
178	EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
179	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
180	if ((rc = emop->emo_reconfigure(enp)) != 0)
181		goto fail3;
182
183	return (0);
184
185fail3:
186	EFSYS_PROBE(fail3);
187
188	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
189
190fail2:
191	EFSYS_PROBE(fail2);
192fail1:
193	EFSYS_PROBE1(fail1, int, rc);
194
195	return (rc);
196}
197
198	__checkReturn			int
199efx_mac_filter_set(
200	__in				efx_nic_t *enp,
201	__in				boolean_t unicst,
202	__in				boolean_t brdcst)
203{
204	efx_port_t *epp = &(enp->en_port);
205	efx_mac_ops_t *emop = epp->ep_emop;
206	boolean_t old_unicst;
207	boolean_t old_brdcst;
208	int rc;
209
210	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
211	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
212
213	old_unicst = unicst;
214	old_brdcst = brdcst;
215
216	epp->ep_unicst = unicst;
217	epp->ep_brdcst = brdcst;
218
219	if ((rc = emop->emo_reconfigure(enp)) != 0)
220		goto fail1;
221
222	return (0);
223
224fail1:
225	EFSYS_PROBE1(fail1, int, rc);
226
227	epp->ep_unicst = old_unicst;
228	epp->ep_brdcst = old_brdcst;
229
230	return (rc);
231}
232
233	__checkReturn			int
234efx_mac_drain(
235	__in				efx_nic_t *enp,
236	__in				boolean_t enabled)
237{
238	efx_port_t *epp = &(enp->en_port);
239	efx_mac_ops_t *emop = epp->ep_emop;
240	int rc;
241
242	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
243	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
244	EFSYS_ASSERT(emop != NULL);
245
246	if (epp->ep_mac_drain == enabled)
247		return (0);
248
249	epp->ep_mac_drain = enabled;
250
251	if (enabled && emop->emo_reset != NULL) {
252		if ((rc = emop->emo_reset(enp)) != 0)
253			goto fail1;
254
255		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
256		enp->en_reset_flags &= ~EFX_RESET_PHY;
257	}
258
259	if ((rc = emop->emo_reconfigure(enp)) != 0)
260		goto fail2;
261
262	return (0);
263
264fail2:
265	EFSYS_PROBE(fail2);
266fail1:
267	EFSYS_PROBE1(fail1, int, rc);
268
269	return (rc);
270}
271
272	__checkReturn	int
273efx_mac_up(
274	__in		efx_nic_t *enp,
275	__out		boolean_t *mac_upp)
276{
277	efx_port_t *epp = &(enp->en_port);
278	efx_mac_ops_t *emop = epp->ep_emop;
279	int rc;
280
281	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
282	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
283
284	if ((rc = emop->emo_up(enp, mac_upp)) != 0)
285		goto fail1;
286
287	return (0);
288
289fail1:
290	EFSYS_PROBE1(fail1, int, rc);
291
292	return (rc);
293}
294
295	__checkReturn			int
296efx_mac_fcntl_set(
297	__in				efx_nic_t *enp,
298	__in				unsigned int fcntl,
299	__in				boolean_t autoneg)
300{
301	efx_port_t *epp = &(enp->en_port);
302	efx_mac_ops_t *emop = epp->ep_emop;
303	efx_phy_ops_t *epop = epp->ep_epop;
304	unsigned int old_fcntl;
305	boolean_t old_autoneg;
306	unsigned int old_adv_cap;
307	int rc;
308
309	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
310	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
311
312	if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
313		rc = EINVAL;
314		goto fail1;
315	}
316
317	/*
318	 * Ignore a request to set flow control autonegotiation
319	 * if the PHY doesn't support it.
320	 */
321	if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
322		autoneg = B_FALSE;
323
324	old_fcntl = epp->ep_fcntl;
325	old_autoneg = autoneg;
326	old_adv_cap = epp->ep_adv_cap_mask;
327
328	epp->ep_fcntl = fcntl;
329	epp->ep_fcntl_autoneg = autoneg;
330
331	/*
332	 * If the PHY supports autonegotiation, then encode the flow control
333	 * settings in the advertised capabilities, and restart AN. Otherwise,
334	 * just push the new settings directly to the MAC.
335	 */
336	if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) {
337		if (fcntl & EFX_FCNTL_RESPOND)
338			epp->ep_adv_cap_mask |=    (1 << EFX_PHY_CAP_PAUSE |
339						    1 << EFX_PHY_CAP_ASYM);
340		else
341			epp->ep_adv_cap_mask &=   ~(1 << EFX_PHY_CAP_PAUSE |
342						    1 << EFX_PHY_CAP_ASYM);
343
344		if (fcntl & EFX_FCNTL_GENERATE)
345			epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
346
347		if ((rc = epop->epo_reconfigure(enp)) != 0)
348			goto fail2;
349
350	} else {
351		if ((rc = emop->emo_reconfigure(enp)) != 0)
352			goto fail2;
353	}
354
355	return (0);
356
357fail2:
358	EFSYS_PROBE(fail2);
359
360	epp->ep_fcntl = old_fcntl;
361	epp->ep_fcntl_autoneg = old_autoneg;
362	epp->ep_adv_cap_mask = old_adv_cap;
363
364fail1:
365	EFSYS_PROBE1(fail1, int, rc);
366
367	return (rc);
368}
369
370			void
371efx_mac_fcntl_get(
372	__in		efx_nic_t *enp,
373	__out		unsigned int *fcntl_wantedp,
374	__out		unsigned int *fcntl_linkp)
375{
376	efx_port_t *epp = &(enp->en_port);
377	unsigned int wanted;
378
379	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
380	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
381
382	/*
383	 * If the PHY supports auto negotiation, then the requested flow
384	 * control settings are encoded in the advertised capabilities.
385	 */
386	if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) {
387		wanted = 0;
388
389		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
390			wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
391		if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
392			wanted ^= EFX_FCNTL_GENERATE;
393	} else
394		wanted = epp->ep_fcntl;
395
396	*fcntl_linkp = epp->ep_fcntl;
397	*fcntl_wantedp = wanted;
398}
399
400	__checkReturn			int
401efx_mac_hash_set(
402	__in				efx_nic_t *enp,
403	__in_ecount(EFX_MAC_HASH_BITS)	unsigned int const *bucket)
404{
405	efx_port_t *epp = &(enp->en_port);
406	efx_mac_ops_t *emop = epp->ep_emop;
407	efx_oword_t old_hash[2];
408	unsigned int idx;
409	int rc;
410
411	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
412	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
413
414	memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
415
416	/* Set the lower 128 bits of the hash */
417	EFX_ZERO_OWORD(epp->ep_multicst_hash[0]);
418	for (idx = 0; idx < 128; idx++) {
419		if (bucket[idx] != 0)
420#pragma GCC diagnostic push
421#pragma GCC diagnostic ignored "-Wtype-limits"
422			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], idx);
423#pragma GCC diagnostic pop
424	}
425
426	/* Set the upper 128 bits of the hash */
427	EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
428	for (idx = 0; idx < 128; idx++) {
429		if (bucket[idx + 128] != 0)
430#pragma GCC diagnostic push
431#pragma GCC diagnostic ignored "-Wtype-limits"
432			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], idx);
433#pragma GCC diagnostic pop
434	}
435
436	if ((rc = emop->emo_reconfigure(enp)) != 0)
437		goto fail1;
438
439	return (0);
440
441fail1:
442	EFSYS_PROBE1(fail1, int, rc);
443
444	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
445
446	return (rc);
447}
448
449#if EFSYS_OPT_MAC_STATS
450
451#if EFSYS_OPT_NAMES
452
453/* START MKCONFIG GENERATED EfxMacStatNamesBlock adf707adba80813e */
454static const char 	__cs * __cs __efx_mac_stat_name[] = {
455	"rx_octets",
456	"rx_pkts",
457	"rx_unicst_pkts",
458	"rx_multicst_pkts",
459	"rx_brdcst_pkts",
460	"rx_pause_pkts",
461	"rx_le_64_pkts",
462	"rx_65_to_127_pkts",
463	"rx_128_to_255_pkts",
464	"rx_256_to_511_pkts",
465	"rx_512_to_1023_pkts",
466	"rx_1024_to_15xx_pkts",
467	"rx_ge_15xx_pkts",
468	"rx_errors",
469	"rx_fcs_errors",
470	"rx_drop_events",
471	"rx_false_carrier_errors",
472	"rx_symbol_errors",
473	"rx_align_errors",
474	"rx_internal_errors",
475	"rx_jabber_pkts",
476	"rx_lane0_char_err",
477	"rx_lane1_char_err",
478	"rx_lane2_char_err",
479	"rx_lane3_char_err",
480	"rx_lane0_disp_err",
481	"rx_lane1_disp_err",
482	"rx_lane2_disp_err",
483	"rx_lane3_disp_err",
484	"rx_match_fault",
485	"rx_nodesc_drop_cnt",
486	"tx_octets",
487	"tx_pkts",
488	"tx_unicst_pkts",
489	"tx_multicst_pkts",
490	"tx_brdcst_pkts",
491	"tx_pause_pkts",
492	"tx_le_64_pkts",
493	"tx_65_to_127_pkts",
494	"tx_128_to_255_pkts",
495	"tx_256_to_511_pkts",
496	"tx_512_to_1023_pkts",
497	"tx_1024_to_15xx_pkts",
498	"tx_ge_15xx_pkts",
499	"tx_errors",
500	"tx_sgl_col_pkts",
501	"tx_mult_col_pkts",
502	"tx_ex_col_pkts",
503	"tx_late_col_pkts",
504	"tx_def_pkts",
505	"tx_ex_def_pkts",
506};
507/* END MKCONFIG GENERATED EfxMacStatNamesBlock */
508
509	__checkReturn			const char __cs *
510efx_mac_stat_name(
511	__in				efx_nic_t *enp,
512	__in				unsigned int id)
513{
514	_NOTE(ARGUNUSED(enp))
515	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
516
517	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
518	return (__efx_mac_stat_name[id]);
519}
520
521#endif	/* EFSYS_OPT_STAT_NAME */
522
523	__checkReturn			int
524efx_mac_stats_upload(
525	__in				efx_nic_t *enp,
526	__in				efsys_mem_t *esmp)
527{
528	efx_port_t *epp = &(enp->en_port);
529	efx_mac_ops_t *emop = epp->ep_emop;
530	int rc;
531
532	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
533	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
534	EFSYS_ASSERT(emop != NULL);
535
536	/*
537	 * Don't assert !ep_mac_stats_pending, because the client might
538	 * have failed to finalise statistics when previously stopping
539	 * the port.
540	 */
541	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
542		goto fail1;
543
544	epp->ep_mac_stats_pending = B_TRUE;
545
546	return (0);
547
548fail1:
549	EFSYS_PROBE1(fail1, int, rc);
550
551	return (rc);
552}
553
554	__checkReturn			int
555efx_mac_stats_periodic(
556	__in				efx_nic_t *enp,
557	__in				efsys_mem_t *esmp,
558	__in				uint16_t period_ms,
559	__in				boolean_t events)
560{
561	efx_port_t *epp = &(enp->en_port);
562	efx_mac_ops_t *emop = epp->ep_emop;
563	int rc;
564
565	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
566	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
567
568	EFSYS_ASSERT(emop != NULL);
569
570	if (emop->emo_stats_periodic == NULL) {
571		rc = EINVAL;
572		goto fail1;
573	}
574
575	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
576		goto fail2;
577
578	return (0);
579
580fail2:
581	EFSYS_PROBE(fail2);
582fail1:
583	EFSYS_PROBE1(fail1, int, rc);
584
585	return (rc);
586}
587
588
589	__checkReturn			int
590efx_mac_stats_update(
591	__in				efx_nic_t *enp,
592	__in				efsys_mem_t *esmp,
593	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
594	__in				uint32_t *generationp)
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	EFSYS_ASSERT(emop != NULL);
603
604	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
605	if (rc == 0)
606		epp->ep_mac_stats_pending = B_FALSE;
607
608	return (rc);
609}
610
611#endif	/* EFSYS_OPT_MAC_STATS */
612
613	__checkReturn			int
614efx_mac_select(
615	__in				efx_nic_t *enp)
616{
617	efx_port_t *epp = &(enp->en_port);
618	efx_mac_type_t type = EFX_MAC_INVALID;
619	efx_mac_ops_t *emop;
620	int rc = EINVAL;
621
622#if EFSYS_OPT_SIENA
623	if (enp->en_family == EFX_FAMILY_SIENA) {
624		type = EFX_MAC_SIENA;
625		goto chosen;
626	}
627#endif
628
629#if EFSYS_OPT_FALCON
630	switch (epp->ep_link_mode) {
631#if EFSYS_OPT_MAC_FALCON_GMAC
632	case EFX_LINK_100HDX:
633	case EFX_LINK_100FDX:
634	case EFX_LINK_1000HDX:
635	case EFX_LINK_1000FDX:
636		type = EFX_MAC_FALCON_GMAC;
637		goto chosen;
638#endif	/* EFSYS_OPT_FALCON_GMAC */
639
640#if EFSYS_OPT_MAC_FALCON_XMAC
641	case EFX_LINK_10000FDX:
642		type = EFX_MAC_FALCON_XMAC;
643		goto chosen;
644#endif	/* EFSYS_OPT_FALCON_XMAC */
645
646	default:
647#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
648		/* Only initialise a MAC supported by the PHY */
649		if (epp->ep_phy_cap_mask &
650		    ((1 << EFX_PHY_CAP_1000FDX) |
651		    (1 << EFX_PHY_CAP_1000HDX) |
652		    (1 << EFX_PHY_CAP_100FDX) |
653		    (1 << EFX_PHY_CAP_100HDX) |
654		    (1 << EFX_PHY_CAP_10FDX) |
655		    (1 << EFX_PHY_CAP_10FDX)))
656			type = EFX_MAC_FALCON_GMAC;
657		else
658			type = EFX_MAC_FALCON_XMAC;
659#elif EFSYS_OPT_MAC_FALCON_GMAC
660		type = EFX_MAC_FALCON_GMAC;
661#else
662		type = EFX_MAC_FALCON_XMAC;
663#endif
664		goto chosen;
665	}
666#endif	/* EFSYS_OPT_FALCON */
667
668chosen:
669	EFSYS_ASSERT(type != EFX_MAC_INVALID);
670	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
671	emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
672	EFSYS_ASSERT(emop != NULL);
673
674	epp->ep_mac_type = type;
675
676	if (emop->emo_reset != NULL) {
677		if ((rc = emop->emo_reset(enp)) != 0)
678			goto fail1;
679
680		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
681		enp->en_reset_flags &= ~EFX_RESET_MAC;
682	}
683
684	return (0);
685
686fail1:
687	EFSYS_PROBE1(fail1, int, rc);
688
689	return (rc);
690}
691