With the previous patch an 'active-high' LED node is accepted, so led_polarity_mode can now hold 0. qca808x_config_init() only re-asserts QCA808X_LED_ACTIVE_HIGH when the mode is -1, the value that means device tree asked for nothing, so an explicit active-high does not reach the register. That matters because the bit does not survive a reset. phy_init_hw() runs .soft_reset before .config_init on every attach and resume, and commit f203c8c77c76 ("net: phy: qcom: qca808x: default to LED active High if not set") records why: "on PHY reset, the Active High bit is not set resulting in the LED driven as active-low". The polarity written from device tree during phy_probe() is therefore gone by the time the link comes up, and the LED runs inverted. Re-assert the bit for anything other than an explicit active-low, which is the one case that wants it clear and gets that from the reset for free. Name the unset value while here: led_polarity_mode otherwise holds a PHY_LED_ACTIVE_* value, so spelling the comparison PHY_LED_ACTIVE_LOW says what it means where -1, 0 and 1 did not. Reported-by: Sashiko Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260908105959.70453-1-donggeunyoo.kernel%40gmail.com Cc: stable@vger.kernel.org Fixes: a274465cc3be ("net: phy: support 'active-high' property for PHY LEDs") Signed-off-by: Donggeun Yoo Assisted-by: Claude:claude-fable-5 --- Tested in QEMU against a synthetic MDIO bus answering as a QCA8081, with the reset clearing BIT(6). With only 1/2 applied an 'active-high' node comes up inverted; see the cover letter. drivers/net/phy/qcom/qca808x.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/qcom/qca808x.c b/drivers/net/phy/qcom/qca808x.c index 3ba58f14e248..bab26e4c6140 100644 --- a/drivers/net/phy/qcom/qca808x.c +++ b/drivers/net/phy/qcom/qca808x.c @@ -87,6 +87,9 @@ #define QCA8081_PHY_ID 0x004dd101 +/* led_polarity_mode otherwise holds a PHY_LED_ACTIVE_* value */ +#define QCA808X_PHY_LED_UNSET -1 + MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); MODULE_LICENSE("GPL"); @@ -187,8 +190,7 @@ static int qca808x_probe(struct phy_device *phydev) if (!priv) return -ENOMEM; - /* Init LED polarity mode to -1 */ - priv->led_polarity_mode = -1; + priv->led_polarity_mode = QCA808X_PHY_LED_UNSET; phydev->priv = priv; @@ -200,8 +202,8 @@ static int qca808x_config_init(struct phy_device *phydev) struct qca808x_priv *priv = phydev->priv; int ret; - /* Default to LED Active High if active-low not in DT */ - if (priv->led_polarity_mode == -1) { + /* Set LED Active High unless active-low was requested in DT */ + if (priv->led_polarity_mode != PHY_LED_ACTIVE_LOW) { ret = phy_set_bits_mmd(phydev, MDIO_MMD_AN, QCA808X_MMD7_LED_POLARITY_CTRL, QCA808X_LED_ACTIVE_HIGH); @@ -615,7 +617,7 @@ static int qca808x_led_polarity_set(struct phy_device *phydev, int index, * To detect this, check if last requested polarity mode * match the new one. */ - if (priv->led_polarity_mode >= 0 && + if (priv->led_polarity_mode != QCA808X_PHY_LED_UNSET && priv->led_polarity_mode != active_low) { phydev_err(phydev, "PHY polarity is global. Mismatched polarity on different LED\n"); return -EINVAL; -- 2.53.0