Commit dd92f179 authored by David S. Miller's avatar David S. Miller

Merge branch '100base-Fx-link-modes'

Dan Murphy says:

====================
100base Fx link modes

As per patch https://lore.kernel.org/patchwork/patch/1300241/ the link
modes for 100base FX full and half duplex modes did not exist.  Adding
these link modes to the core and ethtool allow devices like the
DP83822, DP83869 and Broadcomm PHYs to properly advertise the correct
mode for Fiber 100Mbps.

Corresponding user land ethtool patches are available but rely on
these patches to be applied first.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 09599729 9ef7e18b
......@@ -110,9 +110,8 @@
#define DP83822_RX_ER_SHIFT 8
#define MII_DP83822_FIBER_ADVERTISE (ADVERTISED_TP | ADVERTISED_MII | \
ADVERTISED_FIBRE | ADVERTISED_BNC | \
ADVERTISED_Pause | ADVERTISED_Asym_Pause | \
ADVERTISED_100baseT_Full)
ADVERTISED_FIBRE | \
ADVERTISED_Pause | ADVERTISED_Asym_Pause)
struct dp83822_private {
bool fx_signal_det_low;
......@@ -406,6 +405,14 @@ static int dp83822_config_init(struct phy_device *phydev)
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
phydev->advertising);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
phydev->advertising);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
phydev->advertising);
/* Auto neg is not supported in fiber mode */
bmcr = phy_read(phydev, MII_BMCR);
......
......@@ -52,6 +52,10 @@
BMCR_FULLDPLX | \
BMCR_SPEED1000)
#define MII_DP83869_FIBER_ADVERTISE (ADVERTISED_FIBRE | \
ADVERTISED_Pause | \
ADVERTISED_Asym_Pause)
/* This is the same bit mask as the BMCR so re-use the BMCR default */
#define DP83869_FX_CTRL_DEFAULT MII_DP83869_BMCR_DEFAULT
......@@ -118,6 +122,28 @@ struct dp83869_private {
int mode;
};
static int dp83869_read_status(struct phy_device *phydev)
{
struct dp83869_private *dp83869 = phydev->priv;
int ret;
ret = genphy_read_status(phydev);
if (ret)
return ret;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
if (phydev->link) {
if (dp83869->mode == DP83869_RGMII_100_BASE)
phydev->speed = SPEED_100;
} else {
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
}
}
return 0;
}
static int dp83869_ack_interrupt(struct phy_device *phydev)
{
int err = phy_read(phydev, MII_DP83869_ISR);
......@@ -295,6 +321,51 @@ static int dp83869_configure_rgmii(struct phy_device *phydev,
return ret;
}
static int dp83869_configure_fiber(struct phy_device *phydev,
struct dp83869_private *dp83869)
{
int bmcr;
int ret;
/* Only allow advertising what this PHY supports */
linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
linkmode_set_bit(ADVERTISED_FIBRE, phydev->advertising);
if (dp83869->mode == DP83869_RGMII_1000_BASE) {
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->supported);
} else {
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
phydev->supported);
/* Auto neg is not supported in 100base FX mode */
bmcr = phy_read(phydev, MII_BMCR);
if (bmcr < 0)
return bmcr;
phydev->autoneg = AUTONEG_DISABLE;
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->advertising);
if (bmcr & BMCR_ANENABLE) {
ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
if (ret < 0)
return ret;
}
}
/* Update advertising from supported */
linkmode_or(phydev->advertising, phydev->advertising,
phydev->supported);
return 0;
}
static int dp83869_configure_mode(struct phy_device *phydev,
struct dp83869_private *dp83869)
{
......@@ -384,6 +455,7 @@ static int dp83869_configure_mode(struct phy_device *phydev,
break;
case DP83869_RGMII_1000_BASE:
case DP83869_RGMII_100_BASE:
ret = dp83869_configure_fiber(phydev, dp83869);
break;
default:
return -EINVAL;
......@@ -494,6 +566,7 @@ static struct phy_driver dp83869_driver[] = {
/* IRQ related */
.ack_interrupt = dp83869_ack_interrupt,
.config_intr = dp83869_config_intr,
.read_status = dp83869_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
......
......@@ -8,7 +8,7 @@
const char *phy_speed_to_str(int speed)
{
BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 90,
BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 92,
"Enum ethtool_link_mode_bit_indices and phylib are out of sync. "
"If a speed or mode has been added please update phy_speed_to_str "
"and the PHY settings array.\n");
......@@ -160,6 +160,8 @@ static const struct phy_setting settings[] = {
PHY_SETTING( 100, FULL, 100baseT_Full ),
PHY_SETTING( 100, FULL, 100baseT1_Full ),
PHY_SETTING( 100, HALF, 100baseT_Half ),
PHY_SETTING( 100, HALF, 100baseFX_Half ),
PHY_SETTING( 100, FULL, 100baseFX_Full ),
/* 10M */
PHY_SETTING( 10, FULL, 10baseT_Full ),
PHY_SETTING( 10, HALF, 10baseT_Half ),
......
......@@ -1617,6 +1617,8 @@ enum ethtool_link_mode_bit_indices {
ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87,
ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 88,
ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89,
ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90,
ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91,
/* must be last entry */
__ETHTOOL_LINK_MODE_MASK_NBITS
};
......
......@@ -192,6 +192,8 @@ const char link_mode_names[][ETH_GSTRING_LEN] = {
__DEFINE_LINK_MODE_NAME(400000, LR4_ER4_FR4, Full),
__DEFINE_LINK_MODE_NAME(400000, DR4, Full),
__DEFINE_LINK_MODE_NAME(400000, CR4, Full),
__DEFINE_LINK_MODE_NAME(100, FX, Half),
__DEFINE_LINK_MODE_NAME(100, FX, Full),
};
static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
......
......@@ -272,6 +272,8 @@ static const struct link_mode_info link_mode_params[] = {
__DEFINE_LINK_MODE_PARAMS(400000, LR4_ER4_FR4, Full),
__DEFINE_LINK_MODE_PARAMS(400000, DR4, Full),
__DEFINE_LINK_MODE_PARAMS(400000, CR4, Full),
__DEFINE_LINK_MODE_PARAMS(100, FX, Half),
__DEFINE_LINK_MODE_PARAMS(100, FX, Full),
};
static const struct nla_policy
......
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