From owner-svn-src-head@FreeBSD.ORG Sat May 16 10:35:31 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 31052D36; Sat, 16 May 2015 10:35:31 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1FB8115D8; Sat, 16 May 2015 10:35:31 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t4GAZUrH084399; Sat, 16 May 2015 10:35:30 GMT (envelope-from arybchik@FreeBSD.org) Received: (from arybchik@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t4GAZUAk084398; Sat, 16 May 2015 10:35:30 GMT (envelope-from arybchik@FreeBSD.org) Message-Id: <201505161035.t4GAZUAk084398@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: arybchik set sender to arybchik@FreeBSD.org using -f From: Andrew Rybchenko Date: Sat, 16 May 2015 10:35:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r283007 - head/sys/dev/sfxge X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 May 2015 10:35:31 -0000 Author: arybchik Date: Sat May 16 10:35:30 2015 New Revision: 283007 URL: https://svnweb.freebsd.org/changeset/base/283007 Log: sfxge: avoid usage of ifm_data The driver uses ifm_data to save capabilities mask calculated during initialization when supported phy modes are discovered. The patch simply calculates it when either media or options are changed. Reviewed by: glebius Sponsored by: Solarflare Communications, Inc. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D2540 Modified: head/sys/dev/sfxge/sfxge_port.c Modified: head/sys/dev/sfxge/sfxge_port.c ============================================================================== --- head/sys/dev/sfxge/sfxge_port.c Sat May 16 10:31:15 2015 (r283006) +++ head/sys/dev/sfxge/sfxge_port.c Sat May 16 10:35:30 2015 (r283007) @@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$"); #include "sfxge.h" +static int sfxge_phy_cap_mask(struct sfxge_softc *, int, uint32_t *); + static int sfxge_mac_stat_update(struct sfxge_softc *sc) { @@ -443,6 +445,7 @@ sfxge_port_start(struct sfxge_softc *sc) efx_nic_t *enp; size_t pdu; int rc; + uint32_t phy_cap_mask; port = &sc->port; enp = sc->enp; @@ -483,10 +486,13 @@ sfxge_port_start(struct sfxge_softc *sc) if ((rc = efx_mac_drain(enp, B_FALSE)) != 0) goto fail3; - if ((rc = efx_phy_adv_cap_set(sc->enp, sc->media.ifm_cur->ifm_data)) - != 0) + if ((rc = sfxge_phy_cap_mask(sc, sc->media.ifm_cur->ifm_media, + &phy_cap_mask)) != 0) goto fail4; + if ((rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask)) != 0) + goto fail5; + port->init_state = SFXGE_PORT_STARTED; /* Single poll in case there were missing initial events */ @@ -495,6 +501,7 @@ sfxge_port_start(struct sfxge_softc *sc) return (0); +fail5: fail4: (void)efx_mac_drain(enp, B_TRUE); fail3: @@ -738,12 +745,95 @@ sfxge_media_status(struct ifnet *ifp, st SFXGE_ADAPTER_UNLOCK(sc); } +static efx_phy_cap_type_t +sfxge_link_mode_to_phy_cap(efx_link_mode_t mode) +{ + switch (mode) { + case EFX_LINK_10HDX: + return (EFX_PHY_CAP_10HDX); + case EFX_LINK_10FDX: + return (EFX_PHY_CAP_10FDX); + case EFX_LINK_100HDX: + return (EFX_PHY_CAP_100HDX); + case EFX_LINK_100FDX: + return (EFX_PHY_CAP_100FDX); + case EFX_LINK_1000HDX: + return (EFX_PHY_CAP_1000HDX); + case EFX_LINK_1000FDX: + return (EFX_PHY_CAP_1000FDX); + case EFX_LINK_10000FDX: + return (EFX_PHY_CAP_10000FDX); + default: + EFSYS_ASSERT(B_FALSE); + return (EFX_PHY_CAP_INVALID); + } +} + +static int +sfxge_phy_cap_mask(struct sfxge_softc *sc, int ifmedia, uint32_t *phy_cap_mask) +{ + efx_phy_media_type_t medium_type; + boolean_t mode_found = B_FALSE; + uint32_t cap_mask, mode_cap_mask; + efx_link_mode_t mode; + efx_phy_cap_type_t phy_cap; + + efx_phy_media_type_get(sc->enp, &medium_type); + if (medium_type >= nitems(sfxge_link_mode)) { + if_printf(sc->ifnet, "unexpected media type %d\n", medium_type); + return (EINVAL); + } + + efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); + + for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) { + if (ifmedia == sfxge_link_mode[medium_type][mode]) { + mode_found = B_TRUE; + break; + } + } + + if (!mode_found) { + /* + * If media is not in the table, it must be IFM_AUTO. + */ + KASSERT((cap_mask & (1 << EFX_PHY_CAP_AN)) && + ifmedia == (IFM_ETHER | IFM_AUTO), + ("%s: no mode for media %d", __func__, ifmedia)); + *phy_cap_mask = (cap_mask & ~(1 << EFX_PHY_CAP_ASYM)); + return (0); + } + + phy_cap = sfxge_link_mode_to_phy_cap(mode); + if (phy_cap == EFX_PHY_CAP_INVALID) { + if_printf(sc->ifnet, + "cannot map link mode %d to phy capability\n", + mode); + return (EINVAL); + } + + mode_cap_mask = (1 << phy_cap); + mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN); +#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS + if (ifmedia & IFM_ETH_RXPAUSE) + mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); + if (!(ifmedia & IFM_ETH_TXPAUSE)) + mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_ASYM); +#else + mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); +#endif + + *phy_cap_mask = mode_cap_mask; + return (0); +} + static int sfxge_media_change(struct ifnet *ifp) { struct sfxge_softc *sc; struct ifmedia_entry *ifm; int rc; + uint32_t phy_cap_mask; sc = ifp->if_softc; ifm = sc->media.ifm_cur; @@ -759,7 +849,10 @@ sfxge_media_change(struct ifnet *ifp) if (rc != 0) goto out; - rc = efx_phy_adv_cap_set(sc->enp, ifm->ifm_data); + if ((rc = sfxge_phy_cap_mask(sc, ifm->ifm_media, &phy_cap_mask)) != 0) + goto out; + + rc = efx_phy_adv_cap_set(sc->enp, phy_cap_mask); out: SFXGE_ADAPTER_UNLOCK(sc); @@ -771,6 +864,7 @@ int sfxge_port_ifmedia_init(struct sfxge efx_phy_media_type_t medium_type; uint32_t cap_mask, mode_cap_mask; efx_link_mode_t mode; + efx_phy_cap_type_t phy_cap; int mode_ifm, best_mode_ifm = 0; int rc; @@ -801,41 +895,30 @@ int sfxge_port_ifmedia_init(struct sfxge efx_phy_media_type_get(sc->enp, &medium_type); efx_phy_adv_cap_get(sc->enp, EFX_PHY_CAP_PERM, &cap_mask); - EFX_STATIC_ASSERT(EFX_LINK_10HDX == EFX_PHY_CAP_10HDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_10FDX == EFX_PHY_CAP_10FDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_100HDX == EFX_PHY_CAP_100HDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_100FDX == EFX_PHY_CAP_100FDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_1000HDX == EFX_PHY_CAP_1000HDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_1000FDX == EFX_PHY_CAP_1000FDX + 1); - EFX_STATIC_ASSERT(EFX_LINK_10000FDX == EFX_PHY_CAP_10000FDX + 1); + for (mode = EFX_LINK_10HDX; mode < EFX_LINK_NMODES; mode++) { + phy_cap = sfxge_link_mode_to_phy_cap(mode); + if (phy_cap == EFX_PHY_CAP_INVALID) + continue; - for (mode = EFX_LINK_10HDX; mode <= EFX_LINK_10000FDX; mode++) { - mode_cap_mask = 1 << (mode - 1); + mode_cap_mask = (1 << phy_cap); mode_ifm = sfxge_link_mode[medium_type][mode]; if ((cap_mask & mode_cap_mask) && mode_ifm) { - mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_AN); - -#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS /* No flow-control */ - ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); + ifmedia_add(&sc->media, mode_ifm, 0, NULL); +#ifdef SFXGE_HAVE_PAUSE_MEDIAOPTS /* Respond-only. If using AN, we implicitly * offer symmetric as well, but that doesn't * mean we *have* to generate pause frames. */ - mode_cap_mask |= cap_mask & ((1 << EFX_PHY_CAP_PAUSE) | - (1 << EFX_PHY_CAP_ASYM)); mode_ifm |= IFM_ETH_RXPAUSE; - ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); + ifmedia_add(&sc->media, mode_ifm, 0, NULL); /* Symmetric */ - mode_cap_mask &= ~(1 << EFX_PHY_CAP_ASYM); mode_ifm |= IFM_ETH_TXPAUSE; -#else /* !SFXGE_HAVE_PAUSE_MEDIAOPTS */ - mode_cap_mask |= cap_mask & (1 << EFX_PHY_CAP_PAUSE); + ifmedia_add(&sc->media, mode_ifm, 0, NULL); #endif - ifmedia_add(&sc->media, mode_ifm, mode_cap_mask, NULL); /* Link modes are numbered in order of speed, * so assume the last one available is the best. @@ -847,8 +930,7 @@ int sfxge_port_ifmedia_init(struct sfxge if (cap_mask & (1 << EFX_PHY_CAP_AN)) { /* Add autoselect mode. */ mode_ifm = IFM_ETHER | IFM_AUTO; - ifmedia_add(&sc->media, mode_ifm, - cap_mask & ~(1 << EFX_PHY_CAP_ASYM), NULL); + ifmedia_add(&sc->media, mode_ifm, 0, NULL); best_mode_ifm = mode_ifm; }