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