[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