diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-11-24 09:33:48 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-11-24 09:33:48 +0000 |
commit | 35902404fce9e8007a69ba893a8a8e569494209e (patch) | |
tree | f01710e69239b903b2045c578856973867e36f77 /target/linux/generic/files/drivers | |
parent | a2768bd9e0efb430e864fe5faf5070ea724e2797 (diff) | |
download | upstream-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/linux/generic/files/drivers')
-rw-r--r-- | target/linux/generic/files/drivers/net/phy/ar8216.c | 49 |
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 }, }; |