2 * Copyright (c) 2010-2016 Solarflare Communications Inc.
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation are
30 * those of the authors and should not be interpreted as representing official
31 * policies, either expressed or implied, of the FreeBSD Project.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/types.h>
38 #include <sys/limits.h>
39 #include <net/ethernet.h>
40 #include <net/if_dl.h>
42 #include "common/efx.h"
46 #define SFXGE_PARAM_STATS_UPDATE_PERIOD_MS \
47 SFXGE_PARAM(stats_update_period_ms)
48 static int sfxge_stats_update_period_ms = SFXGE_STATS_UPDATE_PERIOD_MS;
49 TUNABLE_INT(SFXGE_PARAM_STATS_UPDATE_PERIOD_MS,
50 &sfxge_stats_update_period_ms);
51 SYSCTL_INT(_hw_sfxge, OID_AUTO, stats_update_period_ms, CTLFLAG_RDTUN,
52 &sfxge_stats_update_period_ms, 0,
53 "netstat interface statistics update period in milliseconds");
55 static int sfxge_phy_cap_mask(struct sfxge_softc *, int, uint32_t *);
58 sfxge_mac_stat_update(struct sfxge_softc *sc)
60 struct sfxge_port *port = &sc->port;
61 efsys_mem_t *esmp = &(port->mac_stats.dma_buf);
63 unsigned int min_ticks;
67 SFXGE_PORT_LOCK_ASSERT_OWNED(port);
69 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) {
74 min_ticks = (unsigned int)hz * port->stats_update_period_ms / 1000;
77 if ((unsigned int)(now - port->mac_stats.update_time) < min_ticks) {
82 port->mac_stats.update_time = now;
84 /* If we're unlucky enough to read statistics wduring the DMA, wait
85 * up to 10ms for it to finish (typically takes <500us) */
86 for (count = 0; count < 100; ++count) {
87 EFSYS_PROBE1(wait, unsigned int, count);
89 /* Try to update the cached counters */
90 if ((rc = efx_mac_stats_update(sc->enp, esmp,
91 port->mac_stats.decode_buf, NULL)) != EAGAIN)
103 sfxge_port_update_stats(struct sfxge_softc *sc)
108 SFXGE_PORT_LOCK(&sc->port);
110 /* Ignore error and use old values */
111 (void)sfxge_mac_stat_update(sc);
114 mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf;
116 ifp->if_ipackets = mac_stats[EFX_MAC_RX_PKTS];
117 ifp->if_ierrors = mac_stats[EFX_MAC_RX_ERRORS];
118 ifp->if_opackets = mac_stats[EFX_MAC_TX_PKTS];
119 ifp->if_oerrors = mac_stats[EFX_MAC_TX_ERRORS];
121 mac_stats[EFX_MAC_TX_SGL_COL_PKTS] +
122 mac_stats[EFX_MAC_TX_MULT_COL_PKTS] +
123 mac_stats[EFX_MAC_TX_EX_COL_PKTS] +
124 mac_stats[EFX_MAC_TX_LATE_COL_PKTS];
125 ifp->if_ibytes = mac_stats[EFX_MAC_RX_OCTETS];
126 ifp->if_obytes = mac_stats[EFX_MAC_TX_OCTETS];
127 /* if_imcasts is maintained in net/if_ethersubr.c */
129 mac_stats[EFX_MAC_TX_MULTICST_PKTS] +
130 mac_stats[EFX_MAC_TX_BRDCST_PKTS];
131 /* if_iqdrops is maintained in net/if_ethersubr.c */
132 /* if_noproto is maintained in net/if_ethersubr.c */
134 SFXGE_PORT_UNLOCK(&sc->port);
138 sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
140 struct sfxge_softc *sc = arg1;
141 unsigned int id = arg2;
145 SFXGE_PORT_LOCK(&sc->port);
146 if ((rc = sfxge_mac_stat_update(sc)) == 0)
147 val = ((uint64_t *)sc->port.mac_stats.decode_buf)[id];
148 SFXGE_PORT_UNLOCK(&sc->port);
151 rc = SYSCTL_OUT(req, &val, sizeof(val));
156 sfxge_mac_stat_init(struct sfxge_softc *sc)
158 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
159 struct sysctl_oid_list *stat_list;
163 stat_list = SYSCTL_CHILDREN(sc->stats_node);
165 /* Initialise the named stats */
166 for (id = 0; id < EFX_MAC_NSTATS; id++) {
167 name = efx_mac_stat_name(sc->enp, id);
170 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
171 sc, id, sfxge_mac_stat_handler, "Q",
176 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
179 sfxge_port_wanted_fc(struct sfxge_softc *sc)
181 struct ifmedia_entry *ifm = sc->media.ifm_cur;
183 if (ifm->ifm_media == (IFM_ETHER | IFM_AUTO))
184 return (EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE);
185 return (((ifm->ifm_media & IFM_ETH_RXPAUSE) ? EFX_FCNTL_RESPOND : 0) |
186 ((ifm->ifm_media & IFM_ETH_TXPAUSE) ? EFX_FCNTL_GENERATE : 0));
190 sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
192 unsigned int wanted_fc, link_fc;
194 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
195 return ((link_fc & EFX_FCNTL_RESPOND) ? IFM_ETH_RXPAUSE : 0) |
196 ((link_fc & EFX_FCNTL_GENERATE) ? IFM_ETH_TXPAUSE : 0);
199 #else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */
202 sfxge_port_wanted_fc(struct sfxge_softc *sc)
204 return (sc->port.wanted_fc);
208 sfxge_port_link_fc_ifm(struct sfxge_softc *sc)
214 sfxge_port_wanted_fc_handler(SYSCTL_HANDLER_ARGS)
216 struct sfxge_softc *sc;
217 struct sfxge_port *port;
224 if (req->newptr != NULL) {
225 if ((error = SYSCTL_IN(req, &fcntl, sizeof(fcntl))) != 0)
228 SFXGE_PORT_LOCK(port);
230 if (port->wanted_fc != fcntl) {
231 if (port->init_state == SFXGE_PORT_STARTED)
232 error = efx_mac_fcntl_set(sc->enp,
236 port->wanted_fc = fcntl;
239 SFXGE_PORT_UNLOCK(port);
241 SFXGE_PORT_LOCK(port);
242 fcntl = port->wanted_fc;
243 SFXGE_PORT_UNLOCK(port);
245 error = SYSCTL_OUT(req, &fcntl, sizeof(fcntl));
252 sfxge_port_link_fc_handler(SYSCTL_HANDLER_ARGS)
254 struct sfxge_softc *sc;
255 struct sfxge_port *port;
256 unsigned int wanted_fc, link_fc;
261 SFXGE_PORT_LOCK(port);
262 if (__predict_true(port->init_state == SFXGE_PORT_STARTED) &&
264 efx_mac_fcntl_get(sc->enp, &wanted_fc, &link_fc);
267 SFXGE_PORT_UNLOCK(port);
269 return (SYSCTL_OUT(req, &link_fc, sizeof(link_fc)));
272 #endif /* SFXGE_HAVE_PAUSE_MEDIAOPTS */
274 static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = {
275 [EFX_LINK_10HDX] = IF_Mbps(10),
276 [EFX_LINK_10FDX] = IF_Mbps(10),
277 [EFX_LINK_100HDX] = IF_Mbps(100),
278 [EFX_LINK_100FDX] = IF_Mbps(100),
279 [EFX_LINK_1000HDX] = IF_Gbps(1),
280 [EFX_LINK_1000FDX] = IF_Gbps(1),
281 [EFX_LINK_10000FDX] = IF_Gbps(10),
282 [EFX_LINK_40000FDX] = IF_Gbps(40),
286 sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode)
288 struct sfxge_port *port;
293 if (port->link_mode == mode)
296 port->link_mode = mode;
298 /* Push link state update to the OS */
299 link_state = (SFXGE_LINK_UP(sc) ? LINK_STATE_UP : LINK_STATE_DOWN);
300 if_initbaudrate(sc->ifnet, sfxge_link_baudrate[port->link_mode]);
301 if_link_state_change(sc->ifnet, link_state);
305 sfxge_mac_poll_work(void *arg, int npending)
307 struct sfxge_softc *sc;
309 struct sfxge_port *port;
310 efx_link_mode_t mode;
312 sc = (struct sfxge_softc *)arg;
316 SFXGE_PORT_LOCK(port);
318 if (__predict_false(port->init_state != SFXGE_PORT_STARTED))
321 /* This may sleep waiting for MCDI completion */
322 (void)efx_port_poll(enp, &mode);
323 sfxge_mac_link_update(sc, mode);
326 SFXGE_PORT_UNLOCK(port);
330 sfxge_mac_multicast_list_set(struct sfxge_softc *sc)
332 struct ifnet *ifp = sc->ifnet;
333 struct sfxge_port *port = &sc->port;
334 uint8_t *mcast_addr = port->mcast_addrs;
335 struct ifmultiaddr *ifma;
336 struct sockaddr_dl *sa;
339 mtx_assert(&port->lock, MA_OWNED);
341 port->mcast_count = 0;
343 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
344 if (ifma->ifma_addr->sa_family == AF_LINK) {
345 if (port->mcast_count == EFX_MAC_MULTICAST_LIST_MAX) {
346 device_printf(sc->dev,
347 "Too many multicast addresses\n");
352 sa = (struct sockaddr_dl *)ifma->ifma_addr;
353 memcpy(mcast_addr, LLADDR(sa), EFX_MAC_ADDR_LEN);
354 mcast_addr += EFX_MAC_ADDR_LEN;
358 if_maddr_runlock(ifp);
361 rc = efx_mac_multicast_list_set(sc->enp, port->mcast_addrs,
364 device_printf(sc->dev,
365 "Cannot set multicast address list\n");
372 sfxge_mac_filter_set_locked(struct sfxge_softc *sc)
374 struct ifnet *ifp = sc->ifnet;
375 struct sfxge_port *port = &sc->port;
376 boolean_t all_mulcst;
379 mtx_assert(&port->lock, MA_OWNED);
381 all_mulcst = !!(ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI));
383 rc = sfxge_mac_multicast_list_set(sc);
384 /* Fallback to all multicast if cannot set multicast list */
388 rc = efx_mac_filter_set(sc->enp, !!(ifp->if_flags & IFF_PROMISC),
389 (port->mcast_count > 0), all_mulcst, B_TRUE);
395 sfxge_mac_filter_set(struct sfxge_softc *sc)
397 struct sfxge_port *port = &sc->port;
400 SFXGE_PORT_LOCK(port);
402 * The function may be called without softc_lock held in the
403 * case of SIOCADDMULTI and SIOCDELMULTI ioctls. ioctl handler
404 * checks IFF_DRV_RUNNING flag which implies port started, but
405 * it is not guaranteed to remain. softc_lock shared lock can't
406 * be held in the case of these ioctls processing, since it
407 * results in failure where kernel complains that non-sleepable
408 * lock is held in sleeping thread. Both problems are repeatable
409 * on LAG with LACP proto bring up.
411 if (__predict_true(port->init_state == SFXGE_PORT_STARTED))
412 rc = sfxge_mac_filter_set_locked(sc);
415 SFXGE_PORT_UNLOCK(port);
420 sfxge_port_stop(struct sfxge_softc *sc)
422 struct sfxge_port *port;
428 SFXGE_PORT_LOCK(port);
430 KASSERT(port->init_state == SFXGE_PORT_STARTED,
431 ("port not started"));
433 port->init_state = SFXGE_PORT_INITIALIZED;
435 port->mac_stats.update_time = 0;
437 /* This may call MCDI */
438 (void)efx_mac_drain(enp, B_TRUE);
440 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE);
442 port->link_mode = EFX_LINK_UNKNOWN;
444 /* Destroy the common code port object. */
447 efx_filter_fini(enp);
449 SFXGE_PORT_UNLOCK(port);
453 sfxge_port_start(struct sfxge_softc *sc)
455 uint8_t mac_addr[ETHER_ADDR_LEN];
456 struct ifnet *ifp = sc->ifnet;
457 struct sfxge_port *port;
461 uint32_t phy_cap_mask;
466 SFXGE_PORT_LOCK(port);
468 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
469 ("port not initialized"));
471 /* Initialise the required filtering */
472 if ((rc = efx_filter_init(enp)) != 0)
473 goto fail_filter_init;
475 /* Initialize the port object in the common code. */
476 if ((rc = efx_port_init(sc->enp)) != 0)
480 pdu = EFX_MAC_PDU(ifp->if_mtu);
481 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
484 if ((rc = efx_mac_fcntl_set(enp, sfxge_port_wanted_fc(sc), B_TRUE))
488 /* Set the unicast address */
490 bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr),
491 mac_addr, sizeof(mac_addr));
492 if_addr_runlock(ifp);
493 if ((rc = efx_mac_addr_set(enp, mac_addr)) != 0)
496 sfxge_mac_filter_set_locked(sc);
498 /* Update MAC stats by DMA every period */
499 if ((rc = efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf,
500 port->stats_update_period_ms,
504 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
507 if ((rc = sfxge_phy_cap_mask(sc, sc->media.ifm_cur->ifm_media,
508 &phy_cap_mask)) != 0)
511 if ((rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask)) != 0)
514 port->init_state = SFXGE_PORT_STARTED;
516 /* Single poll in case there were missing initial events */
517 SFXGE_PORT_UNLOCK(port);
518 sfxge_mac_poll_work(sc, 0);
524 (void)efx_mac_drain(enp, B_TRUE);
526 (void)efx_mac_stats_periodic(enp, &port->mac_stats.dma_buf, 0, B_FALSE);
534 efx_filter_fini(enp);
536 SFXGE_PORT_UNLOCK(port);
542 sfxge_phy_stat_update(struct sfxge_softc *sc)
544 struct sfxge_port *port = &sc->port;
545 efsys_mem_t *esmp = &port->phy_stats.dma_buf;
550 SFXGE_PORT_LOCK_ASSERT_OWNED(port);
552 if (__predict_false(port->init_state != SFXGE_PORT_STARTED)) {
558 if ((unsigned int)(now - port->phy_stats.update_time) < (unsigned int)hz) {
563 port->phy_stats.update_time = now;
565 /* If we're unlucky enough to read statistics wduring the DMA, wait
566 * up to 10ms for it to finish (typically takes <500us) */
567 for (count = 0; count < 100; ++count) {
568 EFSYS_PROBE1(wait, unsigned int, count);
570 /* Synchronize the DMA memory for reading */
571 bus_dmamap_sync(esmp->esm_tag, esmp->esm_map,
572 BUS_DMASYNC_POSTREAD);
574 /* Try to update the cached counters */
575 if ((rc = efx_phy_stats_update(sc->enp, esmp,
576 port->phy_stats.decode_buf)) != EAGAIN)
588 sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS)
590 struct sfxge_softc *sc = arg1;
591 unsigned int id = arg2;
595 SFXGE_PORT_LOCK(&sc->port);
596 if ((rc = sfxge_phy_stat_update(sc)) == 0)
597 val = ((uint32_t *)sc->port.phy_stats.decode_buf)[id];
598 SFXGE_PORT_UNLOCK(&sc->port);
601 rc = SYSCTL_OUT(req, &val, sizeof(val));
606 sfxge_phy_stat_init(struct sfxge_softc *sc)
608 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
609 struct sysctl_oid_list *stat_list;
612 uint64_t stat_mask = efx_nic_cfg_get(sc->enp)->enc_phy_stat_mask;
614 stat_list = SYSCTL_CHILDREN(sc->stats_node);
616 /* Initialise the named stats */
617 for (id = 0; id < EFX_PHY_NSTATS; id++) {
618 if (!(stat_mask & ((uint64_t)1 << id)))
620 name = efx_phy_stat_name(sc->enp, id);
623 OID_AUTO, name, CTLTYPE_UINT|CTLFLAG_RD,
624 sc, id, sfxge_phy_stat_handler,
625 id == EFX_PHY_STAT_OUI ? "IX" : "IU",
631 sfxge_port_fini(struct sfxge_softc *sc)
633 struct sfxge_port *port;
637 esmp = &port->mac_stats.dma_buf;
639 KASSERT(port->init_state == SFXGE_PORT_INITIALIZED,
640 ("Port not initialized"));
642 port->init_state = SFXGE_PORT_UNINITIALIZED;
644 port->link_mode = EFX_LINK_UNKNOWN;
646 /* Finish with PHY DMA memory */
647 sfxge_dma_free(&port->phy_stats.dma_buf);
648 free(port->phy_stats.decode_buf, M_SFXGE);
650 sfxge_dma_free(esmp);
651 free(port->mac_stats.decode_buf, M_SFXGE);
653 SFXGE_PORT_LOCK_DESTROY(port);
659 sfxge_port_stats_update_period_ms(struct sfxge_softc *sc)
661 int period_ms = sfxge_stats_update_period_ms;
664 device_printf(sc->dev,
665 "treat negative stats update period %d as 0 (disable)\n",
668 } else if (period_ms > UINT16_MAX) {
669 device_printf(sc->dev,
670 "treat too big stats update period %d as %u\n",
671 period_ms, UINT16_MAX);
672 period_ms = UINT16_MAX;
679 sfxge_port_stats_update_period_ms_handler(SYSCTL_HANDLER_ARGS)
681 struct sfxge_softc *sc;
682 struct sfxge_port *port;
683 unsigned int period_ms;
689 if (req->newptr != NULL) {
690 error = SYSCTL_IN(req, &period_ms, sizeof(period_ms));
694 if (period_ms > UINT16_MAX)
697 SFXGE_PORT_LOCK(port);
699 if (port->stats_update_period_ms != period_ms) {
700 if (port->init_state == SFXGE_PORT_STARTED)
701 error = efx_mac_stats_periodic(sc->enp,
702 &port->mac_stats.dma_buf,
705 port->stats_update_period_ms = period_ms;
708 SFXGE_PORT_UNLOCK(port);
710 SFXGE_PORT_LOCK(port);
711 period_ms = port->stats_update_period_ms;
712 SFXGE_PORT_UNLOCK(port);
714 error = SYSCTL_OUT(req, &period_ms, sizeof(period_ms));
721 sfxge_port_init(struct sfxge_softc *sc)
723 struct sfxge_port *port;
724 struct sysctl_ctx_list *sysctl_ctx;
725 struct sysctl_oid *sysctl_tree;
726 efsys_mem_t *mac_stats_buf, *phy_stats_buf;
730 mac_stats_buf = &port->mac_stats.dma_buf;
731 phy_stats_buf = &port->phy_stats.dma_buf;
733 KASSERT(port->init_state == SFXGE_PORT_UNINITIALIZED,
734 ("Port already initialized"));
738 SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev));
740 DBGPRINT(sc->dev, "alloc PHY stats");
741 port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t),
742 M_SFXGE, M_WAITOK | M_ZERO);
743 if ((rc = sfxge_dma_alloc(sc, EFX_PHY_STATS_SIZE, phy_stats_buf)) != 0)
745 sfxge_phy_stat_init(sc);
747 DBGPRINT(sc->dev, "init sysctl");
748 sysctl_ctx = device_get_sysctl_ctx(sc->dev);
749 sysctl_tree = device_get_sysctl_tree(sc->dev);
751 #ifndef SFXGE_HAVE_PAUSE_MEDIAOPTS
752 /* If flow control cannot be configured or reported through
753 * ifmedia, provide sysctls for it. */
754 port->wanted_fc = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
755 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
756 "wanted_fc", CTLTYPE_UINT|CTLFLAG_RW, sc, 0,
757 sfxge_port_wanted_fc_handler, "IU", "wanted flow control mode");
758 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
759 "link_fc", CTLTYPE_UINT|CTLFLAG_RD, sc, 0,
760 sfxge_port_link_fc_handler, "IU", "link flow control mode");
763 DBGPRINT(sc->dev, "alloc MAC stats");
764 port->mac_stats.decode_buf = malloc(EFX_MAC_NSTATS * sizeof(uint64_t),
765 M_SFXGE, M_WAITOK | M_ZERO);
766 if ((rc = sfxge_dma_alloc(sc, EFX_MAC_STATS_SIZE, mac_stats_buf)) != 0)
768 port->stats_update_period_ms = sfxge_port_stats_update_period_ms(sc);
769 sfxge_mac_stat_init(sc);
771 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
772 "stats_update_period_ms", CTLTYPE_UINT|CTLFLAG_RW, sc, 0,
773 sfxge_port_stats_update_period_ms_handler, "IU",
774 "interface statistics refresh period");
776 port->init_state = SFXGE_PORT_INITIALIZED;
778 DBGPRINT(sc->dev, "success");
782 free(port->mac_stats.decode_buf, M_SFXGE);
783 sfxge_dma_free(phy_stats_buf);
785 free(port->phy_stats.decode_buf, M_SFXGE);
786 SFXGE_PORT_LOCK_DESTROY(port);
788 DBGPRINT(sc->dev, "failed %d", rc);
792 static const int sfxge_link_mode[EFX_PHY_MEDIA_NTYPES][EFX_LINK_NMODES] = {
793 [EFX_PHY_MEDIA_CX4] = {
794 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_CX4,
796 [EFX_PHY_MEDIA_KX4] = {
797 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_KX4,
799 [EFX_PHY_MEDIA_XFP] = {
800 /* Don't know the module type, but assume SR for now. */
801 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR,
803 [EFX_PHY_MEDIA_QSFP_PLUS] = {
804 /* Don't know the module type, but assume SR for now. */
805 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR,
806 [EFX_LINK_40000FDX] = IFM_ETHER | IFM_FDX | IFM_40G_CR4,
808 [EFX_PHY_MEDIA_SFP_PLUS] = {
809 /* Don't know the module type, but assume SX/SR for now. */
810 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_SX,
811 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_SR,
813 [EFX_PHY_MEDIA_BASE_T] = {
814 [EFX_LINK_10HDX] = IFM_ETHER | IFM_HDX | IFM_10_T,
815 [EFX_LINK_10FDX] = IFM_ETHER | IFM_FDX | IFM_10_T,
816 [EFX_LINK_100HDX] = IFM_ETHER | IFM_HDX | IFM_100_TX,
817 [EFX_LINK_100FDX] = IFM_ETHER | IFM_FDX | IFM_100_TX,
818 [EFX_LINK_1000HDX] = IFM_ETHER | IFM_HDX | IFM_1000_T,
819 [EFX_LINK_1000FDX] = IFM_ETHER | IFM_FDX | IFM_1000_T,
820 [EFX_LINK_10000FDX] = IFM_ETHER | IFM_FDX | IFM_10G_T,
825 sfxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
827 struct sfxge_softc *sc;
828 efx_phy_media_type_t medium_type;
829 efx_link_mode_t mode;
832 SFXGE_ADAPTER_LOCK(sc);
834 ifmr->ifm_status = IFM_AVALID;
835 ifmr->ifm_active = IFM_ETHER;
837 if (SFXGE_RUNNING(sc) && SFXGE_LINK_UP(sc)) {
838 ifmr->ifm_status |= IFM_ACTIVE;
840 efx_phy_media_type_get(sc->enp, &medium_type);
841 mode = sc->port.link_mode;
842 ifmr->ifm_active |= sfxge_link_mode[medium_type][mode];
843 ifmr->ifm_active |= sfxge_port_link_fc_ifm(sc);
846 SFXGE_ADAPTER_UNLOCK(sc);
849 static efx_phy_cap_type_t
850 sfxge_link_mode_to_phy_cap(efx_link_mode_t mode)
854 return (EFX_PHY_CAP_10HDX);
856 return (EFX_PHY_CAP_10FDX);
857 case EFX_LINK_100HDX:
858 return (EFX_PHY_CAP_100HDX);
859 case EFX_LINK_100FDX:
860 return (EFX_PHY_CAP_100FDX);
861 case EFX_LINK_1000HDX:
862 return (EFX_PHY_CAP_1000HDX);
863 case EFX_LINK_1000FDX:
864 return (EFX_PHY_CAP_1000FDX);
865 case EFX_LINK_10000FDX:
866 return (EFX_PHY_CAP_10000FDX);
867 case EFX_LINK_40000FDX:
868 return (EFX_PHY_CAP_40000FDX);
870 EFSYS_ASSERT(B_FALSE);
871 return (EFX_PHY_CAP_INVALID);
876 sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask)
878 /* Get global options (duplex), type and subtype bits */
879 int ifmedia_masked = ifmedia & (IFM_GMASK | IFM_NMASK | IFM_TMASK);
880 efx_phy_media_type_t medium_type;
881 boolean_t mode_found = B_FALSE;
882 uint32_t cap_mask, mode_cap_mask;
883 efx_link_mode_t mode;
884 efx_phy_cap_type_t phy_cap;
886 efx_phy_media_type_get(sc->enp, &medium_type);
887 if (medium_type >= nitems(sfxge_link_mode)) {
888 if_printf(sc->ifnet, "unexpected media type %d\n", medium_type);
892 efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask);
894 for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) {
895 if (ifmedia_masked == sfxge_link_mode[medium_type][mode]) {
903 * If media is not in the table, it must be IFM_AUTO.
905 KASSERT((cap_mask & (1 << EFX_PHY_CAP_AN)) &&
906 ifmedia_masked == (IFM_ETHER | IFM_AUTO),
907 ("%s: no mode for media %#x", __func__, ifmedia));
908 *phy_cap_mask = (cap_mask & ~(1 << EFX_PHY_CAP_ASYM));
912 phy_cap = sfxge_link_mode_to_phy_cap(mode);
913 if (phy_cap == EFX_PHY_CAP_INVALID) {
915 "cannot map link mode %d to phy capability\n",
920 mode_cap_mask = (1 << phy_cap);
921 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN);
922 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
923 if (ifmedia & IFM_ETH_RXPAUSE)
924 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE);
925 if (!(ifmedia & IFM_ETH_TXPAUSE))
926 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_ASYM);
928 mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE);
931 *phy_cap_mask = mode_cap_mask;
936 sfxge_media_change(struct ifnet *ifp)
938 struct sfxge_softc *sc;
939 struct ifmedia_entry *ifm;
941 uint32_t phy_cap_mask;
944 ifm = sc->media.ifm_cur;
946 SFXGE_ADAPTER_LOCK(sc);
948 if (!SFXGE_RUNNING(sc)) {
953 rc = efx_mac_fcntl_set(sc->enp, sfxge_port_wanted_fc(sc), B_TRUE);
957 if ((rc = sfxge_phy_cap_mask(sc, ifm->ifm_media, &phy_cap_mask)) != 0)
960 rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask);
962 SFXGE_ADAPTER_UNLOCK(sc);
967 int sfxge_port_ifmedia_init(struct sfxge_softc *sc)
969 efx_phy_media_type_t medium_type;
970 uint32_t cap_mask, mode_cap_mask;
971 efx_link_mode_t mode;
972 efx_phy_cap_type_t phy_cap;
973 int mode_ifm, best_mode_ifm = 0;
977 * We need port state to initialise the ifmedia list.
978 * It requires initialized NIC what is already done in
979 * sfxge_create() when resources are estimated.
981 if ((rc = efx_filter_init(sc->enp)) != 0)
983 if ((rc = efx_port_init(sc->enp)) != 0)
987 * Register ifconfig callbacks for querying and setting the
988 * link mode and link status.
990 ifmedia_init(&sc->media, IFM_IMASK, sfxge_media_change,
994 * Map firmware medium type and capabilities to ifmedia types.
995 * ifmedia does not distinguish between forcing the link mode
996 * and disabling auto-negotiation. 1000BASE-T and 10GBASE-T
997 * require AN even if only one link mode is enabled, and for
998 * 100BASE-TX it is useful even if the link mode is forced.
999 * Therefore we never disable auto-negotiation.
1001 * Also enable and advertise flow control by default.
1004 efx_phy_media_type_get(sc->enp, &medium_type);
1005 efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask);
1007 for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) {
1008 phy_cap = sfxge_link_mode_to_phy_cap(mode);
1009 if (phy_cap == EFX_PHY_CAP_INVALID)
1012 mode_cap_mask = (1 << phy_cap);
1013 mode_ifm = sfxge_link_mode[medium_type][mode];
1015 if ((cap_mask & mode_cap_mask) && mode_ifm) {
1016 /* No flow-control */
1017 ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1019 #ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS
1020 /* Respond-only. If using AN, we implicitly
1021 * offer symmetric as well, but that doesn't
1022 * mean we *have* to generate pause frames.
1024 mode_ifm |= IFM_ETH_RXPAUSE;
1025 ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1028 mode_ifm |= IFM_ETH_TXPAUSE;
1029 ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1032 /* Link modes are numbered in order of speed,
1033 * so assume the last one available is the best.
1035 best_mode_ifm = mode_ifm;
1039 if (cap_mask & (1 << EFX_PHY_CAP_AN)) {
1040 /* Add autoselect mode. */
1041 mode_ifm = IFM_ETHER | IFM_AUTO;
1042 ifmedia_add(&sc->media, mode_ifm, 0, NULL);
1043 best_mode_ifm = mode_ifm;
1046 if (best_mode_ifm != 0)
1047 ifmedia_set(&sc->media, best_mode_ifm);
1049 /* Now discard port state until interface is started. */
1050 efx_port_fini(sc->enp);
1052 efx_filter_fini(sc->enp);