From dd78f34eba83ef0795a69856894fa10eb8dee97e Mon Sep 17 00:00:00 2001 From: Rudy Andram Date: Mon, 27 Jul 2026 12:32:38 +0200 Subject: [PATCH] qualcommax: pcs-qca-uniphy: take the USXGMII link from the receiver qca_uniphy_pcs_get_state_usxgmii() took the link from the USXGMII code word's link bit. An AQR113C behind this XPCS never asserts it: autonegotiation completes, the code word tracks the copper rate as the media renegotiates and reports full duplex, and the link bit stays clear the whole time. Once the port is marked as in-band managed that bit becomes the carrier gate, so the port never gets carrier, link_up() never runs, the port MAC is never enabled and the XPCS keeps its 10G reset default. Take the link from the 10GBASE-R receiver instead, the way qca_uniphy_pcs_get_state_10base_r() does. It answers the only question a PCS can answer on its own, whether the system interface is up. The code word stays the speed source: the Aquantia driver reports RATE_MATCH_NONE for USXGMII, so phylink does not substitute the PHY's speed and this is where the port's rate comes from. The link bit is kept as an_complete, which is what it actually describes. Confirmed on a QNAP QHora-301w, where 10g-1 now reaches carrier against a 1G link partner and configures an address. Signed-off-by: Rudy Andram Signed-off-by: Julius Bairaktaris Link: https://github.com/openwrt/openwrt/pull/24420 Signed-off-by: Robert Marko --- .../files/drivers/net/pcs/pcs-qca-uniphy.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/target/linux/qualcommax/files/drivers/net/pcs/pcs-qca-uniphy.c b/target/linux/qualcommax/files/drivers/net/pcs/pcs-qca-uniphy.c index 3ec4aea477..89f76ff51f 100644 --- a/target/linux/qualcommax/files/drivers/net/pcs/pcs-qca-uniphy.c +++ b/target/linux/qualcommax/files/drivers/net/pcs/pcs-qca-uniphy.c @@ -356,16 +356,24 @@ static void qca_uniphy_pcs_get_state_usxgmii(struct qca_uniphy *uniphy, unsigned int val; int ret; + ret = regmap_read(uniphy->regmap, XPCS_KR_STS1, &val); + if (ret) { + state->link = 0; + return; + } + + state->link = !!(val & XPCS_KR_STS1_PLU); + + if (!state->link) + return; + ret = regmap_read(uniphy->regmap, XPCS_MII_AN_INTR_STS, &val); if (ret) { state->link = 0; return; } - state->link = !!(val & XPCS_USXG_AN_LINK_STS); - - if (!state->link) - return; + state->an_complete = !!(val & XPCS_USXG_AN_LINK_STS); switch (FIELD_GET(XPCS_USXG_AN_SPEED_MASK, val)) { case XPCS_USXG_AN_SPEED_10000: