]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: bcmasp: Add support for PHY-based Wake-on-LAN
authorFlorian Fainelli <florian.fainelli@broadcom.com>
Mon, 13 Oct 2025 17:23:06 +0000 (10:23 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 16 Oct 2025 00:45:52 +0000 (17:45 -0700)
If available, interrogate the PHY to find out whether we can use it for
Wake-on-LAN. This can be a more power efficient way of implementing that
feature, especially when the MAC is powered off in low power states.

Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20251013172306.2250223-1-florian.fainelli@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c

index 63f1a8c3a7fbe347bb64bf31540a5e3b74eee55c..dd80ccfca19d564596338a0ec2e471915ec72d35 100644 (file)
@@ -163,11 +163,30 @@ static void bcmasp_set_msglevel(struct net_device *dev, u32 level)
 static void bcmasp_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct bcmasp_intf *intf = netdev_priv(dev);
+       struct bcmasp_priv *priv = intf->parent;
+       struct device *kdev = &priv->pdev->dev;
+       u32 phy_wolopts = 0;
+
+       if (dev->phydev) {
+               phy_ethtool_get_wol(dev->phydev, wol);
+               phy_wolopts = wol->wolopts;
+       }
+
+       /* MAC is not wake-up capable, return what the PHY does */
+       if (!device_can_wakeup(kdev))
+               return;
+
+       /* Overlay MAC capabilities with that of the PHY queried before */
+       wol->supported |= BCMASP_SUPPORTED_WAKE;
+       wol->wolopts |= intf->wolopts;
+
+       /* Return the PHY configured magic password */
+       if (phy_wolopts & WAKE_MAGICSECURE)
+               return;
 
-       wol->supported = BCMASP_SUPPORTED_WAKE;
-       wol->wolopts = intf->wolopts;
        memset(wol->sopass, 0, sizeof(wol->sopass));
 
+       /* Otherwise the MAC one */
        if (wol->wolopts & WAKE_MAGICSECURE)
                memcpy(wol->sopass, intf->sopass, sizeof(intf->sopass));
 }
@@ -177,10 +196,21 @@ static int bcmasp_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        struct bcmasp_intf *intf = netdev_priv(dev);
        struct bcmasp_priv *priv = intf->parent;
        struct device *kdev = &priv->pdev->dev;
+       int ret = 0;
+
+       /* Try Wake-on-LAN from the PHY first */
+       if (dev->phydev) {
+               ret = phy_ethtool_set_wol(dev->phydev, wol);
+               if (ret != -EOPNOTSUPP && wol->wolopts)
+                       return ret;
+       }
 
        if (!device_can_wakeup(kdev))
                return -EOPNOTSUPP;
 
+       if (wol->wolopts & ~BCMASP_SUPPORTED_WAKE)
+               return -EINVAL;
+
        /* Interface Specific */
        intf->wolopts = wol->wolopts;
        if (intf->wolopts & WAKE_MAGICSECURE)