Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: phy: micrel: fix KSZ9477 PHY issues after suspend/resume

When the PHY is powered up after powered down most of the registers are
reset, so the PHY setup code needs to be done again. In addition the
interrupt register will need to be setup again so that link status
indication works again.

Fixes: 26dd2974c5b5 ("net: phy: micrel: Move KSZ9477 errata fixes to PHY driver")
Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tristram Ha and committed by
David S. Miller
6149db49 33700a0c

+56 -6
+56 -6
drivers/net/phy/micrel.c
··· 1939 1939 {0x1c, 0x20, 0xeeee}, 1940 1940 }; 1941 1941 1942 - static int ksz9477_config_init(struct phy_device *phydev) 1942 + static int ksz9477_phy_errata(struct phy_device *phydev) 1943 1943 { 1944 1944 int err; 1945 1945 int i; ··· 1967 1967 return err; 1968 1968 } 1969 1969 1970 + err = genphy_restart_aneg(phydev); 1971 + if (err) 1972 + return err; 1973 + 1974 + return err; 1975 + } 1976 + 1977 + static int ksz9477_config_init(struct phy_device *phydev) 1978 + { 1979 + int err; 1980 + 1981 + /* Only KSZ9897 family of switches needs this fix. */ 1982 + if ((phydev->phy_id & 0xf) == 1) { 1983 + err = ksz9477_phy_errata(phydev); 1984 + if (err) 1985 + return err; 1986 + } 1987 + 1970 1988 /* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes 1971 1989 * in this switch shall be regarded as broken. 1972 1990 */ 1973 1991 if (phydev->dev_flags & MICREL_NO_EEE) 1974 1992 phydev->eee_broken_modes = -1; 1975 - 1976 - err = genphy_restart_aneg(phydev); 1977 - if (err) 1978 - return err; 1979 1993 1980 1994 return kszphy_config_init(phydev); 1981 1995 } ··· 2088 2074 ret = kszphy_config_reset(phydev); 2089 2075 if (ret) 2090 2076 return ret; 2077 + 2078 + /* Enable PHY Interrupts */ 2079 + if (phy_interrupt_is_valid(phydev)) { 2080 + phydev->interrupts = PHY_INTERRUPT_ENABLED; 2081 + if (phydev->drv->config_intr) 2082 + phydev->drv->config_intr(phydev); 2083 + } 2084 + 2085 + return 0; 2086 + } 2087 + 2088 + static int ksz9477_resume(struct phy_device *phydev) 2089 + { 2090 + int ret; 2091 + 2092 + /* No need to initialize registers if not powered down. */ 2093 + ret = phy_read(phydev, MII_BMCR); 2094 + if (ret < 0) 2095 + return ret; 2096 + if (!(ret & BMCR_PDOWN)) 2097 + return 0; 2098 + 2099 + genphy_resume(phydev); 2100 + 2101 + /* After switching from power-down to normal mode, an internal global 2102 + * reset is automatically generated. Wait a minimum of 1 ms before 2103 + * read/write access to the PHY registers. 2104 + */ 2105 + usleep_range(1000, 2000); 2106 + 2107 + /* Only KSZ9897 family of switches needs this fix. */ 2108 + if ((phydev->phy_id & 0xf) == 1) { 2109 + ret = ksz9477_phy_errata(phydev); 2110 + if (ret) 2111 + return ret; 2112 + } 2091 2113 2092 2114 /* Enable PHY Interrupts */ 2093 2115 if (phy_interrupt_is_valid(phydev)) { ··· 5543 5493 .config_intr = kszphy_config_intr, 5544 5494 .handle_interrupt = kszphy_handle_interrupt, 5545 5495 .suspend = genphy_suspend, 5546 - .resume = genphy_resume, 5496 + .resume = ksz9477_resume, 5547 5497 .get_features = ksz9477_get_features, 5548 5498 } }; 5549 5499