Hi, I won't mind some broad testing of the following diff which adds some additional media options to ix(4) from FreeBSD and includes a fix for changing media from Masanobu SAITOH.
The fix makes sure that when the media operation speed is selected manually, the device doesn't additionally advertise other (slower) modes. diff --git sys/dev/pci/if_ix.c sys/dev/pci/if_ix.c index 339ba2bc4f1..8fca8742f7f 100644 --- sys/dev/pci/if_ix.c +++ sys/dev/pci/if_ix.c @@ -1028,62 +1028,115 @@ ixgbe_intr(void *arg) * This routine is called whenever the user queries the status of * the interface using ifconfig. * **********************************************************************/ void -ixgbe_media_status(struct ifnet * ifp, struct ifmediareq *ifmr) +ixgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) { struct ix_softc *sc = ifp->if_softc; + int layer; + + layer = sc->hw.mac.ops.get_supported_physical_layer(&sc->hw); ifmr->ifm_active = IFM_ETHER; ifmr->ifm_status = IFM_AVALID; INIT_DEBUGOUT("ixgbe_media_status: begin"); ixgbe_update_link_status(sc); - if (LINK_STATE_IS_UP(ifp->if_link_state)) { - ifmr->ifm_status |= IFM_ACTIVE; + if (!LINK_STATE_IS_UP(ifp->if_link_state)) + return; + + ifmr->ifm_status |= IFM_ACTIVE; + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_T || + layer & IXGBE_PHYSICAL_LAYER_1000BASE_T || + layer & IXGBE_PHYSICAL_LAYER_100BASE_TX) switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_T | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_T | IFM_FDX; + break; case IXGBE_LINK_SPEED_100_FULL: ifmr->ifm_active |= IFM_100_TX | IFM_FDX; break; + } + if (layer & IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU || + layer & IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_SFP_CU | IFM_FDX; + break; + } + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LR) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_LR | IFM_FDX; + break; case IXGBE_LINK_SPEED_1GB_FULL: - switch (sc->optics) { - case IFM_10G_SR: /* multi-speed fiber */ - ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; - break; - case IFM_10G_LR: /* multi-speed fiber */ - ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; - break; - default: - ifmr->ifm_active |= sc->optics | IFM_FDX; - break; - } + ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; break; + } + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_LRM) + switch (sc->link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: - ifmr->ifm_active |= sc->optics | IFM_FDX; + ifmr->ifm_active |= IFM_10G_LRM | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_LX | IFM_FDX; break; } - - switch (sc->hw.fc.current_mode) { - case ixgbe_fc_tx_pause: - ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE; + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_SR || + layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_SR | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_SX | IFM_FDX; break; - case ixgbe_fc_rx_pause: - ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE; + } + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_CX4 | IFM_FDX; break; - case ixgbe_fc_full: - ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE | - IFM_ETH_TXPAUSE; + } + if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_KR | IFM_FDX; break; - default: - ifmr->ifm_active &= ~(IFM_FLOW | IFM_ETH_RXPAUSE | - IFM_ETH_TXPAUSE); + case IXGBE_LINK_SPEED_2_5GB_FULL: + ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; break; } - } + else if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4 + || layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) + switch (sc->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + ifmr->ifm_active |= IFM_10G_KX4 | IFM_FDX; + break; + case IXGBE_LINK_SPEED_2_5GB_FULL: + ifmr->ifm_active |= IFM_2500_KX | IFM_FDX; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + ifmr->ifm_active |= IFM_1000_KX | IFM_FDX; + break; + } + + if (sc->hw.fc.current_mode == ixgbe_fc_rx_pause || + sc->hw.fc.current_mode == ixgbe_fc_full) + ifmr->ifm_active |= IFM_FLOW | IFM_ETH_RXPAUSE; + if (sc->hw.fc.current_mode == ixgbe_fc_tx_pause || + sc->hw.fc.current_mode == ixgbe_fc_full) + ifmr->ifm_active |= IFM_FLOW | IFM_ETH_TXPAUSE; } /********************************************************************* * * Media Ioctl callback @@ -1097,37 +1150,43 @@ ixgbe_media_change(struct ifnet *ifp) { struct ix_softc *sc = ifp->if_softc; struct ixgbe_hw *hw = &sc->hw; struct ifmedia *ifm = &sc->media; ixgbe_link_speed speed = 0; + bool autoneg; if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) return (EINVAL); if (hw->phy.media_type == ixgbe_media_type_backplane) return (ENODEV); switch (IFM_SUBTYPE(ifm->ifm_media)) { case IFM_AUTO: + if (!hw->mac.ops.get_link_capabilities || + hw->mac.ops.get_link_capabilities(hw, &speed, + &autoneg)) + return (EINVAL); + break; case IFM_10G_T: - speed |= IXGBE_LINK_SPEED_100_FULL; - case IFM_10G_SR: /* KR, too */ + case IFM_10G_LRM: + case IFM_10G_SR: + case IFM_10G_KR: case IFM_10G_LR: - case IFM_10G_CX4: /* KX4 */ - speed |= IXGBE_LINK_SPEED_1GB_FULL; + case IFM_10G_KX4: + case IFM_10G_CX4: case IFM_10G_SFP_CU: - speed |= IXGBE_LINK_SPEED_10GB_FULL; + speed = IXGBE_LINK_SPEED_10GB_FULL; break; case IFM_1000_T: - speed |= IXGBE_LINK_SPEED_100_FULL; case IFM_1000_LX: case IFM_1000_SX: - case IFM_1000_CX: /* KX */ - speed |= IXGBE_LINK_SPEED_1GB_FULL; + case IFM_1000_KX: + speed = IXGBE_LINK_SPEED_1GB_FULL; break; case IFM_100_TX: - speed |= IXGBE_LINK_SPEED_100_FULL; + speed = IXGBE_LINK_SPEED_100_FULL; break; default: return (EINVAL); } @@ -1675,15 +1734,15 @@ ixgbe_add_media_types(struct ix_softc *sc) } else if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_SX, 0, NULL); if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_CX4) ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KR) - ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_SR, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KR, 0, NULL); if (layer & IXGBE_PHYSICAL_LAYER_10GBASE_KX4) - ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_CX4, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_10G_KX4, 0, NULL); if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_KX) - ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_CX, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_KX, 0, NULL); if (hw->device_id == IXGBE_DEV_ID_82598AT) { ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T, 0, NULL);