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