From nobody Sun Sep 27 00:40:09 2026 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 02CA0331A65 for ; Thu, 27 Aug 2026 21:16:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865406; cv=none; b=Dj06uQAmLuPpiTI6hu9wEJ2jfkN9g17mBxXqlV6talhxhmPPorJcgrXq9yep1kDNJHoe6lrE2XAxCD2Fe19nbBmLaGXVHDL062p27+h1dZzBq3xLSGC/+S9lyWfCF20hGKJyhp9rD3ApWmyXOAPR1DKCyJNhCgrxu/4yc7aP6Js= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865406; c=relaxed/simple; bh=8OOocvXC8LP6o3jAGo+TyFH1e88QG6h+jhSfcp4tMUI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dRvmvkqWpBhEZNfGFVzh6X+X8puNL5jhrx+mB0zHmHRKFtKlFJ9jnMSKB7JWDEQgpd1eaSuiHKBDp2hUCU6iaZdvYjsv9UlsjuXL30dwdg4yqUBUZ6Cdf98ECYQ74vW+Or+zOPbEJWvChi+rlUfD8WltJr0v2THCMsW+HzjS5TA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=lex.la; spf=pass smtp.mailfrom=lex.la; dkim=pass (2048-bit key) header.d=lex.la header.i=@lex.la header.b=YCoXGtSA; arc=none smtp.client-ip=209.85.128.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=lex.la Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=lex.la Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=lex.la header.i=@lex.la header.b="YCoXGtSA" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-49b0d8bc2aaso2734305e9.0 for ; Thu, 27 Aug 2026 14:16:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lex.la; s=google; t=1787865403; x=1788470203; darn=vger.kernel.org; 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:content-type; bh=j4jRBlKg/XoLKKaAI25ceUVYZs1W/kkw7dO9eH42sTk=; b=YCoXGtSAxVvi9s4fmULV2QPD13TthhkPrCVW1a8rGQbwUI+9JIDwccS6EjTrPq3885 rsRJ8264tohXlSd6y+SfMyEzSEdFVnvzPcVrRdkKH4TM6kjQk7T8QV24AEu7JKXeLWxh C4bgZMjKraJLeiHWbk30yV5ctnYV00HRpwESj4IBSeVCOkn/UQUyHXRkYLA41qTiGzyb D/u3igWJDP569YQ02A6EGVhC6eEiJ/P/qkKUmvx1hRWeqZsU5mDShoZeiEDzHzJ7Pn0f 1yK0M0e0GiYcdTYJZNKERkCrPntDjgLlrwyZQnatNf/qGofdlE6o8lo/vYhIj57+DbGw 9wpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787865403; x=1788470203; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=j4jRBlKg/XoLKKaAI25ceUVYZs1W/kkw7dO9eH42sTk=; b=FOp3BdswTVWLTCcduvcNNG1jhMXZ5fIiR6NXqzv/ySpx30xo51h2+2LMNE6dJO09XJ whTCdrVaopiyb9vt7yu/9iKv5v8F7OYKTeJJ1YohrEE/JjofLYhceyQnwzEWEED3kE2G Y24Ddo2acXPjuFQHQ9dLCbI7yQ2SOo5tJXhjfQQMshQ/VqYi4HgrJDU8pZw9hZXjlUkX HdPeHDB4zhW7VrmqRnHIWUJ5KUvndvYTAFz8c8D9xi+9LfiDJu9e6ZM9a6TRs2LE+f/x hlV3L7VuYalfw8Nlj7GSkGoAZLSnQzBevpOU5YnUakBIhth2gQZSfd3TVAieFfnT2eST FF4Q== X-Forwarded-Encrypted: i=1; AHgh+RpaenYeO1RnERcSNGipDWKJBOkQN0LbVPqz4OiiI+9Sv+Jg+gB58s7ztYfhxWNMR6spWHe4WlTMC65/WaE=@vger.kernel.org X-Gm-Message-State: AFuF++n9LAThfqVNVBSVxqoczJSYc6dy1vQ0fVuWBRUVCy8Jje38G+Y7 wfG13iZe+d9XsRXLeuCqbgVERoh8G8c94sM/ePECVPQ4Kzfw663hAZkK2ddqnqJBaic= X-Gm-Gg: AR+sD10Nu4xU9dn9UXq3OSS8KmgYpbo+VeOgxRucd/UiRGcFAqA1EQoBNWVw3o2kqIv YQ1iVcBfsegIjNzPXmqNO/BDXTwstO23gCrVY42dqLUjJKVq1iI7I9ufPXiNSC1A/51CW/QmB+w FeJnHs7zJ0/9Vh0KODRqkuFSnrMCecITckXilANItUkjYAN6MwrrjdUSdPQ1bZE/ELGLidZQaRr VBLJk3MW1CyGcvel3csXpdSPu1Zc0xuGrtksv8o30kddDDyj8H5vnteUVdsSnEAcj1zpot+1EyJ 8owwW08p5ocqL9arQorVCmXeic9D4k3Cbeu/Ai+6RC3F/kNkuEZe4ejbNOxqHiHcwAQknmHaaFy JdYMsmO9liH7S6GbvKtOTrHINpGWEAIuj3BnJktvt1Gg5i+VKwHrxD2fk3tisGYEXLXsBygqMQV MTKIIW8XZ7BO7D4aT13dPojvfIUdB6tN1PVf6IZJUI9OadTEY35EvEYkQ= X-Received: by 2002:a05:600c:3e1b:b0:499:8ae1:b900 with SMTP id 5b1f17b1804b1-49b91c4cb6dmr27314955e9.12.1787865403169; Thu, 27 Aug 2026 14:16:43 -0700 (PDT) Received: from ownbook ([31.146.92.111]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482e4f0c8f7sm11423442f8f.27.2026.08.27.14.16.41 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 27 Aug 2026 14:16:42 -0700 (PDT) From: Aleksei Sviridkin To: Andrew Lunn , Heiner Kallweit , Russell King Cc: Aleksei Sviridkin , Vladimir Oltean , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net v3 1/2] net: phylink: unwind the PHY binding when bringup fails late Date: Fri, 28 Aug 2026 00:16:37 +0300 Message-ID: <20260827211638.63395-2-f@lex.la> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260827211638.63395-1-f@lex.la> References: <20260827211638.63395-1-f@lex.la> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" phylink_bringup_phy() records the PHY in pl->phydev before its last fallible step: on a MAC whose phylink ops implement LPI, phy_eee_rx_clock_stop() can fail with a real MDIO error. The callers unwind with phy_detach(), which knows nothing about pl->phydev, so a pointer to a PHY that is no longer attached outlives the failed connect. What that costs depends on how the caller got here. phylink_connect_phy() and the SFP path go through phylink_attach_phy(), which refuses to attach while pl->phydev is set and turns a transient MDIO error into a permanent -EBUSY. phylink_fwnode_phy_connect() has no such check, so a later connect overwrites the stale pointer and hides the problem. A disconnect does not: phylink_disconnect_phy() hands that pointer to phy_disconnect(), and the second phy_detach() on the same PHY drops references the first one already released. Clear the binding on the failure path. This is the same operation phylink_disconnect_phy() performs, so both now share a helper. The PHY-side fields are left to phy_detach(), which every caller already runs on this path. Fixes: 03abf2a7c654 ("net: phylink: add EEE management") Signed-off-by: Aleksei Sviridkin Reviewed-by: Andrew Lunn --- drivers/net/phy/phylink.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 5b8e956902fb..a55e4a64028f 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -2083,6 +2083,18 @@ static int phylink_validate_phy(struct phylink *pl, = struct phy_device *phy, return phylink_validate(pl, supported, state); } =20 +/* Disassociate @phy from @pl. Caller must hold pl->phydev_mutex. */ +static void phylink_clear_phydev(struct phylink *pl, struct phy_device *ph= y) +{ + mutex_lock(&phy->lock); + mutex_lock(&pl->state_mutex); + pl->phydev =3D NULL; + pl->phy_enable_tx_lpi =3D false; + pl->mac_tx_clk_stop =3D false; + mutex_unlock(&pl->state_mutex); + mutex_unlock(&phy->lock); +} + static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, phy_interface_t interface) { @@ -2197,6 +2209,12 @@ static int phylink_bringup_phy(struct phylink *pl, s= truct phy_device *phy, if (ret =3D=3D 0 && phy_interrupt_is_valid(phy)) phy_request_interrupt(phy); =20 + if (ret) { + mutex_lock(&pl->phydev_mutex); + phylink_clear_phydev(pl, phy); + mutex_unlock(&pl->phydev_mutex); + } + return ret; } =20 @@ -2347,15 +2365,8 @@ void phylink_disconnect_phy(struct phylink *pl) =20 mutex_lock(&pl->phydev_mutex); phy =3D pl->phydev; - if (phy) { - mutex_lock(&phy->lock); - mutex_lock(&pl->state_mutex); - pl->phydev =3D NULL; - pl->phy_enable_tx_lpi =3D false; - pl->mac_tx_clk_stop =3D false; - mutex_unlock(&pl->state_mutex); - mutex_unlock(&phy->lock); - } + if (phy) + phylink_clear_phydev(pl, phy); mutex_unlock(&pl->phydev_mutex); =20 if (phy) { --=20 2.55.0 From nobody Sun Sep 27 00:40:09 2026 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7645524E4C6 for ; Thu, 27 Aug 2026 21:16:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865409; cv=none; b=bNWhlEuEbRFaDf3MCzaGn07XZ9atN8rwYUof8A0volwv15OPFYzQC16VGCWuiM2BbCLYmyI4qtIjv/zZvsDrMSMNAzphKTzmzouN0duSCb7O/4enJj7oexw2pf1yVnpAEyjv1Q5r4P38hOxZS/ODeXv4m/GFhubrcBeBCdV5NBg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865409; c=relaxed/simple; bh=OStuMbIJRGR13QguPPMS5Cujr1HI19Kyd2Ubu5FBRLs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=at2d6zF7WCfeloDzJSr7YNtz5/UTWA6seDy8lqxshcVggLe6A1bcuT068pAfWJfWWJp7WCowpDviFl5BKlnpXCIUepnhgkiIB6fanJksZIc90y88aj8yps16VrYJS/Yw9LMAzSxkHg/NIT7f2Rw+zpR7rHFvQkk0jSRFtC5Y/Jg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=lex.la; spf=pass smtp.mailfrom=lex.la; dkim=pass (2048-bit key) header.d=lex.la header.i=@lex.la header.b=d/ervt//; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=lex.la Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=lex.la Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=lex.la header.i=@lex.la header.b="d/ervt//" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-47c2b362ee2so69887f8f.1 for ; Thu, 27 Aug 2026 14:16:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lex.la; s=google; t=1787865405; x=1788470205; darn=vger.kernel.org; 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:content-type; bh=+A4DiEskWi8Pmb6CKBEIUqGXSf7tGcrNLyl+aIITkDY=; b=d/ervt//lXz+rtvbC5jX3kBLuQKmScpYnNLa+6IyU4W5wON4rqxVqKdy69Uh1K4FGE uERL04wsggr4P8zYwy4SFNfrdJmOyaKkTuvb5w2NQgJ3gqpcGZkuSd31HjYyl50WODZx P2+4rCNog60zOtlYSXHhsbPE6eq8gBm50H9teafKWGCPN2z7tIrduLdv9y1+TrnhLPAv lKu3gZ++NVoh6cJgd/AJgaE+utl/td9ixZOE77hHh6iDQiBTvHxkLanKxGcgpCPVwC8e Ixm9E8kzV0gqgQCmYATu2SrWpCKyDyWsOlrM+aRboGwTeto3+xGqhvzYdSK6+1gvRS7C gdpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787865405; x=1788470205; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=+A4DiEskWi8Pmb6CKBEIUqGXSf7tGcrNLyl+aIITkDY=; b=MibSzk2MnhdBy1Lcz3//g6q+d4q0AOcnwJYGNSnWFcIxkB9dfVk4+dkZmzbuqxt1Cb ycz11Bmo4XvT++kFMYr++QhYO6Mev+J85qq8b88ztil882RqTtg7JM4I07Q5jXpn/App VCOsD8Hja3L9MY1IIlPDm+OgnXCzekH9wsnZ0MI09CPp6nIhUYfgW8Jz1g3bjU2/rBEM 2kN0xYEj/Tfb7801fCq2geu5jYPGuvBgQXqCd0eRjuu1iCtqiOpcW/+jZ5GJBW6zEy4+ 4bCN6aMLP7sQ3WwSkTz9vHHPn4NaKfcfL6tbuHuPu5j8dBU/AlbEah2ncC8PxP6KKtsk AJ+A== X-Forwarded-Encrypted: i=1; AHgh+RqdQXOea0MtrtbqRJ0HeWR4Ca0h+LyIGvmenrHCQ3d/Y50wUXhl8ypFLhXGCXupOJvq0lb1Az+3IbgGYYQ=@vger.kernel.org X-Gm-Message-State: AFuF++m2dVTx1Bkztj5VTcskSmHcrLpONaNASOItOD7XF/NCVgy5X39X 4aGURBjQBHJ/sj4McRG5sXAxx6gGKiMcE5MAqDcBDpudtrN/JoosbaVTLCYaj7SZ+ls= X-Gm-Gg: AR+sD13jg4IFl3Pa9H0IaQy12RmG4RXKRioU9Y6tSYcEPL1UpvyYV9y670vDX9hoVnv FBK7ozmCmNISGIIiJaRvHwp4sn0NDi+vqU02dIVLh8Dd0UEK4oekQqDY8iLsbTpWeAwAQzcinCi +TGZV8oLKh1NDxj6/pbdMrmtejVzzbWDRmWMjp6Uu7uZL+1yEiPDC9evow75IJjNKdnQvONhpCp WTTYcFq3BZ0meWOb56owB7+LWlsUcYYNhRynWSQ6iW4ipf/mMYE9XwZIJOU9wItzrlp9g7sLe9l 1+fyOzzLptutTRNyVAHkvAmcfFo9P+eTNysQPPSF8UPxuXdqK5wttMDxTCCYMWLKB4U5Ag+UK5U 1bi81j1KxyFJUzwZ4XJ7vrJx43oPpU81adMhB3nHUt4WROQfjN908lI4IxvqL18P636rJY8x4Nb 8ICVxwSuolRHGF5wSy7wgJ99dl+lx858l3VyiNLm7ObWAx/KUMXDvX0Ok= X-Received: by 2002:a05:6000:2388:b0:47f:9283:1fb3 with SMTP id ffacd0b85a97d-482f7828315mr2228378f8f.0.1787865404806; Thu, 27 Aug 2026 14:16:44 -0700 (PDT) Received: from ownbook ([31.146.92.111]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-482e4f0c8f7sm11423442f8f.27.2026.08.27.14.16.43 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 27 Aug 2026 14:16:44 -0700 (PDT) From: Aleksei Sviridkin To: Andrew Lunn , Heiner Kallweit , Russell King Cc: Aleksei Sviridkin , Vladimir Oltean , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net v3 2/2] net: phy: restore the interrupt after a generic-driver bind cycle Date: Fri, 28 Aug 2026 00:16:38 +0300 Message-ID: <20260827211638.63395-3-f@lex.la> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260827211638.63395-1-f@lex.la> References: <20260827211638.63395-1-f@lex.la> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A PHY with no specific driver available at attach time gets the generic one, and phy_probe() sets phydev->irq to PHY_POLL because that driver has no interrupt callbacks. Neither end of that bind cycle puts the value back: phy_detach() releases the generic driver so a real one can bind later, and a generic probe that fails never reaches phy_detach() at all. The specific driver that binds afterwards therefore starts with irq =3D=3D PHY_POLL, and the PHY is polled for the rest of the uptime with no warning on that path. A DSA switch that connects its user ports before the rootfs holding the PHY driver module is mounted hits this on every boot. mdiobus_alloc() fills bus->irq[] with PHY_POLL for every address, and the bind cycle never writes to that table, so the entry still holds whatever the bus registered there. Restore phydev->irq from it on both exits, and only where the cycle left PHY_POLL. That guard preserves an interrupt mode a MAC installed on the attached PHY after connect, and it keeps a restored interrupt number out of the phy_connect_direct()/phy_disconnect() asymmetry, where such a MAC would have the interrupt requested and never freed. Fixes: 00db8189d984 ("This patch adds a PHY Abstraction Layer to the Linux = Kernel, enabling ethernet drivers to remain as ignorant as is reasonable of= the connected PHY's design and operation details.") Signed-off-by: Aleksei Sviridkin --- Both exits matter: phy_detach() for a generic driver that bound and is being released, and phy_attach_direct()'s error_module_put label for a generic probe that failed, which never calls phy_detach(). Which buses and MAC drivers the bus interrupt table covers, which other paths to PHY_POLL the guard also restores and why none of them is harmed, and the sysfs unbind case this does not cover, are worked through under v2: https://lore.kernel.org/netdev/20260824024029.41310-3-f@lex.la/ drivers/net/phy/phy_device.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 94b2e85e00a3..be4c35db8de9 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1734,6 +1734,18 @@ static bool phy_drv_supports_irq(const struct phy_dr= iver *phydrv) return phydrv->config_intr && phydrv->handle_interrupt; } =20 +/* Give back the interrupt phy_probe() parked when a driver with no interr= upt + * callbacks bound. mdiobus_alloc() defaults bus->irq[] to PHY_POLL and the + * bind cycle does not touch the table, so whatever the bus recorded there + * still stands. Only the parking is undone: any other value the PHY carri= es + * was put there by someone else. + */ +static void phy_restore_genphy_irq(struct phy_device *phydev) +{ + if (phydev->irq =3D=3D PHY_POLL) + phydev->irq =3D phydev->mdio.bus->irq[phydev->mdio.addr]; +} + /** * phy_attach_direct - attach a network device to a given PHY device point= er * @dev: network device to attach @@ -1896,6 +1908,7 @@ int phy_attach_direct(struct net_device *dev, struct = phy_device *phydev, =20 error_module_put: module_put(d->driver->owner); + phy_restore_genphy_irq(phydev); phydev->is_genphy_driven =3D 0; d->driver =3D NULL; error_put_device: @@ -1965,6 +1978,7 @@ void phy_detach(struct phy_device *phydev) * real driver could be loaded */ if (phydev->is_genphy_driven) { + phy_restore_genphy_irq(phydev); device_release_driver(&phydev->mdio.dev); phydev->is_genphy_driven =3D 0; } --=20 2.55.0