diff options
author | Weiguo Hu <hwg@rock-chips.com> | 2018-02-10 11:42:55 +0800 |
---|---|---|
committer | Shirley Shuk Yee Yuen <shirleyshukyee@google.com> | 2018-04-13 13:57:27 -0400 |
commit | b9970f9bc9304d8cd13f828da037209b81e31055 (patch) | |
tree | a9b9916b72552ffaaa4c60131fab8e8eff6900f9 | |
parent | 6c179b3c311a62e55f62ded31af1271f60085d40 (diff) | |
download | rk-v4.4-b9970f9bc9304d8cd13f828da037209b81e31055.tar.gz |
net: phy: rockchip: do phy reset once in no link status
This solve failed to linkup for very few chip
This can reduce udp package lost rate sometimes
Change-Id: I684d9ea974e56478e7906c6e79c4c8505c042823
Signed-off-by: Weiguo Hu <hwg@rock-chips.com>
-rw-r--r-- | drivers/net/phy/rockchip.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/drivers/net/phy/rockchip.c b/drivers/net/phy/rockchip.c index b63b3448aaa4..4ee9fa5c2e34 100644 --- a/drivers/net/phy/rockchip.c +++ b/drivers/net/phy/rockchip.c @@ -57,6 +57,8 @@ #define PHY_ABNORMAL_THRESHOLD 15 +#define ENABLE_PHY_FIXUP_RESET + struct rk_int_phy_priv { int restore_reg0; int restore_a3_config; @@ -64,6 +66,8 @@ struct rk_int_phy_priv { int a3_config_set; int txrx_counters_done_count; int last_speed; + int last_state; + int reset; }; static int rockchip_integrated_phy_init_tstmode(struct phy_device *phydev) @@ -192,42 +196,15 @@ static int rockchip_integrated_phy_adjust_a3_config(struct phy_device *phydev, static void rockchip_integrated_phy_link_change_notify(struct phy_device *phydev) { - int speed = SPEED_10; struct rk_int_phy_priv *priv = phydev->priv; - if (phydev->autoneg == AUTONEG_ENABLE) { - int reg = phy_read(phydev, MII_SPECIAL_CONTROL_STATUS); - - if (reg < 0) { - phydev_err(phydev, "phy_read err: %d.\n", reg); - return; - } - - if (reg & MII_SPEED_100) - speed = SPEED_100; - else if (reg & MII_SPEED_10) - speed = SPEED_10; - } else { - int bmcr = phy_read(phydev, MII_BMCR); - - if (bmcr < 0) { - phydev_err(phydev, "phy_read err: %d.\n", bmcr); - return; - } - - if (bmcr & BMCR_SPEED100) - speed = SPEED_100; - else - speed = SPEED_10; - } - /* * If mode switch happens from 10BT to 100BT, all DSP/AFE * registers are set to default values. So any AFE/DSP * registers have to be re-initialized in this case. */ if (phydev->link && - speed == SPEED_100 && + phydev->speed == SPEED_100 && priv->last_speed == SPEED_10) { int ret = rockchip_integrated_phy_analog_init(phydev); @@ -237,7 +214,7 @@ void rockchip_integrated_phy_link_change_notify(struct phy_device *phydev) } if (phydev->link) - priv->last_speed = speed; + priv->last_speed = phydev->speed; } static int rockchip_set_polarity(struct phy_device *phydev, int polarity) @@ -398,6 +375,30 @@ static int rockchip_integrated_phy_fixup_100M(struct phy_device *phydev) return 0; } +#ifdef ENABLE_PHY_FIXUP_RESET +static int rockchip_integrated_phy_fixup_reset(struct phy_device *phydev) +{ + int ret; + struct rk_int_phy_priv *priv = phydev->priv; + + /* reset phy once + * solve failed to linkup for very few chip + * reduce udp package lost rate sometimes + */ + if (priv->last_state == PHY_NOLINK && phydev->state == PHY_NOLINK) { + if (++priv->reset == 2) { + phydev_dbg(phydev, "%s\n", __func__); + ret = genphy_soft_reset(phydev); + if (ret < 0) + return ret; + } + } + + priv->last_state = phydev->state; + return 0; +} +#endif + static int rockchip_integrated_phy_read_status(struct phy_device *phydev) { int ret; @@ -414,6 +415,12 @@ static int rockchip_integrated_phy_read_status(struct phy_device *phydev) if (ret) return ret; +#ifdef ENABLE_PHY_FIXUP_RESET + ret = rockchip_integrated_phy_fixup_reset(phydev); + if (ret) + return ret; +#endif + return 0; } |