This patch adds 1GE SFP+ media support to Intel's 82599_SFP. I wasn't able to find a 1GE SFP/SFP+ LR (single mode) optic module for 82599, and therefore needed to bring my E10GSFPLR optics down in speed (possible in some other operating systems).
Some notes: * The patch is extensively tested on 82599_SFP (link ups/downs, reboot, used in production) * It seems to work on other NICs as well (82599_SFP_SF2, for example) but I've not been enable to perform careful testing on those * The patch is designed not to produce any functional change for people not explicitly setting media, in order to simplify testing and reviewing * I realise that 1000baseT is not the optimal media name for fibre, but since it was aleady used to report 1GE status in the driver, I didn't change it (in order to keep the patch small and reviewable) --- sys/dev/pci/if_ix.c-before-speed Thu May 2 11:05:16 2013 +++ sys/dev/pci/if_ix.c Fri May 3 16:56:26 2013 @@ -1067,8 +1067,44 @@ int ixgbe_media_change(struct ifnet * ifp) { - /* ignore */ - return (0); + struct ix_softc *sc = ifp->if_softc; + struct ifmedia *ifm = &sc->media; + ixgbe_link_speed speed; + int err = 0; + + INIT_DEBUGOUT("ixgbe_media_change: begin"); + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_AUTO: + speed = IXGBE_LINK_SPEED_100_FULL | + IXGBE_LINK_SPEED_1GB_FULL | + IXGBE_LINK_SPEED_10GB_FULL; + break; + case IFM_10G_T: + case IFM_10G_LR: + case IFM_10G_SR: + case IFM_10G_SFP_CU: + case IFM_10G_CX4: + speed = IXGBE_LINK_SPEED_10GB_FULL; + break; + case IFM_1000_T: + speed = IXGBE_LINK_SPEED_1GB_FULL; + break; + case IFM_100_TX: + speed = IXGBE_LINK_SPEED_100_FULL; + break; + default: + printf("%s: Unsupported media type\n", ifp->if_xname); + return (EINVAL); + } + + if (sc->hw.mac.ops.setup_link) + err = sc->hw.mac.ops.setup_link(&sc->hw, speed, FALSE, sc->link_up); + + return (err); } /********************************************************************* @@ -1632,6 +1668,10 @@ ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); } + if (hw->device_id == PCI_PRODUCT_INTEL_82599_SFP) { + ifmedia_add(&sc->media, + IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); + } ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); @@ -1645,6 +1685,8 @@ void ixgbe_config_link(struct ix_softc *sc) { + struct ixgbe_hw *hw = &sc->hw; + struct ifmedia *ifm = &sc->media; uint32_t autoneg, err = 0; int sfp, negotiate = FALSE; @@ -1688,6 +1730,13 @@ err = sc->hw.mac.ops.setup_link(&sc->hw, autoneg, negotiate, sc->link_up); } + + /* 82599_SFP defaults to 10G when brought up, sync with user set */ + if ((hw->device_id == PCI_PRODUCT_INTEL_82599_SFP) && + (IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_T) && + (sc->hw.mac.ops.setup_link)) + err = sc->hw.mac.ops.setup_link(&sc->hw, + IXGBE_LINK_SPEED_1GB_FULL, FALSE, sc->link_up); }