net: phy: mxl-gpy: Remove interrupt mask clearing from config_init
[ Upstream commit c44d3ffd85db03ebcc3090e55589e10d5af9f3a9 ] 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: 7d901a1e878a ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
de4fc1091a
commit
123eaaf636
@ -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 gpy_probe(struct phy_device *phydev)
|
||||
@ -619,11 +621,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);
|
||||
}
|
||||
|
||||
@ -670,6 +684,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) {
|
||||
@ -717,6 +732,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,
|
||||
@ -724,6 +741,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) {
|
||||
@ -740,9 +764,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);
|
||||
}
|
||||
@ -750,18 +776,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…
x
Reference in New Issue
Block a user