net: phy: don’t clear BMCR in genphy_soft_reset [Linux 3.16.72]

This Linux kernel change "net: phy: don’t clear BMCR in genphy_soft_reset" is included in the Linux 3.16.72 release. This change is authored by Heiner Kallweit <hkallweit1 [at] gmail.com> on Fri Mar 22 20:00:20 2019 +0100. The commit for this change in Linux stable tree is 521ee6f (patch) which is from upstream commit d29f5aa. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream d29f5aa.

net: phy: don't clear BMCR in genphy_soft_reset

commit d29f5aa0bc0c321e1b9e4658a2a7e08e885da52a upstream.

So far we effectively clear the BMCR register. Some PHY's can deal
with this (e.g. because they reset BMCR to a default as part of a
soft-reset) whilst on others this causes issues because e.g. the
autoneg bit is cleared. Marvell is an example, see also thread [0].
So let's be a little bit more gentle and leave all bits we're not
interested in as-is. This change is needed for PHY drivers to
properly deal with the original patch.

[0] https://marc.info/?t=155264050700001&r=1&w=2

Fixes: 6e2d85ec0559 ("net: phy: Stop with excessive soft reset")
Tested-by: Phil Reid <[email protected]>
Tested-by: liweihang <[email protected]>
Signed-off-by: Heiner Kallweit <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
[bwh: Backported to 3.16: open-code phy_set_bits()]
Signed-off-by: Ben Hutchings <[email protected]>

There are 5 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/phy/phy_device.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 7a6d2f8..77fcb1b 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1072,7 +1072,10 @@ int genphy_soft_reset(struct phy_device *phydev)
 {
    int ret;

-   ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
+   ret = phy_read(phydev, MII_BMCR);
+   if (ret < 0)
+       return ret;
+   ret = phy_write(phydev, MII_BMCR, ret | BMCR_RESET);
    if (ret < 0)
        return ret;

Leave a Reply

Your email address will not be published. Required fields are marked *