aboutsummaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2014-11-24 09:33:48 +0000
committerFelix Fietkau <nbd@openwrt.org>2014-11-24 09:33:48 +0000
commit35902404fce9e8007a69ba893a8a8e569494209e (patch)
treef01710e69239b903b2045c578856973867e36f77 /target
parenta2768bd9e0efb430e864fe5faf5070ea724e2797 (diff)
downloadupstream-35902404fce9e8007a69ba893a8a8e569494209e.tar.gz
upstream-35902404fce9e8007a69ba893a8a8e569494209e.tar.bz2
upstream-35902404fce9e8007a69ba893a8a8e569494209e.zip
ar8216: Fix issue with autoneg being disabled under 3.14, revert 43332
Patch reverts 43332 which seems to cause issues with VLAN functionality. Add a specific check to check whether ANEG is still enabled and re-enable it if necessary. Disable generic phy soft reset for kernel >=3.16. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> SVN-Revision: 43356
Diffstat (limited to 'target')
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.c49
1 files changed, 47 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 1d58f3a5d7..5e93a1f75d 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"
@@ -342,6 +343,29 @@ ar8xxx_phy_poll_reset(struct mii_bus *bus)
return -ETIMEDOUT;
}
+static int
+ar8xxx_phy_check_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ if (phydev->autoneg != AUTONEG_ENABLE)
+ 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);
+}
+
static void
ar8xxx_phy_init(struct ar8xxx_priv *priv)
{
@@ -2774,7 +2798,7 @@ ar8xxx_phy_config_init(struct phy_device *phydev)
return -ENODEV;
if (chip_is_ar8327(priv) || chip_is_ar8337(priv))
- return 0;
+ return ar8xxx_phy_check_aneg(phydev);
priv->phy = phydev;
@@ -2848,6 +2872,15 @@ ar8xxx_phy_read_status(struct phy_device *phydev)
return ret;
}
+static int
+ar8xxx_phy_config_aneg(struct phy_device *phydev)
+{
+ if (phydev->addr == 0)
+ return 0;
+
+ return genphy_config_aneg(phydev);
+}
+
static const u32 ar8xxx_phy_ids[] = {
0x004dd033,
0x004dd034, /* AR8327 */
@@ -3010,6 +3043,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",
@@ -3019,8 +3061,11 @@ static struct phy_driver ar8xxx_phy_driver = {
.remove = ar8xxx_phy_remove,
.detach = ar8xxx_phy_detach,
.config_init = ar8xxx_phy_config_init,
- .config_aneg = genphy_config_aneg,
+ .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 },
};