]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
net: phy: mxl-gpy: Remove interrupt mask clearing from config_init
authorRaju Lakkaraju <Raju.Lakkaraju@microchip.com>
Fri, 14 Jun 2024 17:11:57 +0000 (22:41 +0530)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 18 Jun 2024 10:04:23 +0000 (12:04 +0200)
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>
drivers/net/phy/mxl-gpy.c

index b2d36a3a96f1e9d98e50ab2f219946c2b2d85731..e5f8ac4b4604bdbaa7149fbb72e89a26cca015cd 100644 (file)
@@ -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)