xref: /freebsd/sys/dev/sfxge/common/efx_mac.c (revision 10b59a9b4add0320d52c15ce057dd697261e7dfc)
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
40 static 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
57 static 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
74 static 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 
90 static 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
110 efx_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 
140 fail3:
141 	EFSYS_PROBE(fail3);
142 
143 	epp->ep_mac_pdu = old_pdu;
144 
145 fail2:
146 	EFSYS_PROBE(fail2);
147 fail1:
148 	EFSYS_PROBE1(fail1, int, rc);
149 
150 	return (rc);
151 }
152 
153 	__checkReturn			int
154 efx_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 
185 fail3:
186 	EFSYS_PROBE(fail3);
187 
188 	EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
189 
190 fail2:
191 	EFSYS_PROBE(fail2);
192 fail1:
193 	EFSYS_PROBE1(fail1, int, rc);
194 
195 	return (rc);
196 }
197 
198 	__checkReturn			int
199 efx_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 
224 fail1:
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
234 efx_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 
264 fail2:
265 	EFSYS_PROBE(fail2);
266 fail1:
267 	EFSYS_PROBE1(fail1, int, rc);
268 
269 	return (rc);
270 }
271 
272 	__checkReturn	int
273 efx_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 
289 fail1:
290 	EFSYS_PROBE1(fail1, int, rc);
291 
292 	return (rc);
293 }
294 
295 	__checkReturn			int
296 efx_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 
357 fail2:
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 
364 fail1:
365 	EFSYS_PROBE1(fail1, int, rc);
366 
367 	return (rc);
368 }
369 
370 			void
371 efx_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
401 efx_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 index;
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 (index = 0; index < 128; index++) {
419 		if (bucket[index] != 0)
420 			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index);
421 	}
422 
423 	/* Set the upper 128 bits of the hash */
424 	EFX_ZERO_OWORD(epp->ep_multicst_hash[1]);
425 	for (index = 0; index < 128; index++) {
426 		if (bucket[index + 128] != 0)
427 			EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index);
428 	}
429 
430 	if ((rc = emop->emo_reconfigure(enp)) != 0)
431 		goto fail1;
432 
433 	return (0);
434 
435 fail1:
436 	EFSYS_PROBE1(fail1, int, rc);
437 
438 	memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
439 
440 	return (rc);
441 }
442 
443 #if EFSYS_OPT_MAC_STATS
444 
445 #if EFSYS_OPT_NAMES
446 
447 /* START MKCONFIG GENERATED EfxMacStatNamesBlock adf707adba80813e */
448 static const char 	__cs * __cs __efx_mac_stat_name[] = {
449 	"rx_octets",
450 	"rx_pkts",
451 	"rx_unicst_pkts",
452 	"rx_multicst_pkts",
453 	"rx_brdcst_pkts",
454 	"rx_pause_pkts",
455 	"rx_le_64_pkts",
456 	"rx_65_to_127_pkts",
457 	"rx_128_to_255_pkts",
458 	"rx_256_to_511_pkts",
459 	"rx_512_to_1023_pkts",
460 	"rx_1024_to_15xx_pkts",
461 	"rx_ge_15xx_pkts",
462 	"rx_errors",
463 	"rx_fcs_errors",
464 	"rx_drop_events",
465 	"rx_false_carrier_errors",
466 	"rx_symbol_errors",
467 	"rx_align_errors",
468 	"rx_internal_errors",
469 	"rx_jabber_pkts",
470 	"rx_lane0_char_err",
471 	"rx_lane1_char_err",
472 	"rx_lane2_char_err",
473 	"rx_lane3_char_err",
474 	"rx_lane0_disp_err",
475 	"rx_lane1_disp_err",
476 	"rx_lane2_disp_err",
477 	"rx_lane3_disp_err",
478 	"rx_match_fault",
479 	"rx_nodesc_drop_cnt",
480 	"tx_octets",
481 	"tx_pkts",
482 	"tx_unicst_pkts",
483 	"tx_multicst_pkts",
484 	"tx_brdcst_pkts",
485 	"tx_pause_pkts",
486 	"tx_le_64_pkts",
487 	"tx_65_to_127_pkts",
488 	"tx_128_to_255_pkts",
489 	"tx_256_to_511_pkts",
490 	"tx_512_to_1023_pkts",
491 	"tx_1024_to_15xx_pkts",
492 	"tx_ge_15xx_pkts",
493 	"tx_errors",
494 	"tx_sgl_col_pkts",
495 	"tx_mult_col_pkts",
496 	"tx_ex_col_pkts",
497 	"tx_late_col_pkts",
498 	"tx_def_pkts",
499 	"tx_ex_def_pkts",
500 };
501 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
502 
503 	__checkReturn			const char __cs *
504 efx_mac_stat_name(
505 	__in				efx_nic_t *enp,
506 	__in				unsigned int id)
507 {
508 	_NOTE(ARGUNUSED(enp))
509 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
510 
511 	EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
512 	return (__efx_mac_stat_name[id]);
513 }
514 
515 #endif	/* EFSYS_OPT_STAT_NAME */
516 
517 	__checkReturn			int
518 efx_mac_stats_upload(
519 	__in				efx_nic_t *enp,
520 	__in				efsys_mem_t *esmp)
521 {
522 	efx_port_t *epp = &(enp->en_port);
523 	efx_mac_ops_t *emop = epp->ep_emop;
524 	int rc;
525 
526 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
527 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
528 	EFSYS_ASSERT(emop != NULL);
529 
530 	/*
531 	 * Don't assert !ep_mac_stats_pending, because the client might
532 	 * have failed to finalise statistics when previously stopping
533 	 * the port.
534 	 */
535 	if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
536 		goto fail1;
537 
538 	epp->ep_mac_stats_pending = B_TRUE;
539 
540 	return (0);
541 
542 fail1:
543 	EFSYS_PROBE1(fail1, int, rc);
544 
545 	return (rc);
546 }
547 
548 	__checkReturn			int
549 efx_mac_stats_periodic(
550 	__in				efx_nic_t *enp,
551 	__in				efsys_mem_t *esmp,
552 	__in				uint16_t period_ms,
553 	__in				boolean_t events)
554 {
555 	efx_port_t *epp = &(enp->en_port);
556 	efx_mac_ops_t *emop = epp->ep_emop;
557 	int rc;
558 
559 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
560 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
561 
562 	EFSYS_ASSERT(emop != NULL);
563 
564 	if (emop->emo_stats_periodic == NULL) {
565 		rc = EINVAL;
566 		goto fail1;
567 	}
568 
569 	if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
570 		goto fail2;
571 
572 	return (0);
573 
574 fail2:
575 	EFSYS_PROBE(fail2);
576 fail1:
577 	EFSYS_PROBE1(fail1, int, rc);
578 
579 	return (rc);
580 }
581 
582 
583 	__checkReturn			int
584 efx_mac_stats_update(
585 	__in				efx_nic_t *enp,
586 	__in				efsys_mem_t *esmp,
587 	__inout_ecount(EFX_MAC_NSTATS)	efsys_stat_t *essp,
588 	__in				uint32_t *generationp)
589 {
590 	efx_port_t *epp = &(enp->en_port);
591 	efx_mac_ops_t *emop = epp->ep_emop;
592 	int rc;
593 
594 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
595 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
596 	EFSYS_ASSERT(emop != NULL);
597 
598 	rc = emop->emo_stats_update(enp, esmp, essp, generationp);
599 	if (rc == 0)
600 		epp->ep_mac_stats_pending = B_FALSE;
601 
602 	return (rc);
603 }
604 
605 #endif	/* EFSYS_OPT_MAC_STATS */
606 
607 	__checkReturn			int
608 efx_mac_select(
609 	__in				efx_nic_t *enp)
610 {
611 	efx_port_t *epp = &(enp->en_port);
612 	efx_mac_type_t type = EFX_MAC_INVALID;
613 	efx_mac_ops_t *emop;
614 	int rc = EINVAL;
615 
616 #if EFSYS_OPT_SIENA
617 	if (enp->en_family == EFX_FAMILY_SIENA) {
618 		type = EFX_MAC_SIENA;
619 		goto chosen;
620 	}
621 #endif
622 
623 #if EFSYS_OPT_FALCON
624 	switch (epp->ep_link_mode) {
625 #if EFSYS_OPT_MAC_FALCON_GMAC
626 	case EFX_LINK_100HDX:
627 	case EFX_LINK_100FDX:
628 	case EFX_LINK_1000HDX:
629 	case EFX_LINK_1000FDX:
630 		type = EFX_MAC_FALCON_GMAC;
631 		goto chosen;
632 #endif	/* EFSYS_OPT_FALCON_GMAC */
633 
634 #if EFSYS_OPT_MAC_FALCON_XMAC
635 	case EFX_LINK_10000FDX:
636 		type = EFX_MAC_FALCON_XMAC;
637 		goto chosen;
638 #endif	/* EFSYS_OPT_FALCON_XMAC */
639 
640 	default:
641 #if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
642 		/* Only initialise a MAC supported by the PHY */
643 		if (epp->ep_phy_cap_mask &
644 		    ((1 << EFX_PHY_CAP_1000FDX) |
645 		    (1 << EFX_PHY_CAP_1000HDX) |
646 		    (1 << EFX_PHY_CAP_100FDX) |
647 		    (1 << EFX_PHY_CAP_100HDX) |
648 		    (1 << EFX_PHY_CAP_10FDX) |
649 		    (1 << EFX_PHY_CAP_10FDX)))
650 			type = EFX_MAC_FALCON_GMAC;
651 		else
652 			type = EFX_MAC_FALCON_XMAC;
653 #elif EFSYS_OPT_MAC_FALCON_GMAC
654 		type = EFX_MAC_FALCON_GMAC;
655 #else
656 		type = EFX_MAC_FALCON_XMAC;
657 #endif
658 		goto chosen;
659 	}
660 #endif	/* EFSYS_OPT_FALCON */
661 
662 chosen:
663 	EFSYS_ASSERT(type != EFX_MAC_INVALID);
664 	EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
665 	emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
666 	EFSYS_ASSERT(emop != NULL);
667 
668 	epp->ep_mac_type = type;
669 
670 	if (emop->emo_reset != NULL) {
671 		if ((rc = emop->emo_reset(enp)) != 0)
672 			goto fail1;
673 
674 		EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
675 		enp->en_reset_flags &= ~EFX_RESET_MAC;
676 	}
677 
678 	return (0);
679 
680 fail1:
681 	EFSYS_PROBE1(fail1, int, rc);
682 
683 	return (rc);
684 }
685