xref: /freebsd/sys/dev/sfxge/sfxge_port.c (revision ec273ebf3b6aed5fba8c56b6ece5ad8693a48ea7)
1 /*-
2  * Copyright (c) 2010-2011 Solarflare Communications, Inc.
3  * All rights reserved.
4  *
5  * This software was developed in part by Philip Paeps under contract for
6  * Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/types.h>
34 #include <sys/limits.h>
35 #include <net/ethernet.h>
36 #include <net/if_dl.h>
37 
38 #include "common/efx.h"
39 
40 #include "sfxge.h"
41 
42 static int
43 sfxge_mac_stat_update(struct sfxge_softc *sc)
44 {
45 	struct sfxge_port *port = &sc->port;
46 	efsys_mem_t *esmp = &(port->mac_stats.dma_buf);
47 	clock_t now;
48 	unsigned int count;
49 	int rc;
50 
51 	SFXGE_PORT_LOCK_ASSERT_OWNED(port);
52 
53 	if (port->init_state != SFXGE_PORT_STARTED) {
54 		rc = 0;
55 		goto out;
56 	}
57 
58 	now = ticks;
59 	if (now - port->mac_stats.update_time < hz) {
60 		rc = 0;
61 		goto out;
62 	}
63 
64 	port->mac_stats.update_time = now;
65 
66 	/* If we're unlucky enough to read statistics wduring the DMA, wait
67 	 * up to 10ms for it to finish (typically takes <500us) */
68 	for (count = 0; count < 100; ++count) {
69 		EFSYS_PROBE1(wait, unsigned int, count);
70 
71 		/* Synchronize the DMA memory for reading */
72 		bus_dmamap_sync(esmp->esm_tag, esmp->esm_map,
73 		    BUS_DMASYNC_POSTREAD);
74 
75 		/* Try to update the cached counters */
76 		if ((rc = efx_mac_stats_update(sc->enp, esmp,
77 		    port->mac_stats.decode_buf, NULL)) != EAGAIN)
78 			goto out;
79 
80 		DELAY(100);
81 	}
82 
83 	rc = ETIMEDOUT;
84 out:
85 	return (rc);
86 }
87 
88 static int
89 sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
90 {
91 	struct sfxge_softc *sc = arg1;
92 	unsigned int id = arg2;
93 	int rc;
94 
95 	SFXGE_PORT_LOCK(&sc->port);
96 	if ((rc = sfxge_mac_stat_update(sc)) != 0)
97 		goto out;
98 
99 	rc = SYSCTL_OUT(req,
100 			(uint64_t *)sc->port.mac_stats.decode_buf + id,
101 			sizeof(uint64_t));
102 out:
103 	SFXGE_PORT_UNLOCK(&sc->port);
104 	return (rc);
105 }
106 
107 static void
108 sfxge_mac_stat_init(struct sfxge_softc *sc)
109 {
110 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
111 	struct sysctl_oid_list *stat_list;
112 	unsigned int id;
113 	const char *name;
114 
115 	stat_list = SYSCTL_CHILDREN(sc->stats_node);
116 
117 	/* Initialise the named stats */
118 	for (id = 0; id < EFX_MAC_NSTATS; id++) {
119 		name = efx_mac_stat_name(sc->enp, id);
120 		SYSCTL_ADD_PROC(
121 			ctx, stat_list,
122 			OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
123 			sc, id, sfxge_mac_stat_handler, "Q",
124 			"");
125 	}
126 }
127 
128 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
129 
130 static unsigned int
131 sfxge_port_wanted_fc(struct sfxge_softc *sc)
132 {
133 	struct ifmedia_entry *ifm = sc->media.ifm_cur;
134 
135 	if (ifm->ifm_media == (IFM_ETHER | IFM_AUTO))
136 		return (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE);
137 	return (((ifm->ifm_media & IFM_ETH_RXPAUSE) ? EFX_FCNTL_RESPOND : 0) |
138 		((ifm->ifm_media & IFM_ETH_TXPAUSE) ? EFX_FCNTL_GENERATE : 0));
139 }
140 
141 static unsigned int
142 sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
143 {
144 	unsigned int wanted_fc, link_fc;
145 
146 	efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
147 	return ((link_fc & EFX_FCNTL_RESPOND) ? IFM_ETH_RXPAUSE : 0) |
148 		((link_fc & EFX_FCNTL_GENERATE) ? IFM_ETH_TXPAUSE : 0);
149 }
150 
151 #else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */
152 
153 static unsigned int
154 sfxge_port_wanted_fc(struct sfxge_softc *sc)
155 {
156 	return (sc->port.wanted_fc);
157 }
158 
159 static unsigned int
160 sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
161 {
162 	return (0);
163 }
164 
165 static int
166 sfxge_port_wanted_fc_handler(SYSCTL_HANDLER_ARGS)
167 {
168 	struct sfxge_softc *sc;
169 	struct sfxge_port *port;
170 	unsigned int fcntl;
171 	int error;
172 
173 	sc = arg1;
174 	port = &sc->port;
175 
176 	SFXGE_PORT_LOCK(port);
177 
178 	if (req->newptr != NULL) {
179 		if ((error = SYSCTL_IN(req, &fcntl, sizeof(fcntl))) != 0)
180 			goto out;
181 
182 		if (port->wanted_fc == fcntl)
183 			goto out;
184 
185 		port->wanted_fc = fcntl;
186 
187 		if (port->init_state != SFXGE_PORT_STARTED)
188 			goto out;
189 
190 		error = efx_mac_fcntl_set(sc->enp, port->wanted_fc, B_TRUE);
191 	} else {
192 		error = SYSCTL_OUT(req, &port->wanted_fc,
193 				   sizeof(port->wanted_fc));
194 	}
195 
196 out:
197 	SFXGE_PORT_UNLOCK(port);
198 
199 	return (error);
200 }
201 
202 static int
203 sfxge_port_link_fc_handler(SYSCTL_HANDLER_ARGS)
204 {
205 	struct sfxge_softc *sc;
206 	struct sfxge_port *port;
207 	unsigned int wanted_fc, link_fc;
208 	int error;
209 
210 	sc = arg1;
211 	port = &sc->port;
212 
213 	SFXGE_PORT_LOCK(port);
214 	if (port->init_state == SFXGE_PORT_STARTED && SFXGE_LINK_UP(sc))
215 		efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
216 	else
217 		link_fc = 0;
218 	error = SYSCTL_OUT(req, &link_fc, sizeof(link_fc));
219 	SFXGE_PORT_UNLOCK(port);
220 
221 	return (error);
222 }
223 
224 #endif /* SFXGE_HAVE_PAUSE_MEDIAOPTS */
225 
226 static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = {
227 	[EFX_LINK_10HDX]	= IF_Mbps(10),
228 	[EFX_LINK_10FDX]	= IF_Mbps(10),
229 	[EFX_LINK_100HDX]	= IF_Mbps(100),
230 	[EFX_LINK_100FDX]	= IF_Mbps(100),
231 	[EFX_LINK_1000HDX]	= IF_Gbps(1),
232 	[EFX_LINK_1000FDX]	= IF_Gbps(1),
233 	[EFX_LINK_10000FDX]     = IF_Gbps(10),
234 };
235 
236 void
237 sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode)
238 {
239 	struct sfxge_port *port;
240 	int link_state;
241 
242 	port = &sc->port;
243 
244 	if (port->link_mode == mode)
245 		return;
246 
247 	port->link_mode = mode;
248 
249 	/* Push link state update to the OS */
250 	link_state = (port->link_mode != EFX_LINK_DOWN ?
251 		      LINK_STATE_UP : LINK_STATE_DOWN);
252 	sc->ifnet->if_baudrate = sfxge_link_baudrate[port->link_mode];
253 	if_link_state_change(sc->ifnet, link_state);
254 }
255 
256 static void
257 sfxge_mac_poll_work(void *arg, int npending)
258 {
259 	struct sfxge_softc *sc;
260 	efx_nic_t *enp;
261 	struct sfxge_port *port;
262 	efx_link_mode_t mode;
263 
264 	sc = (struct sfxge_softc *)arg;
265 	enp = sc->enp;
266 	port = &sc->port;
267 
268 	SFXGE_PORT_LOCK(port);
269 
270 	if (port->init_state != SFXGE_PORT_STARTED)
271 		goto done;
272 
273 	/* This may sleep waiting for MCDI completion */
274 	(void)efx_port_poll(enp, &mode);
275 	sfxge_mac_link_update(sc, mode);
276 
277 done:
278 	SFXGE_PORT_UNLOCK(port);
279 }
280 
281 static int
282 sfxge_mac_filter_set_locked(struct sfxge_softc *sc)
283 {
284 	unsigned int bucket[EFX_MAC_HASH_BITS];
285 	struct ifnet *ifp = sc->ifnet;
286 	struct ifmultiaddr *ifma;
287 	struct sockaddr_dl *sa;
288 	efx_nic_t *enp = sc->enp;
289 	unsigned int index;
290 	int rc;
291 
292 	/* Set promisc-unicast and broadcast filter bits */
293 	if ((rc = efx_mac_filter_set(enp, !!(ifp->if_flags & IFF_PROMISC),
294 				     B_TRUE)) != 0)
295 		return (rc);
296 
297 	/* Set multicast hash filter */
298 	if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) {
299 		for (index = 0; index < EFX_MAC_HASH_BITS; index++)
300 			bucket[index] = 1;
301 	} else {
302 		/* Broadcast frames also go through the multicast
303 		 * filter, and the broadcast address hashes to
304 		 * 0xff. */
305 		bucket[0xff] = 1;
306 
307 		if_maddr_rlock(ifp);
308 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
309 			if (ifma->ifma_addr->sa_family == AF_LINK) {
310 				sa = (struct sockaddr_dl *)ifma->ifma_addr;
311 				index = ether_crc32_le(LLADDR(sa), 6) & 0xff;
312 				bucket[index] = 1;
313 			}
314 		}
315 		if_maddr_runlock(ifp);
316 	}
317 	return (efx_mac_hash_set(enp, bucket));
318 }
319 
320 int
321 sfxge_mac_filter_set(struct sfxge_softc *sc)
322 {
323 	struct sfxge_port *port = &sc->port;
324 	int rc;
325 
326 	SFXGE_PORT_LOCK(port);
327 	/*
328 	 * The function may be called without softc_lock held in the
329 	 * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler
330 	 * checks IFF_DRV_RUNNING flag which implies port started, but
331 	 * it is not guaranteed to remain. softc_lock shared lock can't
332 	 * be held in the case of these ioctls processing, since it
333 	 * results in failure where kernel complains that non-sleepable
334 	 * lock is held in sleeping thread. Both problems are repeatable
335 	 * on LAG with LACP proto bring up.
336 	 */
337 	if (port->init_state == SFXGE_PORT_STARTED)
338 		rc = sfxge_mac_filter_set_locked(sc);
339 	else
340 		rc = 0;
341 	SFXGE_PORT_UNLOCK(port);
342 	return (rc);
343 }
344 
345 void
346 sfxge_port_stop(struct sfxge_softc *sc)
347 {
348 	struct sfxge_port *port;
349 	efx_nic_t *enp;
350 
351 	port = &sc->port;
352 	enp = sc->enp;
353 
354 	SFXGE_PORT_LOCK(port);
355 
356 	KASSERT(port->init_state == SFXGE_PORT_STARTED,
357 	    ("port not started"));
358 
359 	port->init_state = SFXGE_PORT_INITIALIZED;
360 
361 	port->mac_stats.update_time = 0;
362 
363 	/* This may call MCDI */
364 	(void)efx_mac_drain(enp, B_TRUE);
365 
366 	(void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE);
367 
368 	port->link_mode = EFX_LINK_UNKNOWN;
369 
370 	/* Destroy the common code port object. */
371 	efx_port_fini(sc->enp);
372 
373 	SFXGE_PORT_UNLOCK(port);
374 }
375 
376 int
377 sfxge_port_start(struct sfxge_softc *sc)
378 {
379 	uint8_t mac_addr[ETHER_ADDR_LEN];
380 	struct ifnet *ifp = sc->ifnet;
381 	struct sfxge_port *port;
382 	efx_nic_t *enp;
383 	size_t pdu;
384 	int rc;
385 
386 	port = &sc->port;
387 	enp = sc->enp;
388 
389 	SFXGE_PORT_LOCK(port);
390 
391 	KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
392 	    ("port not initialized"));
393 
394 	/* Initialize the port object in the common code. */
395 	if ((rc = efx_port_init(sc->enp)) != 0)
396 		goto fail;
397 
398 	/* Set the SDU */
399 	pdu = EFX_MAC_PDU(ifp->if_mtu);
400 	if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
401 		goto fail2;
402 
403 	if ((rc = efx_mac_fcntl_set(enp, sfxge_port_wanted_fc(sc), B_TRUE))
404 	    != 0)
405 		goto fail2;
406 
407 	/* Set the unicast address */
408 	if_addr_rlock(ifp);
409 	bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr),
410 	      mac_addr, sizeof(mac_addr));
411 	if_addr_runlock(ifp);
412 	if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0)
413 		goto fail;
414 
415 	sfxge_mac_filter_set_locked(sc);
416 
417 	/* Update MAC stats by DMA every second */
418 	if ((rc = efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf,
419 	    1000, B_FALSE)) != 0)
420 		goto fail2;
421 
422 	if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
423 		goto fail3;
424 
425 	if ((rc = efx_phy_adv_cap_set(sc->enp, sc->media.ifm_cur->ifm_data))
426 	    != 0)
427 		goto fail4;
428 
429 	port->init_state = SFXGE_PORT_STARTED;
430 
431 	/* Single poll in case there were missing initial events */
432 	SFXGE_PORT_UNLOCK(port);
433 	sfxge_mac_poll_work(sc, 0);
434 
435 	return (0);
436 
437 fail4:
438 	(void)efx_mac_drain(enp, B_TRUE);
439 fail3:
440 	(void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf,
441 	    0, B_FALSE);
442 fail2:
443 	efx_port_fini(sc->enp);
444 fail:
445 	SFXGE_PORT_UNLOCK(port);
446 
447 	return (rc);
448 }
449 
450 static int
451 sfxge_phy_stat_update(struct sfxge_softc *sc)
452 {
453 	struct sfxge_port *port = &sc->port;
454 	efsys_mem_t *esmp = &port->phy_stats.dma_buf;
455 	clock_t now;
456 	unsigned int count;
457 	int rc;
458 
459 	SFXGE_PORT_LOCK_ASSERT_OWNED(port);
460 
461 	if (port->init_state != SFXGE_PORT_STARTED) {
462 		rc = 0;
463 		goto out;
464 	}
465 
466 	now = ticks;
467 	if (now - port->phy_stats.update_time < hz) {
468 		rc = 0;
469 		goto out;
470 	}
471 
472 	port->phy_stats.update_time = now;
473 
474 	/* If we're unlucky enough to read statistics wduring the DMA, wait
475 	 * up to 10ms for it to finish (typically takes <500us) */
476 	for (count = 0; count < 100; ++count) {
477 		EFSYS_PROBE1(wait, unsigned int, count);
478 
479 		/* Synchronize the DMA memory for reading */
480 		bus_dmamap_sync(esmp->esm_tag, esmp->esm_map,
481 		    BUS_DMASYNC_POSTREAD);
482 
483 		/* Try to update the cached counters */
484 		if ((rc = efx_phy_stats_update(sc->enp, esmp,
485 		    port->phy_stats.decode_buf)) != EAGAIN)
486 			goto out;
487 
488 		DELAY(100);
489 	}
490 
491 	rc = ETIMEDOUT;
492 out:
493 	return (rc);
494 }
495 
496 static int
497 sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS)
498 {
499 	struct sfxge_softc *sc = arg1;
500 	unsigned int id = arg2;
501 	int rc;
502 
503 	SFXGE_PORT_LOCK(&sc->port);
504 	if ((rc = sfxge_phy_stat_update(sc)) != 0)
505 		goto out;
506 
507 	rc = SYSCTL_OUT(req,
508 			(uint32_t *)sc->port.phy_stats.decode_buf + id,
509 			sizeof(uint32_t));
510 out:
511 	SFXGE_PORT_UNLOCK(&sc->port);
512 	return (rc);
513 }
514 
515 static void
516 sfxge_phy_stat_init(struct sfxge_softc *sc)
517 {
518 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
519 	struct sysctl_oid_list *stat_list;
520 	unsigned int id;
521 	const char *name;
522 	uint64_t stat_mask = efx_nic_cfg_get(sc->enp)->enc_phy_stat_mask;
523 
524 	stat_list = SYSCTL_CHILDREN(sc->stats_node);
525 
526 	/* Initialise the named stats */
527 	for (id = 0; id < EFX_PHY_NSTATS; id++) {
528 		if (!(stat_mask & ((uint64_t)1 << id)))
529 			continue;
530 		name = efx_phy_stat_name(sc->enp, id);
531 		SYSCTL_ADD_PROC(
532 			ctx, stat_list,
533 			OID_AUTO, name, CTLTYPE_UINT|CTLFLAG_RD,
534 			sc, id, sfxge_phy_stat_handler,
535 			id == EFX_PHY_STAT_OUI ? "IX" : "IU",
536 			"");
537 	}
538 }
539 
540 void
541 sfxge_port_fini(struct sfxge_softc *sc)
542 {
543 	struct sfxge_port *port;
544 	efsys_mem_t *esmp;
545 
546 	port = &sc->port;
547 	esmp = &port->mac_stats.dma_buf;
548 
549 	KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
550 	    ("Port not initialized"));
551 
552 	port->init_state = SFXGE_PORT_UNINITIALIZED;
553 
554 	port->link_mode = EFX_LINK_UNKNOWN;
555 
556 	/* Finish with PHY DMA memory */
557 	sfxge_dma_free(&port->phy_stats.dma_buf);
558 	free(port->phy_stats.decode_buf, M_SFXGE);
559 
560 	sfxge_dma_free(esmp);
561 	free(port->mac_stats.decode_buf, M_SFXGE);
562 
563 	SFXGE_PORT_LOCK_DESTROY(port);
564 
565 	port->sc = NULL;
566 }
567 
568 int
569 sfxge_port_init(struct sfxge_softc *sc)
570 {
571 	struct sfxge_port *port;
572 	struct sysctl_ctx_list *sysctl_ctx;
573 	struct sysctl_oid *sysctl_tree;
574 	efsys_mem_t *mac_stats_buf, *phy_stats_buf;
575 	int rc;
576 
577 	port = &sc->port;
578 	mac_stats_buf = &port->mac_stats.dma_buf;
579 	phy_stats_buf = &port->phy_stats.dma_buf;
580 
581 	KASSERT(port->init_state == SFXGE_PORT_UNINITIALIZED,
582 	    ("Port already initialized"));
583 
584 	port->sc = sc;
585 
586 	SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev));
587 
588 	port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t),
589 					    M_SFXGE, M_WAITOK | M_ZERO);
590 	if ((rc = sfxge_dma_alloc(sc, EFX_PHY_STATS_SIZE, phy_stats_buf)) != 0)
591 		goto fail;
592 	sfxge_phy_stat_init(sc);
593 
594 	sysctl_ctx = device_get_sysctl_ctx(sc->dev);
595 	sysctl_tree = device_get_sysctl_tree(sc->dev);
596 
597 #ifndef SFXGE_HAVE_PAUSE_MEDIAOPTS
598 	/* If flow control cannot be configured or reported through
599 	 * ifmedia, provide sysctls for it. */
600 	port->wanted_fc = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
601 	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
602 	    "wanted_fc", CTLTYPE_UINT|CTLFLAG_RW, sc, 0,
603 	    sfxge_port_wanted_fc_handler, "IU", "wanted flow control mode");
604 	SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
605 	    "link_fc", CTLTYPE_UINT|CTLFLAG_RD, sc, 0,
606 	    sfxge_port_link_fc_handler, "IU", "link flow control mode");
607 #endif
608 
609 	port->mac_stats.decode_buf = malloc(EFX_MAC_NSTATS * sizeof(uint64_t),
610 					    M_SFXGE, M_WAITOK | M_ZERO);
611 	if ((rc = sfxge_dma_alloc(sc, EFX_MAC_STATS_SIZE, mac_stats_buf)) != 0)
612 		goto fail2;
613 	sfxge_mac_stat_init(sc);
614 
615 	port->init_state = SFXGE_PORT_INITIALIZED;
616 
617 	return (0);
618 
619 fail2:
620 	free(port->mac_stats.decode_buf, M_SFXGE);
621 	sfxge_dma_free(phy_stats_buf);
622 fail:
623 	free(port->phy_stats.decode_buf, M_SFXGE);
624 	SFXGE_PORT_LOCK_DESTROY(port);
625 	port->sc = NULL;
626 	return (rc);
627 }
628 
629 static int sfxge_link_mode[EFX_PHY_MEDIA_NTYPES][EFX_LINK_NMODES] = {
630 	[EFX_PHY_MEDIA_CX4] = {
631 		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_CX4,
632 	},
633 	[EFX_PHY_MEDIA_KX4] = {
634 		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_KX4,
635 	},
636 	[EFX_PHY_MEDIA_XFP] = {
637 		/* Don't know the module type, but assume SR for now. */
638 		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_SR,
639 	},
640 	[EFX_PHY_MEDIA_SFP_PLUS] = {
641 		/* Don't know the module type, but assume SX/SR for now. */
642 		[EFX_LINK_1000FDX]	= IFM_ETHER | IFM_FDX | IFM_1000_SX,
643 		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_SR,
644 	},
645 	[EFX_PHY_MEDIA_BASE_T] = {
646 		[EFX_LINK_10HDX]	= IFM_ETHER | IFM_HDX | IFM_10_T,
647 		[EFX_LINK_10FDX]	= IFM_ETHER | IFM_FDX | IFM_10_T,
648 		[EFX_LINK_100HDX]	= IFM_ETHER | IFM_HDX | IFM_100_TX,
649 		[EFX_LINK_100FDX]	= IFM_ETHER | IFM_FDX | IFM_100_TX,
650 		[EFX_LINK_1000HDX]	= IFM_ETHER | IFM_HDX | IFM_1000_T,
651 		[EFX_LINK_1000FDX]	= IFM_ETHER | IFM_FDX | IFM_1000_T,
652 		[EFX_LINK_10000FDX]	= IFM_ETHER | IFM_FDX | IFM_10G_T,
653 	},
654 };
655 
656 static void
657 sfxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
658 {
659 	struct sfxge_softc *sc;
660 	efx_phy_media_type_t medium_type;
661 	efx_link_mode_t mode;
662 
663 	sc = ifp->if_softc;
664 	SFXGE_ADAPTER_LOCK(sc);
665 
666 	ifmr->ifm_status = IFM_AVALID;
667 	ifmr->ifm_active = IFM_ETHER;
668 
669 	if (SFXGE_RUNNING(sc) && SFXGE_LINK_UP(sc)) {
670 		ifmr->ifm_status |= IFM_ACTIVE;
671 
672 		efx_phy_media_type_get(sc->enp, &medium_type);
673 		mode = sc->port.link_mode;
674 		ifmr->ifm_active |= sfxge_link_mode[medium_type][mode];
675 		ifmr->ifm_active |= sfxge_port_link_fc_ifm(sc);
676 	}
677 
678 	SFXGE_ADAPTER_UNLOCK(sc);
679 }
680 
681 static int
682 sfxge_media_change(struct ifnet *ifp)
683 {
684 	struct sfxge_softc *sc;
685 	struct ifmedia_entry *ifm;
686 	int rc;
687 
688 	sc = ifp->if_softc;
689 	ifm = sc->media.ifm_cur;
690 
691 	SFXGE_ADAPTER_LOCK(sc);
692 
693 	if (!SFXGE_RUNNING(sc)) {
694 		rc = 0;
695 		goto out;
696 	}
697 
698 	rc = efx_mac_fcntl_set(sc->enp, sfxge_port_wanted_fc(sc), B_TRUE);
699 	if (rc != 0)
700 		goto out;
701 
702 	rc = efx_phy_adv_cap_set(sc->enp, ifm->ifm_data);
703 out:
704 	SFXGE_ADAPTER_UNLOCK(sc);
705 
706 	return (rc);
707 }
708 
709 int sfxge_port_ifmedia_init(struct sfxge_softc *sc)
710 {
711 	efx_phy_media_type_t medium_type;
712 	uint32_t cap_mask, mode_cap_mask;
713 	efx_link_mode_t mode;
714 	int mode_ifm, best_mode_ifm = 0;
715 	int rc;
716 
717 	/* We need port state to initialise the ifmedia list. */
718 	if ((rc = efx_nic_init(sc->enp)) != 0)
719 		goto out;
720 	if ((rc = efx_port_init(sc->enp)) != 0)
721 		goto out2;
722 
723 	/*
724 	 * Register ifconfig callbacks for querying and setting the
725 	 * link mode and link status.
726 	 */
727 	ifmedia_init(&sc->media, IFM_IMASK, sfxge_media_change,
728 	    sfxge_media_status);
729 
730 	/*
731 	 * Map firmware medium type and capabilities to ifmedia types.
732 	 * ifmedia does not distinguish between forcing the link mode
733 	 * and disabling auto-negotiation.  1000BASE-T and 10GBASE-T
734 	 * require AN even if only one link mode is enabled, and for
735 	 * 100BASE-TX it is useful even if the link mode is forced.
736 	 * Therefore we never disable auto-negotiation.
737 	 *
738 	 * Also enable and advertise flow control by default.
739 	 */
740 
741 	efx_phy_media_type_get(sc->enp, &medium_type);
742 	efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask);
743 
744 	EFX_STATIC_ASSERT(EFX_LINK_10HDX == EFX_PHY_CAP_10HDX + 1);
745 	EFX_STATIC_ASSERT(EFX_LINK_10FDX == EFX_PHY_CAP_10FDX + 1);
746 	EFX_STATIC_ASSERT(EFX_LINK_100HDX == EFX_PHY_CAP_100HDX + 1);
747 	EFX_STATIC_ASSERT(EFX_LINK_100FDX == EFX_PHY_CAP_100FDX + 1);
748 	EFX_STATIC_ASSERT(EFX_LINK_1000HDX == EFX_PHY_CAP_1000HDX + 1);
749 	EFX_STATIC_ASSERT(EFX_LINK_1000FDX == EFX_PHY_CAP_1000FDX + 1);
750 	EFX_STATIC_ASSERT(EFX_LINK_10000FDX == EFX_PHY_CAP_10000FDX + 1);
751 
752 	for (mode = EFX_LINK_10HDX; mode <= EFX_LINK_10000FDX; mode++) {
753 		mode_cap_mask = 1 << (mode - 1);
754 		mode_ifm = sfxge_link_mode[medium_type][mode];
755 
756 		if ((cap_mask & mode_cap_mask) && mode_ifm) {
757 			mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN);
758 
759 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
760 			/* No flow-control */
761 			ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL);
762 
763 			/* Respond-only.  If using AN, we implicitly
764 			 * offer symmetric as well, but that doesn't
765 			 * mean we *have* to generate pause frames.
766 			 */
767 			mode_cap_mask |= cap_mask & ((1 << EFX_PHY_CAP_PAUSE) |
768 						     (1 << EFX_PHY_CAP_ASYM));
769 			mode_ifm |= IFM_ETH_RXPAUSE;
770 			ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL);
771 
772 			/* Symmetric */
773 			mode_cap_mask &= ~(1 << EFX_PHY_CAP_ASYM);
774 			mode_ifm |= IFM_ETH_TXPAUSE;
775 #else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */
776 			mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE);
777 #endif
778 			ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL);
779 
780 			/* Link modes are numbered in order of speed,
781 			 * so assume the last one available is the best.
782 			 */
783 			best_mode_ifm = mode_ifm;
784 		}
785 	}
786 
787 	if (cap_mask & (1 << EFX_PHY_CAP_AN)) {
788 		/* Add autoselect mode. */
789 		mode_ifm = IFM_ETHER | IFM_AUTO;
790 		ifmedia_add(&sc->media, mode_ifm,
791 			    cap_mask & ~(1 << EFX_PHY_CAP_ASYM), NULL);
792 		best_mode_ifm = mode_ifm;
793 	}
794 
795 	if (best_mode_ifm != 0)
796 		ifmedia_set(&sc->media, best_mode_ifm);
797 
798 	/* Now discard port state until interface is started. */
799 	efx_port_fini(sc->enp);
800 out2:
801 	efx_nic_fini(sc->enp);
802 out:
803 	return (rc);
804 }
805