mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Aleksei Sviridkin <f@lex.la>
To: andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk
Cc: olteanv@gmail.com, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Aleksei Sviridkin <f@lex.la>
Subject: [PATCH net v6 2/2] net: phy: restore the interrupt the bus gave a PHY
Date: Tue,  8 Sep 2026 15:50:25 +0000	[thread overview]
Message-ID: <20260908155025.4155289-3-f@lex.la> (raw)
In-Reply-To: <20260908155025.4155289-1-f@lex.la>

phy_probe() replaces phydev->irq with PHY_POLL when the driver that is
binding has no interrupt support, and nothing puts it back. A PHY whose
own driver is a module on a filesystem that is not mounted yet gets the
generic driver first, loses the number there, and polls for the rest of
the uptime once the real driver takes over.

Put it back from mdiobus->irq[], which is where the number came from:
phy_device_create() seeds phydev->irq out of that table, so the bus that
described the interrupt still holds it. Restore at the three points the
bind cycle can end, phy_remove(), phy_probe()'s own error exit and the
unwind in phy_attach_direct(), so a bind that is undone by any path
leaves the PHY as it was found.

Skip it while phy_link_change marks an attached consumer. That consumer
called phy_request_interrupt() on the PHY_POLL it saw and would free an
interrupt it never requested.

A bus whose driver writes only phydev->irq and never the table is not
covered, because the table then holds PHY_POLL and there is nothing to
give back; lan78xx, smsc95xx and sxgbe are in that position today and
registering the interrupt with the bus is theirs to do.

This needs commit e0d1c55501d3 ("net: phy: fix
phy_uses_state_machine()") to be of any use: without it the mark this
skips on is never cleared once a consumer has attached, and the restore
never runs.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
---
 drivers/net/phy/phy_device.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 94b2e85e00a3..b55402569300 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1734,6 +1734,19 @@ static bool phy_drv_supports_irq(const struct phy_driver *phydrv)
 	return phydrv->config_intr && phydrv->handle_interrupt;
 }
 
+/* Give back what phy_probe() took, from the bus that owns the number, but
+ * not while phy_link_change marks a consumer: it skipped
+ * phy_request_interrupt() on the value it saw, so phy_disconnect() would
+ * free an interrupt nobody requested.
+ */
+static void phy_restore_probe_irq(struct phy_device *phydev)
+{
+	if (phydev->phy_link_change || phydev->irq != PHY_POLL)
+		return;
+
+	phydev->irq = phydev->mdio.bus->irq[phydev->mdio.addr];
+}
+
 /**
  * phy_attach_direct - attach a network device to a given PHY device pointer
  * @dev: network device to attach
@@ -1896,6 +1909,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
 
 error_module_put:
 	module_put(d->driver->owner);
+	phy_restore_probe_irq(phydev);
 	phydev->is_genphy_driven = 0;
 	d->driver = NULL;
 error_put_device:
@@ -3820,6 +3834,8 @@ static int phy_probe(struct device *dev)
 	if (!phydev->is_on_sfp_module)
 		phy_led_triggers_unregister(phydev);
 
+	phy_restore_probe_irq(phydev);
+
 	/* Re-assert the reset signal on error */
 	phy_device_reset(phydev, 1);
 
@@ -3848,6 +3864,8 @@ static int phy_remove(struct device *dev)
 	if (phydev->drv && phydev->drv->remove)
 		phydev->drv->remove(phydev);
 
+	phy_restore_probe_irq(phydev);
+
 	/* Assert the reset signal */
 	phy_device_reset(phydev, 1);
 
-- 
2.53.0


  parent reply	other threads:[~2026-09-08 15:50 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08 15:50 [PATCH net v6 0/2] net: fix a stale phylink PHY pointer and a lost PHY interrupt Aleksei Sviridkin
2026-09-08 15:50 ` [PATCH net v6 1/2] net: phylink: unwind the PHY binding when bringup fails late Aleksei Sviridkin
2026-09-08 15:50 ` Aleksei Sviridkin [this message]
2026-09-11  3:51   ` [PATCH net v6 2/2] net: phy: restore the interrupt the bus gave a PHY netdev-bot+sashiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908155025.4155289-3-f@lex.la \
    --to=f@lex.la \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hkallweit1@gmail.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®