diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 16 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 81 |
2 files changed, 89 insertions, 8 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 08243c2ff4b4..bfa10c3da35f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2058,8 +2058,8 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep) } } -static int fec_enet_get_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int fec_enet_get_link_ksettings(struct net_device *ndev, + struct ethtool_link_ksettings *cmd) { struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; @@ -2067,11 +2067,11 @@ static int fec_enet_get_settings(struct net_device *ndev, if (!phydev) return -ENODEV; - return phy_ethtool_gset(phydev, cmd); + return phy_ethtool_ksettings_get(phydev, cmd); } -static int fec_enet_set_settings(struct net_device *ndev, - struct ethtool_cmd *cmd) +static int fec_enet_set_link_ksettings(struct net_device *ndev, + const struct ethtool_link_ksettings *cmd) { struct fec_enet_private *fep = netdev_priv(ndev); struct phy_device *phydev = fep->phy_dev; @@ -2079,7 +2079,7 @@ static int fec_enet_set_settings(struct net_device *ndev, if (!phydev) return -ENODEV; - return phy_ethtool_sset(phydev, cmd); + return phy_ethtool_ksettings_set(phydev, cmd); } static void fec_enet_get_drvinfo(struct net_device *ndev, @@ -2562,8 +2562,6 @@ fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) } static const struct ethtool_ops fec_enet_ethtool_ops = { - .get_settings = fec_enet_get_settings, - .set_settings = fec_enet_set_settings, .get_drvinfo = fec_enet_get_drvinfo, .get_regs_len = fec_enet_get_regs_len, .get_regs = fec_enet_get_regs, @@ -2583,6 +2581,8 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .set_tunable = fec_enet_set_tunable, .get_wol = fec_enet_get_wol, .set_wol = fec_enet_set_wol, + .get_link_ksettings = fec_enet_get_link_ksettings, + .set_link_ksettings = fec_enet_set_link_ksettings, }; static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 5590b9c182c9..6f221c8c2a7f 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -362,6 +362,60 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) } EXPORT_SYMBOL(phy_ethtool_sset); +int phy_ethtool_ksettings_set(struct phy_device *phydev, + const struct ethtool_link_ksettings *cmd) +{ + u8 autoneg = cmd->base.autoneg; + u8 duplex = cmd->base.duplex; + u32 speed = cmd->base.speed; + u32 advertising; + + if (cmd->base.phy_address != phydev->mdio.addr) + return -EINVAL; + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + + /* We make sure that we don't pass unsupported values in to the PHY */ + advertising &= phydev->supported; + + /* Verify the settings we care about. */ + if (autoneg != AUTONEG_ENABLE && autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (autoneg == AUTONEG_ENABLE && advertising == 0) + return -EINVAL; + + if (autoneg == AUTONEG_DISABLE && + ((speed != SPEED_1000 && + speed != SPEED_100 && + speed != SPEED_10) || + (duplex != DUPLEX_HALF && + duplex != DUPLEX_FULL))) + return -EINVAL; + + phydev->autoneg = autoneg; + + phydev->speed = speed; + + phydev->advertising = advertising; + + if (autoneg == AUTONEG_ENABLE) + phydev->advertising |= ADVERTISED_Autoneg; + else + phydev->advertising &= ~ADVERTISED_Autoneg; + + phydev->duplex = duplex; + + phydev->mdix = cmd->base.eth_tp_mdix_ctrl; + + /* Restart the PHY */ + phy_start_aneg(phydev); + + return 0; +} +EXPORT_SYMBOL(phy_ethtool_ksettings_set); + int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) { cmd->supported = phydev->supported; @@ -385,6 +439,33 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) } EXPORT_SYMBOL(phy_ethtool_gset); +int phy_ethtool_ksettings_get(struct phy_device *phydev, + struct ethtool_link_ksettings *cmd) +{ + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, + phydev->supported); + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, + phydev->advertising); + + ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, + phydev->lp_advertising); + + cmd->base.speed = phydev->speed; + cmd->base.duplex = phydev->duplex; + if (phydev->interface == PHY_INTERFACE_MODE_MOCA) + cmd->base.port = PORT_BNC; + else + cmd->base.port = PORT_MII; + + cmd->base.phy_address = phydev->mdio.addr; + cmd->base.autoneg = phydev->autoneg; + cmd->base.eth_tp_mdix_ctrl = phydev->mdix; + + return 0; +} +EXPORT_SYMBOL(phy_ethtool_ksettings_get); + /** * phy_mii_ioctl - generic PHY MII ioctl interface * @phydev: the phy_device struct |