Commit c44d3ffd authored by Raju Lakkaraju's avatar Raju Lakkaraju Committed by Paolo Abeni

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: 7d901a1e ("net: phy: add Maxlinear GPY115/21x/24x driver")
Reviewed-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: default avatarRaju Lakkaraju <Raju.Lakkaraju@microchip.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8c248cd8
...@@ -107,6 +107,7 @@ struct gpy_priv { ...@@ -107,6 +107,7 @@ struct gpy_priv {
u8 fw_major; u8 fw_major;
u8 fw_minor; u8 fw_minor;
u32 wolopts;
/* It takes 3 seconds to fully switch out of loopback mode before /* It takes 3 seconds to fully switch out of loopback mode before
* it can safely re-enter loopback mode. Record the time when * it can safely re-enter loopback mode. Record the time when
...@@ -221,6 +222,15 @@ static int gpy_hwmon_register(struct phy_device *phydev) ...@@ -221,6 +222,15 @@ static int gpy_hwmon_register(struct phy_device *phydev)
} }
#endif #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) static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
{ {
struct gpy_priv *priv = phydev->priv; struct gpy_priv *priv = phydev->priv;
...@@ -262,16 +272,8 @@ static int gpy_mbox_read(struct phy_device *phydev, u32 addr) ...@@ -262,16 +272,8 @@ static int gpy_mbox_read(struct phy_device *phydev, u32 addr)
static int gpy_config_init(struct phy_device *phydev) static int gpy_config_init(struct phy_device *phydev)
{ {
int ret; /* Nothing to configure. Configuration Requirement Placeholder */
return 0;
/* 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;
} }
static int gpy21x_config_init(struct phy_device *phydev) static int gpy21x_config_init(struct phy_device *phydev)
...@@ -627,11 +629,23 @@ static int gpy_read_status(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) static int gpy_config_intr(struct phy_device *phydev)
{ {
struct gpy_priv *priv = phydev->priv;
u16 mask = 0; u16 mask = 0;
int ret;
ret = gpy_ack_interrupt(phydev);
if (ret)
return ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
mask = PHY_IMASK_MASK; 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); return phy_write(phydev, PHY_IMASK, mask);
} }
...@@ -678,6 +692,7 @@ static int gpy_set_wol(struct phy_device *phydev, ...@@ -678,6 +692,7 @@ static int gpy_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol) struct ethtool_wolinfo *wol)
{ {
struct net_device *attach_dev = phydev->attached_dev; struct net_device *attach_dev = phydev->attached_dev;
struct gpy_priv *priv = phydev->priv;
int ret; int ret;
if (wol->wolopts & WAKE_MAGIC) { if (wol->wolopts & WAKE_MAGIC) {
...@@ -725,6 +740,8 @@ static int gpy_set_wol(struct phy_device *phydev, ...@@ -725,6 +740,8 @@ static int gpy_set_wol(struct phy_device *phydev,
ret = phy_read(phydev, PHY_ISTAT); ret = phy_read(phydev, PHY_ISTAT);
if (ret < 0) if (ret < 0)
return ret; return ret;
priv->wolopts |= WAKE_MAGIC;
} else { } else {
/* Disable magic packet matching */ /* Disable magic packet matching */
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
...@@ -732,6 +749,13 @@ static int gpy_set_wol(struct phy_device *phydev, ...@@ -732,6 +749,13 @@ static int gpy_set_wol(struct phy_device *phydev,
WOL_EN); WOL_EN);
if (ret < 0) if (ret < 0)
return ret; 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) { if (wol->wolopts & WAKE_PHY) {
...@@ -748,9 +772,11 @@ static int gpy_set_wol(struct phy_device *phydev, ...@@ -748,9 +772,11 @@ static int gpy_set_wol(struct phy_device *phydev,
if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC)) if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC))
phy_trigger_machine(phydev); phy_trigger_machine(phydev);
priv->wolopts |= WAKE_PHY;
return 0; return 0;
} }
priv->wolopts &= ~WAKE_PHY;
/* Disable the link state change interrupt */ /* Disable the link state change interrupt */
return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC); return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
} }
...@@ -758,18 +784,10 @@ static int gpy_set_wol(struct phy_device *phydev, ...@@ -758,18 +784,10 @@ static int gpy_set_wol(struct phy_device *phydev,
static void gpy_get_wol(struct phy_device *phydev, static void gpy_get_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol) struct ethtool_wolinfo *wol)
{ {
int ret; struct gpy_priv *priv = phydev->priv;
wol->supported = WAKE_MAGIC | WAKE_PHY; wol->supported = WAKE_MAGIC | WAKE_PHY;
wol->wolopts = 0; wol->wolopts = priv->wolopts;
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;
} }
static int gpy_loopback(struct phy_device *phydev, bool enable) static int gpy_loopback(struct phy_device *phydev, bool enable)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment