From patchwork Mon May 8 18:43:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Fainelli X-Patchwork-Id: 13234813 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3592F11188 for ; Mon, 8 May 2023 18:43:39 +0000 (UTC) Received: from mail-qk1-x72e.google.com (mail-qk1-x72e.google.com [IPv6:2607:f8b0:4864:20::72e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3249759E9; Mon, 8 May 2023 11:43:37 -0700 (PDT) Received: by mail-qk1-x72e.google.com with SMTP id af79cd13be357-7577e7a83a2so73145385a.3; Mon, 08 May 2023 11:43:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683571416; x=1686163416; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HSI1cyMftkfD9gEVAn4dh2LDnuC+DWvnH++idemGV1s=; b=NZlGUytzCI1frZrMMQooFV51EpEkQ64RmUZKdOiBdLTSLWQl3GEkKuIJ305bxA9mQ+ H9UwCjZ5b45pYna2/sb66BEiO40vR/4p+QAL349e+j7Ure6hZ22N5J9GL9Y1xXFW2JIh 76aWwtOQnkcgkxIWepFtNtpIcB+Ve95RRbuMB8NasMqIqMO0cmEf0LnIwHQfkoabqOhV S+8zCh70NVEzn8eKY2yI3dTR/jcnsBHjBGJkJ4mfjqV0YhIaVqzteKjh1IOF650i0UZ9 JO+e0uRblIl47vnx6XE6u7JdQsPJfObxuXu0wAjEw6lHWoVp8HXpSkLUq6y94X6zyPtR BonA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683571416; x=1686163416; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HSI1cyMftkfD9gEVAn4dh2LDnuC+DWvnH++idemGV1s=; b=F8TK+s33aaIUaTvQ2Xa2f2ACONfxaBAAwaT/3sbDjEepdm0Jc9yX1xcHUQ+P7lZKMz szuvTjoI41d/x4r71Yek77JrZCm6lmt+4UXS9Fxyl4fgWVmLaAMSsA3zcSDdewgXwDfB Q7kGabiENoQxOZdZf+Q5z/2FrDtHe9OkMJVXAQg/bLfK0qnOZVNPClXvh8W6XVUUOZsj TqAWmZitzgsdK1h+mq1ifhhj3P+T1VWleDkesOszgNpahDdsQj9ahFIMJjPkBqP1i6qY r693JJbKVeLoAzKWl8qFSvKxzzEcP+EPVNitzqeQ4nytAaT6rfQnyQ0ZeoU6DLONMuJv 3HPg== X-Gm-Message-State: AC+VfDzEl/ZDup8ZHY4rEGLwNNxqPPkdxRXZDODw0rxmQSj9Md5BRDks ZRZKMv1TB/YcEh9ZFaTBLjMFt38pad0= X-Google-Smtp-Source: ACHHUZ5By6VubEzc3EoHUZdPyyeBEgAoCXBKR2ckrESzZSi5o0AH8SM+nRe3le9cNjDE1v+CC0NxUw== X-Received: by 2002:a05:622a:14cc:b0:3ef:336f:56c6 with SMTP id u12-20020a05622a14cc00b003ef336f56c6mr18611137qtx.17.1683571415729; Mon, 08 May 2023 11:43:35 -0700 (PDT) Received: from fainelli-desktop.igp.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id v26-20020ac83d9a000000b003d3a34d2eb2sm3193988qtf.41.2023.05.08.11.43.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 May 2023 11:43:34 -0700 (PDT) From: Florian Fainelli To: netdev@vger.kernel.org Cc: Florian Fainelli , Doug Berger , Broadcom internal kernel review list , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Russell King , =?utf-8?q?Marek_Beh=C3=BAn?= , Peter Geis , Frank , linux-kernel@vger.kernel.org (open list) Subject: [PATCH net-next 1/3] net: phy: Let drivers check Wake-on-LAN status Date: Mon, 8 May 2023 11:43:07 -0700 Message-Id: <20230508184309.1628108-2-f.fainelli@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230508184309.1628108-1-f.fainelli@gmail.com> References: <20230508184309.1628108-1-f.fainelli@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org A few PHY drivers are currently attempting to not suspend the PHY when Wake-on-LAN is enabled, however that code is not currently executing at all due to an early check in phy_suspend(). This prevents PHY drivers from making an appropriate decisions and put the hardware into a low power state if desired. In order to allow the PHY framework to always call into the PHY driver's ->suspend routine whether Wake-on-LAN is enabled or not, provide a phydev::wol_enabled boolean that tracks whether the PHY or the attached MAC has Wake-on-LAN enabled. If phydev::wol_enabled then the PHY shall not prevent its own Wake-on-LAN detection logic from working and shall not prevent the Ethernet MAC from receiving packets for matching. The check for -EBUSY is also removed since it would have prevented a PHY being in an always on power domain and thus retaining its Wake-on-LAN configuration from allowing the system to suspend. Signed-off-by: Florian Fainelli --- drivers/net/phy/aquantia_main.c | 3 +++ drivers/net/phy/at803x.c | 10 ++++++++++ drivers/net/phy/bcm7xxx.c | 3 +++ drivers/net/phy/broadcom.c | 6 ++++++ drivers/net/phy/dp83822.c | 2 +- drivers/net/phy/dp83867.c | 3 +++ drivers/net/phy/dp83tc811.c | 2 +- drivers/net/phy/marvell-88x2222.c | 3 +++ drivers/net/phy/marvell.c | 3 +++ drivers/net/phy/marvell10g.c | 3 +++ drivers/net/phy/micrel.c | 3 +++ drivers/net/phy/microchip.c | 4 +--- drivers/net/phy/motorcomm.c | 2 +- drivers/net/phy/phy-c45.c | 3 +++ drivers/net/phy/phy_device.c | 7 +++++-- drivers/net/phy/realtek.c | 3 +++ include/linux/phy.h | 3 +++ 17 files changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c index 334a6904ca5a..ffe4e8f16c07 100644 --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c @@ -691,6 +691,9 @@ static int aqr107_suspend(struct phy_device *phydev) { int err; + if (phydev->wol_enabled) + return 0; + err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MDIO_CTRL1, MDIO_CTRL1_LPOWER); if (err) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 656136628ffd..acd941beeb8e 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -569,6 +569,13 @@ static int at803x_suspend(struct phy_device *phydev) int value; int wol_enabled; + /* We cannot isolate if the attached network device has + * Wake-on-LAN enabled since we would not be passing + * packets through it. + */ + if (phydev->attached_dev->wol_enabled) + return 0; + value = phy_read(phydev, AT803X_INTR_ENABLE); wol_enabled = value & AT803X_INTR_ENABLE_WOL; @@ -1701,6 +1708,9 @@ static int qca83xx_suspend(struct phy_device *phydev) { u16 mask = 0; + if (phydev->wol_enabled) + return 0; + /* Only QCA8337 support actual suspend. * QCA8327 cause port unreliability when phy suspend * is set. diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 06be71ecd2f8..f060a5783694 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -747,6 +747,9 @@ static int bcm7xxx_suspend(struct phy_device *phydev) }; unsigned int i; + if (phydev->wol_enabled) + return 0; + for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) { ret = phy_write(phydev, bcm7xxx_suspend_cfg[i].reg, diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index ad71c88c87e7..3f142dc266a9 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -443,6 +443,9 @@ static int bcm54xx_suspend(struct phy_device *phydev) bcm54xx_ptp_stop(phydev); + if (phydev->wol_enabled) + return 0; + /* We cannot use a read/modify/write here otherwise the PHY gets into * a bad state where its LEDs keep flashing, thus defeating the purpose * of low power mode. @@ -770,6 +773,9 @@ static int brcm_fet_suspend(struct phy_device *phydev) { int reg, err, err2, brcmtest; + if (phydev->wol_enabled) + return 0; + /* We cannot use a read/modify/write here otherwise the PHY continues * to drive LEDs which defeats the purpose of low power mode. */ diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c index b7cb71817780..2ab0cbd1a60f 100644 --- a/drivers/net/phy/dp83822.c +++ b/drivers/net/phy/dp83822.c @@ -573,7 +573,7 @@ static int dp83822_suspend(struct phy_device *phydev) value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); - if (!(value & DP83822_WOL_EN)) + if (!(value & DP83822_WOL_EN) && !phydev->wol_enabled) genphy_suspend(phydev); return 0; diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index d75f526a20a4..8f2b19e57f90 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -708,6 +708,9 @@ static int dp83867_suspend(struct phy_device *phydev) dp83867_config_intr(phydev); } + if (phydev->wol_enabled) + return 0; + return genphy_suspend(phydev); } diff --git a/drivers/net/phy/dp83tc811.c b/drivers/net/phy/dp83tc811.c index 7ea32fb77190..2106f9ea15f5 100644 --- a/drivers/net/phy/dp83tc811.c +++ b/drivers/net/phy/dp83tc811.c @@ -368,7 +368,7 @@ static int dp83811_suspend(struct phy_device *phydev) value = phy_read_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG); - if (!(value & DP83811_WOL_EN)) + if (!(value & DP83811_WOL_EN) && !phydev->wol_enabled) genphy_suspend(phydev); return 0; diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c index f83cae64585d..9c13e4dd1807 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -458,6 +458,9 @@ static int mv2222_resume(struct phy_device *phydev) static int mv2222_suspend(struct phy_device *phydev) { + /* No need to check for phydev->wol_enabled since we only disable the + * transmitter + */ return mv2222_tx_disable(phydev); } diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 43b6cb725551..c08ad1c3f4c3 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1741,6 +1741,9 @@ static int marvell_suspend(struct phy_device *phydev) { int err; + if (phydev->wol_enabled) + return 0; + /* Suspend the fiber mode first */ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) { diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 55d9d7acc32e..6d45a94e5bea 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -559,6 +559,9 @@ static void mv3310_remove(struct phy_device *phydev) static int mv3310_suspend(struct phy_device *phydev) { + if (phydev->wol_enabled) + return 0; + return mv3310_power_down(phydev); } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3f81bb8dac44..fe71ab8926fc 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1826,6 +1826,9 @@ static int kszphy_suspend(struct phy_device *phydev) phydev->drv->config_intr(phydev); } + if (phydev->wol_enabled) + return 0; + return genphy_suspend(phydev); } diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c index 0b88635f4fbc..5290fd684c93 100644 --- a/drivers/net/phy/microchip.c +++ b/drivers/net/phy/microchip.c @@ -74,10 +74,8 @@ static irqreturn_t lan88xx_handle_interrupt(struct phy_device *phydev) static int lan88xx_suspend(struct phy_device *phydev) { - struct lan88xx_priv *priv = phydev->priv; - /* do not power down PHY when WOL is enabled */ - if (!priv->wolopts) + if (!phydev->wol_enabled) genphy_suspend(phydev); return 0; diff --git a/drivers/net/phy/motorcomm.c b/drivers/net/phy/motorcomm.c index 2fa5a90e073b..50472708c15e 100644 --- a/drivers/net/phy/motorcomm.c +++ b/drivers/net/phy/motorcomm.c @@ -1414,7 +1414,7 @@ static int yt8521_suspend(struct phy_device *phydev) return wol_config; /* if wol enable, do nothing */ - if (wol_config & YTPHY_WCR_ENABLE) + if ((wol_config & YTPHY_WCR_ENABLE) || phydev->wol_enabled) return 0; return yt8521_modify_utp_fiber_bmcr(phydev, 0, BMCR_PDOWN); diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index fee514b96ab1..355e78c441a8 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -64,6 +64,9 @@ EXPORT_SYMBOL_GPL(genphy_c45_pma_resume); */ int genphy_c45_pma_suspend(struct phy_device *phydev) { + if (phydev->wol_enabled) + return 0; + if (!genphy_c45_pma_can_sleep(phydev)) return -EOPNOTSUPP; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 17d0d0555a79..ae86e169a578 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1862,8 +1862,8 @@ int phy_suspend(struct phy_device *phydev) /* If the device has WOL enabled, we cannot suspend the PHY */ phy_ethtool_get_wol(phydev, &wol); - if (wol.wolopts || (netdev && netdev->wol_enabled)) - return -EBUSY; + phydev->wol_enabled = !!(wol.wolopts || (netdev && + netdev->wol_enabled)); if (!phydrv || !phydrv->suspend) return 0; @@ -2687,6 +2687,9 @@ EXPORT_SYMBOL(genphy_write_mmd_unsupported); int genphy_suspend(struct phy_device *phydev) { + if (phydev->wol_enabled) + return 0; + return phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN); } EXPORT_SYMBOL(genphy_suspend); diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 3d99fd6664d7..316f9e868d84 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -482,6 +482,9 @@ static int rtl8211e_config_init(struct phy_device *phydev) static int rtl8211b_suspend(struct phy_device *phydev) { + if (phydev->wol_enabled) + return 0; + phy_write(phydev, MII_MMD_DATA, BIT(9)); return genphy_suspend(phydev); diff --git a/include/linux/phy.h b/include/linux/phy.h index c5a0dc829714..e36dfc8236b4 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -548,6 +548,8 @@ struct macsec_ops; * @downshifted_rate: Set true if link speed has been downshifted. * @is_on_sfp_module: Set true if PHY is located on an SFP module. * @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY + * @wol_enabled: Set to true if the PHY or the attached MAC have Wake-on-LAN + * enabled. * @state: State of the PHY for management purposes * @dev_flags: Device-specific flags used by the PHY driver. * @@ -644,6 +646,7 @@ struct phy_device { unsigned downshifted_rate:1; unsigned is_on_sfp_module:1; unsigned mac_managed_pm:1; + unsigned wol_enabled:1; unsigned autoneg:1; /* The most recently read link state */ From patchwork Mon May 8 18:43:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Fainelli X-Patchwork-Id: 13234814 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 859DD11188 for ; Mon, 8 May 2023 18:43:42 +0000 (UTC) Received: from mail-qk1-x72e.google.com (mail-qk1-x72e.google.com [IPv6:2607:f8b0:4864:20::72e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4DB659E8; Mon, 8 May 2023 11:43:39 -0700 (PDT) Received: by mail-qk1-x72e.google.com with SMTP id af79cd13be357-7575ff76964so116135485a.2; Mon, 08 May 2023 11:43:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683571418; x=1686163418; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NMLTaac8rhvSbe/caPsDcy8khu+PZxjEUlyzscx2eKA=; b=DrVLIab/7J/kQZTEhB0cpR5ABkpqIcnpGqLZAImu5UV5AFs/XOJfcKEvL50M8Y6+Js RXg1xHNjb6N/M7QFsZgcHFJlGFKPWYV76hq4r+xmMI71bvNGXUN74JUefYjiIshVPAZu udlefvkj0b9h+HOx8S9tz4QlqJhSZz1aYgDqLdzYwuz+Mqdpm5rSuDsR2fdB4ooXCSOj pkG0+sGkEBfXlPP+9TeN5Kn/33oZ9/jVkEWpfB7ufDw0Vri9yPi4/Ji3RKiYSWagl8uL ok13PANuWy2iSMLLelrqviSULV67IDwrtsly0kWwmGU3xaOu1D2OsYkqie2CRWkhRY3X f4vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683571418; x=1686163418; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NMLTaac8rhvSbe/caPsDcy8khu+PZxjEUlyzscx2eKA=; b=Uxz+UN68anLw0HDTutXhHkLQ4tpZSRKQlrBXT9Zy8VT7dWTjNjTvW9R6gSBJ4gsMaI j3niworNaE44Oe0Ohv1npF/T7KjAmlYYs9lT8fMETAVm1okZkTmYUlGJSWq4GxaKjs09 Z6cJ5ACEOeEtDi6OC7OgFF5IGITIwq5ufvzklg4i3VGGLX6fxGu0oWfKIwfc6SDsj6Vs LOkeosDJVJjAI2gpvY+eqaRqDSKTmt91s0YMqPQotzv3zYezdFJsldbLj0m1zHRjp1eO X7aAOlc2a11jbQr1BTsNKBadYWSx+5/u3ldSmhRn/ruipdg+O1xSW2BuTV5lZDm7iJrh PXYQ== X-Gm-Message-State: AC+VfDyHOXXyc2N+644x7peUJ0RoadmI4z12WAoBW6vEq2nGPYw5YLhK jEjne6hb4j7C9wxTNRTPJOi8UXsSvhU= X-Google-Smtp-Source: ACHHUZ7Z2b4Oo4Lmmx+DSACF7wASYvMSlycMNruoSKf1WSu1DDkuSQ+MC1flEToLEuDdgI5nbWkhig== X-Received: by 2002:a05:622a:13c8:b0:3ef:4007:485a with SMTP id p8-20020a05622a13c800b003ef4007485amr16533078qtk.68.1683571418182; Mon, 08 May 2023 11:43:38 -0700 (PDT) Received: from fainelli-desktop.igp.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id v26-20020ac83d9a000000b003d3a34d2eb2sm3193988qtf.41.2023.05.08.11.43.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 May 2023 11:43:37 -0700 (PDT) From: Florian Fainelli To: netdev@vger.kernel.org Cc: Florian Fainelli , Doug Berger , Broadcom internal kernel review list , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Russell King , =?utf-8?q?Marek_Beh=C3=BAn?= , Peter Geis , Frank , linux-kernel@vger.kernel.org (open list) Subject: [PATCH net-next 2/3] net: phy: broadcom: Add support for Wake-on-LAN Date: Mon, 8 May 2023 11:43:08 -0700 Message-Id: <20230508184309.1628108-3-f.fainelli@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230508184309.1628108-1-f.fainelli@gmail.com> References: <20230508184309.1628108-1-f.fainelli@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org Add support for WAKE_UCAST, WAKE_MCAST, WAKE_BCAST, WAKE_MAGIC and WAKE_MAGICSECURE. This is only supported with the BCM54210E and compatible Ethernet PHYs. Using the in-band interrupt or an out of band GPIO interrupts are supported. Broadcom PHYs will generate a Wake-on-LAN level low interrupt on LED4 as soon as one of the supported patterns is being matched. That includes generating such an interrupt even if the PHY is operated during normal modes. If WAKE_UCAST is selected, this could lead to the LED4 interrupt firing up for every packet being received which is absolutely undesirable from a performance point of view. Because the Wake-on-LAN configuration can be set long before the system is actually put to sleep, we cannot have an interrupt service routine to clear on read the interrupt status register and ensure that new packet matches will be detected. It is desirable to enable the Wake-on-LAN interrupt as late as possible during the system suspend process such that we limit the number of interrupts to be handled by the system, but also conversely feed into the Linux's system suspend way of dealing with interrupts in and around the points of no return. Signed-off-by: Florian Fainelli --- drivers/net/phy/bcm-phy-lib.c | 212 ++++++++++++++++++++++++++++++++++ drivers/net/phy/bcm-phy-lib.h | 5 + drivers/net/phy/broadcom.c | 124 +++++++++++++++++++- include/linux/brcmphy.h | 55 +++++++++ 4 files changed, 392 insertions(+), 4 deletions(-) diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index b2c0baa51f39..27c57f6ab211 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -6,12 +6,14 @@ #include "bcm-phy-lib.h" #include #include +#include #include #include #include #include #include #include +#include #define MII_BCM_CHANNEL_WIDTH 0x2000 #define BCM_CL45VEN_EEE_ADV 0x3c @@ -816,6 +818,216 @@ int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev, } EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb); +#define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \ + WAKE_MCAST | \ + WAKE_BCAST | \ + WAKE_MAGIC | \ + WAKE_MAGICSECURE) + +int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) +{ + struct net_device *ndev = phydev->attached_dev; + u8 da[ETH_ALEN], mask[ETH_ALEN]; + unsigned int i; + u16 ctl; + int ret; + + /* Allow a MAC driver to play through its own Wake-on-LAN + * implementation + */ + if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK) + return -EOPNOTSUPP; + + /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's + * ethtool only supports 6, for now. + */ + BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN); + + /* Clear previous interrupts */ + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (ret < 0) + return ret; + + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); + if (ret < 0) + return ret; + + ctl = ret; + + if (!wol->wolopts) { + if (phy_interrupt_is_valid(phydev)) + disable_irq_wake(phydev->irq); + + /* Leave all interrupts disabled */ + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, + BCM54XX_WOL_ALL_INTRS); + if (ret < 0) + return ret; + + /* Disable the global Wake-on-LAN enable bit */ + ctl &= ~BCM54XX_WOL_EN; + + return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); + } + + /* Clear the previously configured mode and mask mode for Wake-on-LAN */ + ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT); + ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT); + ctl &= ~BCM54XX_WOL_DIR_PKT_EN; + ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT); + + /* When using WAKE_MAGIC, we program the magic pattern filter to match + * the device's MAC address and we accept any MAC DA in the Ethernet + * frame. + * + * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the + * following: + * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match + * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care + * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match + * + * Note that the Broadcast MAC DA is inherently going to match the + * multicast pattern being matched. + */ + memset(mask, 0, sizeof(mask)); + + if (wol->wolopts & WAKE_MCAST) { + memset(da, 0, sizeof(da)); + memset(mask, 0xff, sizeof(mask)); + da[0] = 0x01; + mask[0] = ~da[0]; + } else { + if (wol->wolopts & WAKE_UCAST) { + ether_addr_copy(da, ndev->dev_addr); + } else if (wol->wolopts & WAKE_BCAST) { + eth_broadcast_addr(da); + } else if (wol->wolopts & WAKE_MAGICSECURE) { + ether_addr_copy(da, wol->sopass); + } else if (wol->wolopts & WAKE_MAGIC) { + memset(da, 0, sizeof(da)); + memset(mask, 0xff, sizeof(mask)); + } + } + + for (i = 0; i < ETH_ALEN / 2; i++) { + if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { + ret = bcm_phy_write_exp(phydev, + BCM54XX_WOL_MPD_DATA1(2 - i), + ndev->dev_addr[i * 2] << 8 | + ndev->dev_addr[i * 2 + 1]); + if (ret < 0) + return ret; + } + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i), + da[i * 2] << 8 | da[i * 2 + 1]); + if (ret < 0) + return ret; + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i), + mask[i * 2] << 8 | mask[i * 2 + 1]); + if (ret) + return ret; + } + + if (wol->wolopts & WAKE_MAGICSECURE) { + ctl |= BCM54XX_WOL_SECKEY_OPT_6B << + BCM54XX_WOL_SECKEY_OPT_SHIFT; + ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT; + ctl |= BCM54XX_WOL_MASK_MODE_DA_FF << + BCM54XX_WOL_MASK_MODE_SHIFT; + } else { + if (wol->wolopts & WAKE_MAGIC) + ctl |= BCM54XX_WOL_MODE_SINGLE_MPD; + else + ctl |= BCM54XX_WOL_DIR_PKT_EN; + ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY << + BCM54XX_WOL_MASK_MODE_SHIFT; + } + + /* Globally enable Wake-on-LAN */ + ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK; + + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); + if (ret < 0) + return ret; + + /* Enable WOL interrupt on LED4 */ + ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL); + if (ret < 0) + return ret; + + ret |= BCM54XX_LED4_SEL_INTR; + ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret); + if (ret < 0) + return ret; + + /* Enable all Wake-on-LAN interrupt sources */ + ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0); + if (ret < 0) + return ret; + + if (phy_interrupt_is_valid(phydev)) + enable_irq_wake(phydev->irq); + + return 0; +} +EXPORT_SYMBOL_GPL(bcm_phy_set_wol); + +void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) +{ + struct net_device *ndev = phydev->attached_dev; + u8 da[ETH_ALEN]; + unsigned int i; + int ret; + u16 ctl; + + wol->supported = BCM54XX_WOL_SUPPORTED_MASK; + wol->wolopts = 0; + + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); + if (ret < 0) + return; + + ctl = ret; + + if (!(ctl & BCM54XX_WOL_EN)) + return; + + for (i = 0; i < sizeof(da) / 2; i++) { + ret = bcm_phy_read_exp(phydev, + BCM54XX_WOL_MPD_DATA2(2 - i)); + if (ret < 0) + return; + + da[i * 2] = ret >> 8; + da[i * 2 + 1] = ret & 0xff; + } + + if (ctl & BCM54XX_WOL_DIR_PKT_EN) { + if (is_broadcast_ether_addr(da)) + wol->wolopts |= WAKE_BCAST; + else if (is_multicast_ether_addr(da)) + wol->wolopts |= WAKE_MCAST; + else if (ether_addr_equal(da, ndev->dev_addr)) + wol->wolopts |= WAKE_UCAST; + } else { + ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK; + switch (ctl) { + case BCM54XX_WOL_MODE_SINGLE_MPD: + wol->wolopts |= WAKE_MAGIC; + break; + case BCM54XX_WOL_MODE_SINGLE_MPDSEC: + wol->wolopts |= WAKE_MAGICSECURE; + memcpy(wol->sopass, da, sizeof(da)); + break; + default: + break; + } + } +} +EXPORT_SYMBOL_GPL(bcm_phy_get_wol); + MODULE_DESCRIPTION("Broadcom PHY Library"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index 9902fb182099..4337e4a5cade 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -9,6 +9,8 @@ #include #include +struct ethtool_wolinfo; + /* 28nm only register definitions */ #define MISC_ADDR(base, channel) base, channel @@ -106,4 +108,7 @@ static inline void bcm_ptp_stop(struct bcm_ptp_private *priv) } #endif +int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); +void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); + #endif /* _LINUX_BCM_PHY_LIB_H */ diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 3f142dc266a9..a9dfa230495b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -14,8 +14,12 @@ #include #include #include +#include #include #include +#include +#include +#include #define BRCM_PHY_MODEL(phydev) \ ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) @@ -30,8 +34,17 @@ MODULE_LICENSE("GPL"); struct bcm54xx_phy_priv { u64 *stats; struct bcm_ptp_private *ptp; + int wake_irq; + bool wake_irq_enabled; }; +static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev) +{ + struct bcm54xx_phy_priv *priv = phydev->priv; + + return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0; +} + static int bcm54xx_config_clock_delay(struct phy_device *phydev) { int rc, val; @@ -413,6 +426,16 @@ static int bcm54xx_config_init(struct phy_device *phydev) bcm54xx_ptp_config_init(phydev); + /* Acknowledge any left over interrupt and charge the device for + * wake-up. + */ + err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (err < 0) + return err; + + if (err) + pm_wakeup_event(&phydev->mdio.dev, 0); + return 0; } @@ -437,14 +460,38 @@ static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable) return ret; } -static int bcm54xx_suspend(struct phy_device *phydev) +static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state) { + struct bcm54xx_phy_priv *priv = phydev->priv; int ret; + if (!bcm54xx_phy_can_wakeup(phydev)) + return 0; + + if (priv->wake_irq_enabled != state) { + if (state) + ret = enable_irq_wake(priv->wake_irq); + else + ret = disable_irq_wake(priv->wake_irq); + priv->wake_irq_enabled = state; + } + + return ret; +} + +static int bcm54xx_suspend(struct phy_device *phydev) +{ + int ret = 0; + bcm54xx_ptp_stop(phydev); + /* Acknowledge any Wake-on-LAN interrupt prior to suspend */ + ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); + if (ret < 0) + return ret; + if (phydev->wol_enabled) - return 0; + return bcm54xx_set_wakeup_irq(phydev, true); /* We cannot use a read/modify/write here otherwise the PHY gets into * a bad state where its LEDs keep flashing, thus defeating the purpose @@ -459,7 +506,13 @@ static int bcm54xx_suspend(struct phy_device *phydev) static int bcm54xx_resume(struct phy_device *phydev) { - int ret; + int ret = 0; + + if (phydev->wol_enabled) { + ret = bcm54xx_set_wakeup_irq(phydev, false); + if (ret) + return ret; + } ret = bcm54xx_iddq_set(phydev, false); if (ret < 0) @@ -807,14 +860,54 @@ static int brcm_fet_suspend(struct phy_device *phydev) return err; } +static void bcm54xx_phy_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + /* We cannot wake-up if we do not have a dedicated PHY interrupt line + * or an out of band GPIO descriptor for wake-up. Zeroing + * wol->supported allows the caller (MAC driver) to play through and + * offer its own Wake-on-LAN scheme if available. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) { + wol->supported = 0; + return; + } + + bcm_phy_get_wol(phydev, wol); +} + +static int bcm54xx_phy_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + int ret; + + /* We cannot wake-up if we do not have a dedicated PHY interrupt line + * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP + * allows the caller (MAC driver) to play through and offer its own + * Wake-on-LAN scheme if available. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) + return -EOPNOTSUPP; + + ret = bcm_phy_set_wol(phydev, wol); + if (ret < 0) + return ret; + + return 0; +} + static int bcm54xx_phy_probe(struct phy_device *phydev) { struct bcm54xx_phy_priv *priv; + struct gpio_desc *wakeup_gpio; + int ret = 0; priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->wake_irq = -ENXIO; + phydev->priv = priv; priv->stats = devm_kcalloc(&phydev->mdio.dev, @@ -827,7 +920,28 @@ static int bcm54xx_phy_probe(struct phy_device *phydev) if (IS_ERR(priv->ptp)) return PTR_ERR(priv->ptp); - return 0; + /* We cannot utilize the _optional variant here since we want to know + * whether the GPIO descriptor exists or not to advertise Wake-on-LAN + * support or not. + */ + wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN); + if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER) + return PTR_ERR(wakeup_gpio); + + if (!IS_ERR(wakeup_gpio)) { + priv->wake_irq = gpiod_to_irq(wakeup_gpio); + ret = irq_set_irq_type(priv->wake_irq, IRQ_TYPE_LEVEL_LOW); + if (ret) + return ret; + } + + /* If we do not have a main interrupt or a side-band wake-up interrupt, + * then the device cannot be marked as wake-up capable. + */ + if (!bcm54xx_phy_can_wakeup(phydev)) + return ret; + + return device_init_wakeup(&phydev->mdio.dev, true); } static void bcm54xx_get_stats(struct phy_device *phydev, @@ -910,6 +1024,8 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .get_wol = bcm54xx_phy_get_wol, + .set_wol = bcm54xx_phy_set_wol, }, { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 9e77165f3ef6..e9afbfb6d7a5 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -89,6 +89,7 @@ #define MII_BCM54XX_EXP_SEL 0x17 /* Expansion register select */ #define MII_BCM54XX_EXP_SEL_TOP 0x0d00 /* TOP_MISC expansion register select */ #define MII_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */ +#define MII_BCM54XX_EXP_SEL_WOL 0x0e00 /* Wake-on-LAN expansion select register */ #define MII_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */ #define MII_BCM54XX_EXP_SEL_ETC 0x0d00 /* Expansion register spare + 2k mem */ @@ -253,6 +254,9 @@ #define BCM54XX_TOP_MISC_IDDQ_SD (1 << 2) #define BCM54XX_TOP_MISC_IDDQ_SR (1 << 3) +#define BCM54XX_TOP_MISC_LED_CTL (MII_BCM54XX_EXP_SEL_TOP + 0x0C) +#define BCM54XX_LED4_SEL_INTR BIT(1) + /* * BCM5482: Secondary SerDes registers */ @@ -272,6 +276,57 @@ #define BCM54612E_EXP_SPARE0 (MII_BCM54XX_EXP_SEL_ETC + 0x34) #define BCM54612E_LED4_CLK125OUT_EN (1 << 1) + +/* Wake-on-LAN registers */ +#define BCM54XX_WOL_MAIN_CTL (MII_BCM54XX_EXP_SEL_WOL + 0x80) +#define BCM54XX_WOL_EN BIT(0) +#define BCM54XX_WOL_MODE_SINGLE_MPD 0 +#define BCM54XX_WOL_MODE_SINGLE_MPDSEC 1 +#define BCM54XX_WOL_MODE_DUAL 2 +#define BCM54XX_WOL_MODE_SHIFT 1 +#define BCM54XX_WOL_MODE_MASK 0x3 +#define BCM54XX_WOL_MP_MSB_FF_EN BIT(3) +#define BCM54XX_WOL_SECKEY_OPT_4B 0 +#define BCM54XX_WOL_SECKEY_OPT_6B 1 +#define BCM54XX_WOL_SECKEY_OPT_8B 2 +#define BCM54XX_WOL_SECKEY_OPT_SHIFT 4 +#define BCM54XX_WOL_SECKEY_OPT_MASK 0x3 +#define BCM54XX_WOL_L2_TYPE_CHK BIT(6) +#define BCM54XX_WOL_L4IPV4UDP_CHK BIT(7) +#define BCM54XX_WOL_L4IPV6UDP_CHK BIT(8) +#define BCM54XX_WOL_UDPPORT_CHK BIT(9) +#define BCM54XX_WOL_CRC_CHK BIT(10) +#define BCM54XX_WOL_SECKEY_MODE BIT(11) +#define BCM54XX_WOL_RST BIT(12) +#define BCM54XX_WOL_DIR_PKT_EN BIT(13) +#define BCM54XX_WOL_MASK_MODE_DA_FF 0 +#define BCM54XX_WOL_MASK_MODE_DA_MPD 1 +#define BCM54XX_WOL_MASK_MODE_DA_ONLY 2 +#define BCM54XX_WOL_MASK_MODE_MPD 3 +#define BCM54XX_WOL_MASK_MODE_SHIFT 14 +#define BCM54XX_WOL_MASK_MODE_MASK 0x3 + +#define BCM54XX_WOL_INNER_PROTO (MII_BCM54XX_EXP_SEL_WOL + 0x81) +#define BCM54XX_WOL_OUTER_PROTO (MII_BCM54XX_EXP_SEL_WOL + 0x82) +#define BCM54XX_WOL_OUTER_PROTO2 (MII_BCM54XX_EXP_SEL_WOL + 0x83) + +#define BCM54XX_WOL_MPD_DATA1(x) (MII_BCM54XX_EXP_SEL_WOL + 0x84 + (x)) +#define BCM54XX_WOL_MPD_DATA2(x) (MII_BCM54XX_EXP_SEL_WOL + 0x87 + (x)) +#define BCM54XX_WOL_SEC_KEY_8B (MII_BCM54XX_EXP_SEL_WOL + 0x8A) +#define BCM54XX_WOL_MASK(x) (MII_BCM54XX_EXP_SEL_WOL + 0x8B + (x)) +#define BCM54XX_SEC_KEY_STORE(x) (MII_BCM54XX_EXP_SEL_WOL + 0x8E) +#define BCM54XX_WOL_SHARED_CNT (MII_BCM54XX_EXP_SEL_WOL + 0x92) + +#define BCM54XX_WOL_INT_MASK (MII_BCM54XX_EXP_SEL_WOL + 0x93) +#define BCM54XX_WOL_PKT1 BIT(0) +#define BCM54XX_WOL_PKT2 BIT(1) +#define BCM54XX_WOL_DIR BIT(2) +#define BCM54XX_WOL_ALL_INTRS (BCM54XX_WOL_PKT1 | \ + BCM54XX_WOL_PKT2 | \ + BCM54XX_WOL_DIR) + +#define BCM54XX_WOL_INT_STATUS (MII_BCM54XX_EXP_SEL_WOL + 0x94) + /*****************************************************************************/ /* Fast Ethernet Transceiver definitions. */ /*****************************************************************************/ From patchwork Mon May 8 18:43:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Fainelli X-Patchwork-Id: 13234815 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DEFE1119C for ; Mon, 8 May 2023 18:43:43 +0000 (UTC) Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECD2B5BBC; Mon, 8 May 2023 11:43:41 -0700 (PDT) Received: by mail-qt1-x835.google.com with SMTP id d75a77b69052e-3ef59098519so23077551cf.1; Mon, 08 May 2023 11:43:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1683571420; x=1686163420; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7H4aUzk9O0HSo71mKo4xYqrEbVfwlYZS2aRn8IbuLRE=; b=RJf4B2GX7Um8hYq5h0lhBcJQWAkO7/LoIzdWoj/yffU59aPl31EMRzY+sXODa7mgHq YL6WRDqCUQD2q6DvbvfNJkpqfoBYAqU5B+V2f015BtznaOv40aOEtQGMi3tLYCSCf66a CZ/a7yUcCTWSlHuOBkSGahfa59zDiIC1sPcPK9a+eKI7DpW2ExA4N5C+AvgJUrkZints REkuh1MLD31fOm5n9w+ZE/e83giVrbvp0o8dK0luB9ES7AnObz1PXgDdlyFVgpUixJ/q 74iVbSLaCFdE5Aus15IczOagO176ONV45VZBn+eQi7gWc2Z/cN8kVQGgSomidIP8Yp9s i1wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683571420; x=1686163420; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7H4aUzk9O0HSo71mKo4xYqrEbVfwlYZS2aRn8IbuLRE=; b=Ac8r40ZyNxRUiZcEqhorC34sfOKrnWXRqq8Ei/yErNnnY5j0bRT6Ysl/H6YFzlxver SmvR/2lQXQYQ0i6vHJpEgq5kBK+PsQucoO3N97yy7xJDGmWgI+XypEMeI1FO6PkM2N9M Zjw+sPzfKM5VWKWjzfLP9NHbWkvFfOTbWh8Oiisbmjmm3CBGs2wetk3wLzSsC+Vd7IDX 9BGYdy7RhnKoQVCGLEygmga9YP3vw6qmUkfRfYzTZGkdbj5hH+uPxt4NCgBdvaw+OKio t8E125yzU6qet0QmJ1CVlmjHdxdtJYGtovlvoBSM6aSF3vrVBuk460LWVbsdLli2BkO1 vg3g== X-Gm-Message-State: AC+VfDx+4vOw6hsDNku721WJyh/IVQCHbqUDljRTu6prXt/okfsYSfP3 40k5sA0YuIKDyFm6ZzjE3ibOXhCeuoc= X-Google-Smtp-Source: ACHHUZ7GacSmAR3OEXzHHULrm8M+nqoQTai+I7GN3nXVIB782NEorOGdFMXHIKixYuGYZE3xzHcBBQ== X-Received: by 2002:ac8:5a83:0:b0:3f0:a511:174f with SMTP id c3-20020ac85a83000000b003f0a511174fmr16610757qtc.20.1683571420564; Mon, 08 May 2023 11:43:40 -0700 (PDT) Received: from fainelli-desktop.igp.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id v26-20020ac83d9a000000b003d3a34d2eb2sm3193988qtf.41.2023.05.08.11.43.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 May 2023 11:43:40 -0700 (PDT) From: Florian Fainelli To: netdev@vger.kernel.org Cc: Florian Fainelli , Doug Berger , Broadcom internal kernel review list , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Andrew Lunn , Heiner Kallweit , Russell King , =?utf-8?q?Marek_Beh=C3=BAn?= , Peter Geis , Frank , linux-kernel@vger.kernel.org (open list) Subject: [PATCH net-next 3/3] net: bcmgenet: Add support for PHY-based Wake-on-LAN Date: Mon, 8 May 2023 11:43:09 -0700 Message-Id: <20230508184309.1628108-4-f.fainelli@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230508184309.1628108-1-f.fainelli@gmail.com> References: <20230508184309.1628108-1-f.fainelli@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org 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 --- drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c index 3a4b6cb7b7b9..7a41cad5788f 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c @@ -42,6 +42,12 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; + if (dev->phydev) { + phy_ethtool_get_wol(dev->phydev, wol); + if (wol->supported) + return; + } + if (!device_can_wakeup(kdev)) { wol->supported = 0; wol->wolopts = 0; @@ -63,6 +69,14 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bcmgenet_priv *priv = netdev_priv(dev); struct device *kdev = &priv->pdev->dev; + int ret; + + /* Try Wake-on-LAN from the PHY first */ + if (dev->phydev) { + ret = phy_ethtool_set_wol(dev->phydev, wol); + if (ret != -EOPNOTSUPP) + return ret; + } if (!device_can_wakeup(kdev)) return -ENOTSUPP;