[OpenWrt-Devel] [PATCH] ar8216: fix issue with ANEG being disabled with kernel >=3.14

Heiner Kallweit hkallweit1 at gmail.com
Thu Nov 13 16:00:44 EST 2014


See also ticket 17800
With kernel>=3.14 autonegotiation is disabled at least for AR8327 based
switches. Reason is that with 3.14 an additional phy reset was
introduced in phy_init_hw in drivers/net/phy/phy_device.c
This reset clears BMCR_ANENABLE.
After the reset phy_init_hw calls the driver's config_init callback
which however for ar8327/8337 does nothing.
Fix the issue by extending ar8xxx_phy_config_init to check for
BMCR_ANENABLE being set in case of ar8327/ar8337.
If needed set the flag and restart autonegotiation.

For kernel>=3.16 the phy reset in phy_init_hw can be overwritten by
a soft_reset callback provided by the phy driver.
ar8216 driver takes care of resetting the switch properly for all
supported switch types anyway, therefore provide a dummy soft_reset
callback to disable the unneeded additional phy reset.

Signed-off-by: Heiner Kallweit <hkallweit1 at gmail.com>
---
 .../linux/generic/files/drivers/net/phy/ar8216.c   | 34 ++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index 4410fbb..03de384 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -36,6 +36,7 @@
 #include <linux/of_device.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
+#include <linux/version.h>
 
 #include "ar8216.h"
 
@@ -2765,8 +2766,24 @@ ar8xxx_phy_config_init(struct phy_device *phydev)
 	if (WARN_ON(!priv))
 		return -ENODEV;
 
-	if (chip_is_ar8327(priv) || chip_is_ar8337(priv))
-		return 0;
+	if (chip_is_ar8327(priv) || chip_is_ar8337(priv)) {
+		if (AUTONEG_ENABLE != phydev->autoneg)
+			return 0;
+		/*
+		 * BMCR_ANENABLE might have been cleared
+		 * by phy_init_hw in certain kernel versions
+		 * therefore check for it
+		 */
+		ret = phy_read(phydev, MII_BMCR);
+		if (ret < 0)
+			return ret;
+		if (ret & BMCR_ANENABLE)
+			return 0;
+
+		dev_info(&phydev->dev, "ANEG disabled, re-enabling ..\n");
+		ret |= BMCR_ANENABLE | BMCR_ANRESTART;
+		return phy_write(phydev, MII_BMCR, ret);
+	}
 
 	priv->phy = phydev;
 
@@ -3011,6 +3028,15 @@ ar8xxx_phy_remove(struct phy_device *phydev)
 	ar8xxx_free(priv);
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+static int
+ar8xxx_phy_soft_reset(struct phy_device *phydev)
+{
+	/* we don't need an extra reset */
+	return 0;
+}
+#endif
+
 static struct phy_driver ar8xxx_phy_driver = {
 	.phy_id		= 0x004d0000,
 	.name		= "Atheros AR8216/AR8236/AR8316",
@@ -3022,6 +3048,10 @@ static struct phy_driver ar8xxx_phy_driver = {
 	.config_init	= ar8xxx_phy_config_init,
 	.config_aneg	= ar8xxx_phy_config_aneg,
 	.read_status	= ar8xxx_phy_read_status,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+	.soft_reset     = ar8xxx_phy_soft_reset,
+#endif
+
 	.driver		= { .owner = THIS_MODULE },
 };
 
-- 
2.1.3
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list