From d70c47c8dc6902db19555b7ff7e6eeb264d4ac06 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 23 Apr 2020 21:34:33 +0200 Subject: [PATCH 1/3] net: phy: make phy_suspend a no-op if PHY is suspended already Gently handle the case that phy_suspend() is called whilst PHY is in power-down. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ac2784192472..206d98502b13 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1524,6 +1524,9 @@ int phy_suspend(struct phy_device *phydev) struct phy_driver *phydrv = phydev->drv; int ret; + if (phydev->suspended) + return 0; + /* If the device has WOL enabled, we cannot suspend the PHY */ phy_ethtool_get_wol(phydev, &wol); if (wol.wolopts || (netdev && netdev->wol_enabled)) From 3194915486b2bc3f77745774f1731b78f32ff688 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 23 Apr 2020 21:35:36 +0200 Subject: [PATCH 2/3] net: phy: remove genphy_no_soft_reset Since 6e2d85ec0559 ("net: phy: Stop with excessive soft reset") we don't need genphy_no_soft_reset() any longer. Not setting callback soft_reset results in a no-op now. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/cortina.c | 1 - drivers/net/phy/marvell10g.c | 2 -- drivers/net/phy/phy-c45.c | 1 - drivers/net/phy/phy_device.c | 1 - drivers/net/phy/teranetics.c | 1 - include/linux/phy.h | 4 ---- 6 files changed, 10 deletions(-) diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index 856cdc36aacd..aac51362c0fe 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -82,7 +82,6 @@ static struct phy_driver cortina_driver[] = { .features = PHY_10GBIT_FEATURES, .config_aneg = gen10g_config_aneg, .read_status = cortina_read_status, - .soft_reset = genphy_no_soft_reset, .probe = cortina_probe, }, }; diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 95e3f4644aeb..80cbc77ffd55 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -727,7 +727,6 @@ static struct phy_driver mv3310_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x3310", .get_features = mv3310_get_features, - .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .probe = mv3310_probe, .suspend = mv3310_suspend, @@ -745,7 +744,6 @@ static struct phy_driver mv3310_drivers[] = { .probe = mv3310_probe, .suspend = mv3310_suspend, .resume = mv3310_resume, - .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .config_aneg = mv3310_config_aneg, .aneg_done = mv3310_aneg_done, diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 67ba47ae5284..defe09d94422 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -564,6 +564,5 @@ struct phy_driver genphy_c45_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic Clause 45 PHY", - .soft_reset = genphy_no_soft_reset, .read_status = genphy_c45_read_status, }; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 206d98502b13..c8f8fd9908fe 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2630,7 +2630,6 @@ static struct phy_driver genphy_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic PHY", - .soft_reset = genphy_no_soft_reset, .get_features = genphy_read_abilities, .suspend = genphy_suspend, .resume = genphy_resume, diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index beb054b931ee..8057ea8dbc21 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -78,7 +78,6 @@ static struct phy_driver teranetics_driver[] = { .phy_id_mask = 0xffffffff, .name = "Teranetics TN2020", .features = PHY_10GBIT_FEATURES, - .soft_reset = genphy_no_soft_reset, .aneg_done = teranetics_aneg_done, .config_aneg = gen10g_config_aneg, .read_status = teranetics_read_status, diff --git a/include/linux/phy.h b/include/linux/phy.h index 3941a6bcba10..e2bfb9240587 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1251,10 +1251,6 @@ static inline int genphy_config_aneg(struct phy_device *phydev) return __genphy_config_aneg(phydev, false); } -static inline int genphy_no_soft_reset(struct phy_device *phydev) -{ - return 0; -} static inline int genphy_no_ack_interrupt(struct phy_device *phydev) { return 0; From 9576e9fa1c02aea3cf1e42eadcbeb12ccf5e87de Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 23 Apr 2020 21:38:42 +0200 Subject: [PATCH 3/3] net: phy: clear phydev->suspended after soft reset If a soft reset is triggered whilst PHY is in power-down, then phydev->suspended will remain set. Seems we didn't face any issue yet caused by this, but better reset the suspended flag after soft reset. See also the following from 22.2.4.1.1 Resetting a PHY is accomplished by setting bit 0.15 to a logic one. This action shall set the status and control registers to their default states. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index c8f8fd9908fe..7e1ddd5745d2 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1082,8 +1082,12 @@ int phy_init_hw(struct phy_device *phydev) if (!phydev->drv) return 0; - if (phydev->drv->soft_reset) + if (phydev->drv->soft_reset) { ret = phydev->drv->soft_reset(phydev); + /* see comment in genphy_soft_reset for an explanation */ + if (!ret) + phydev->suspended = 0; + } if (ret < 0) return ret; @@ -2157,6 +2161,12 @@ int genphy_soft_reset(struct phy_device *phydev) if (ret < 0) return ret; + /* Clause 22 states that setting bit BMCR_RESET sets control registers + * to their default value. Therefore the POWER DOWN bit is supposed to + * be cleared after soft reset. + */ + phydev->suspended = 0; + ret = phy_poll_reset(phydev); if (ret) return ret;