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);
}

Reply via email to