Commit f502ef7d authored by Akeem G. Abodunrin's avatar Akeem G. Abodunrin Committed by Jeff Kirsher

igb: Support for 100base-fx SFP

This patch adds support for 100base-fx SFP and report proper link speed/duplex
via Ethtool.

v2: fix smatch warnings

CC: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarAkeem G Abodunrin <akeem.g.abodunrin@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 33243fb0
...@@ -98,7 +98,8 @@ enum e1000_mac_type { ...@@ -98,7 +98,8 @@ enum e1000_mac_type {
enum e1000_media_type { enum e1000_media_type {
e1000_media_type_unknown = 0, e1000_media_type_unknown = 0,
e1000_media_type_copper = 1, e1000_media_type_copper = 1,
e1000_media_type_internal_serdes = 2, e1000_media_type_fiber = 2,
e1000_media_type_internal_serdes = 3,
e1000_num_media_types e1000_num_media_types
}; };
......
...@@ -178,27 +178,33 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -178,27 +178,33 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP; ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy.addr; ecmd->phy_address = hw->phy.addr;
ecmd->transceiver = XCVR_INTERNAL;
} else { } else {
ecmd->supported = (SUPPORTED_1000baseT_Full | ecmd->supported = (SUPPORTED_1000baseT_Full |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_FIBRE | SUPPORTED_FIBRE |
SUPPORTED_Autoneg); SUPPORTED_Pause);
ecmd->advertising = (ADVERTISED_1000baseT_Full | ecmd->advertising = ADVERTISED_FIBRE;
ADVERTISED_FIBRE |
ADVERTISED_Autoneg | if (adapter->link_speed == SPEED_100)
ADVERTISED_Pause); ecmd->advertising = ADVERTISED_100baseT_Full;
else if (adapter->link_speed == SPEED_1000)
ecmd->advertising = ADVERTISED_1000baseT_Full;
if (hw->mac.autoneg == 1)
ecmd->advertising |= ADVERTISED_Autoneg;
ecmd->port = PORT_FIBRE; ecmd->port = PORT_FIBRE;
ecmd->transceiver = XCVR_EXTERNAL;
} }
ecmd->transceiver = XCVR_INTERNAL;
status = rd32(E1000_STATUS); status = rd32(E1000_STATUS);
if (status & E1000_STATUS_LU) { if (status & E1000_STATUS_LU) {
if ((status & E1000_STATUS_SPEED_1000) || if (status & E1000_STATUS_SPEED_1000)
hw->phy.media_type != e1000_media_type_copper)
ethtool_cmd_speed_set(ecmd, SPEED_1000); ethtool_cmd_speed_set(ecmd, SPEED_1000);
else if (status & E1000_STATUS_SPEED_100) else if (status & E1000_STATUS_SPEED_100)
ethtool_cmd_speed_set(ecmd, SPEED_100); ethtool_cmd_speed_set(ecmd, SPEED_100);
...@@ -215,7 +221,11 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -215,7 +221,11 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->duplex = -1; ecmd->duplex = -1;
} }
ecmd->autoneg = hw->mac.autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; if ((hw->phy.media_type == e1000_media_type_fiber) ||
hw->mac.autoneg)
ecmd->autoneg = AUTONEG_ENABLE;
else
ecmd->autoneg = AUTONEG_DISABLE;
/* MDI-X => 2; MDI =>1; Invalid =>0 */ /* MDI-X => 2; MDI =>1; Invalid =>0 */
if (hw->phy.media_type == e1000_media_type_copper) if (hw->phy.media_type == e1000_media_type_copper)
...@@ -266,9 +276,21 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -266,9 +276,21 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
if (ecmd->autoneg == AUTONEG_ENABLE) { if (ecmd->autoneg == AUTONEG_ENABLE) {
hw->mac.autoneg = 1; hw->mac.autoneg = 1;
if (hw->phy.media_type == e1000_media_type_fiber) {
hw->phy.autoneg_advertised = ecmd->advertising |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg;
if (adapter->link_speed == SPEED_1000)
hw->phy.autoneg_advertised =
ADVERTISED_1000baseT_Full;
else if (adapter->link_speed == SPEED_100)
hw->phy.autoneg_advertised =
ADVERTISED_100baseT_Full;
} else {
hw->phy.autoneg_advertised = ecmd->advertising | hw->phy.autoneg_advertised = ecmd->advertising |
ADVERTISED_TP | ADVERTISED_TP |
ADVERTISED_Autoneg; ADVERTISED_Autoneg;
}
ecmd->advertising = hw->phy.autoneg_advertised; ecmd->advertising = hw->phy.autoneg_advertised;
if (adapter->fc_autoneg) if (adapter->fc_autoneg)
hw->fc.requested_mode = e1000_fc_default; hw->fc.requested_mode = e1000_fc_default;
......
...@@ -7008,11 +7008,19 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx) ...@@ -7008,11 +7008,19 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u32 spd, u8 dplx)
if ((spd & 1) || (dplx & ~1)) if ((spd & 1) || (dplx & ~1))
goto err_inval; goto err_inval;
/* Fiber NIC's only allow 1000 Gbps Full duplex */ /* Fiber NIC's only allow 1000 gbps Full duplex
if ((adapter->hw.phy.media_type == e1000_media_type_internal_serdes) && * and 100Mbps Full duplex for 100baseFx sfp
spd != SPEED_1000 && */
dplx != DUPLEX_FULL) if (adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
switch (spd + dplx) {
case SPEED_10 + DUPLEX_HALF:
case SPEED_10 + DUPLEX_FULL:
case SPEED_100 + DUPLEX_HALF:
goto err_inval; goto err_inval;
default:
break;
}
}
switch (spd + dplx) { switch (spd + dplx) {
case SPEED_10 + DUPLEX_HALF: case SPEED_10 + DUPLEX_HALF:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment