Hi,

I haven't gotten any feedback on the following diff
but I think there's still hope.  Please test.

Original mail:

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

Reply via email to