net: phy: mxl-gpy: Remove interrupt mask clearing from config_init
When the system resumes from sleep, the phy_init_hw() function invokes
config_init(), which clears all interrupt masks and causes wake events to be
lost in subsequent wake sequences. Remove interrupt mask clearing from
config_init() and preserve relevant masks in config_intr().
Fixes: 7d901a1e87
("net: phy: add Maxlinear GPY115/21x/24x driver")
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
8c248cd836
commit
c44d3ffd85
@ -107,6 +107,7 @@ struct gpy_priv {
|
||||
|
||||
u8 fw_major;
|
||||
u8 fw_minor;
|
||||
u32 wolopts;
|
||||
|
||||
/* It takes 3 seconds to fully switch out of loopback mode before
|
||||
* it can safely re-enter loopback mode. Record the time when
|
||||
@ -221,6 +222,15 @@ static int gpy_hwmon_register(struct phy_device *phydev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int gpy_ack_interrupt(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Clear all pending interrupts */
|
||||
ret = phy_read(phydev, PHY_ISTAT);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
|
||||
{
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
@ -262,16 +272,8 @@ out:
|
||||
|
||||
static int gpy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Mask all interrupts */
|
||||
ret = phy_write(phydev, PHY_IMASK, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Clear all pending interrupts */
|
||||
ret = phy_read(phydev, PHY_ISTAT);
|
||||
return ret < 0 ? ret : 0;
|
||||
/* Nothing to configure. Configuration Requirement Placeholder */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpy21x_config_init(struct phy_device *phydev)
|
||||
@ -627,11 +629,23 @@ static int gpy_read_status(struct phy_device *phydev)
|
||||
|
||||
static int gpy_config_intr(struct phy_device *phydev)
|
||||
{
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
u16 mask = 0;
|
||||
int ret;
|
||||
|
||||
ret = gpy_ack_interrupt(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
|
||||
mask = PHY_IMASK_MASK;
|
||||
|
||||
if (priv->wolopts & WAKE_MAGIC)
|
||||
mask |= PHY_IMASK_WOL;
|
||||
|
||||
if (priv->wolopts & WAKE_PHY)
|
||||
mask |= PHY_IMASK_LSTC;
|
||||
|
||||
return phy_write(phydev, PHY_IMASK, mask);
|
||||
}
|
||||
|
||||
@ -678,6 +692,7 @@ static int gpy_set_wol(struct phy_device *phydev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct net_device *attach_dev = phydev->attached_dev;
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
int ret;
|
||||
|
||||
if (wol->wolopts & WAKE_MAGIC) {
|
||||
@ -725,6 +740,8 @@ static int gpy_set_wol(struct phy_device *phydev,
|
||||
ret = phy_read(phydev, PHY_ISTAT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->wolopts |= WAKE_MAGIC;
|
||||
} else {
|
||||
/* Disable magic packet matching */
|
||||
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
|
||||
@ -732,6 +749,13 @@ static int gpy_set_wol(struct phy_device *phydev,
|
||||
WOL_EN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Disable the WOL interrupt */
|
||||
ret = phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_WOL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->wolopts &= ~WAKE_MAGIC;
|
||||
}
|
||||
|
||||
if (wol->wolopts & WAKE_PHY) {
|
||||
@ -748,9 +772,11 @@ static int gpy_set_wol(struct phy_device *phydev,
|
||||
if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC))
|
||||
phy_trigger_machine(phydev);
|
||||
|
||||
priv->wolopts |= WAKE_PHY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv->wolopts &= ~WAKE_PHY;
|
||||
/* Disable the link state change interrupt */
|
||||
return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
|
||||
}
|
||||
@ -758,18 +784,10 @@ static int gpy_set_wol(struct phy_device *phydev,
|
||||
static void gpy_get_wol(struct phy_device *phydev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
int ret;
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
|
||||
wol->supported = WAKE_MAGIC | WAKE_PHY;
|
||||
wol->wolopts = 0;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, VPSPEC2_WOL_CTL);
|
||||
if (ret & WOL_EN)
|
||||
wol->wolopts |= WAKE_MAGIC;
|
||||
|
||||
ret = phy_read(phydev, PHY_IMASK);
|
||||
if (ret & PHY_IMASK_LSTC)
|
||||
wol->wolopts |= WAKE_PHY;
|
||||
wol->wolopts = priv->wolopts;
|
||||
}
|
||||
|
||||
static int gpy_loopback(struct phy_device *phydev, bool enable)
|
||||
|
Loading…
Reference in New Issue
Block a user