* [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
@ 2026-11-11 23:48 Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 1/4] net: phy: move irq_suspended and irq_rerun out of the bitfield Igor Velkov via B4 Relay
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-11-11 23:48 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
Igor Velkov
When the MAC driver manages PHY PM, phylib never sets irq_suspended, and
a PHY interrupt during the sleep transition runs the PHY driver's
handler while the MDIO bus may be powered down. On Helios64 (dwmac-rk)
this hangs the board on suspend as well as on resume.
mac_managed_pm hands phy_suspend(), phy_resume() and the state machine
to the MAC driver, since commit fba863b81604 ("net: phy: make PHY PM
ops a no-op if MAC driver manages PHY PM"); the PHY interrupt stays
with phylib, and so does postponing it.
Patches 1-3 fix the postponing that phylib applies to other PHYs, so
that patch 4 can extend it to MAC-managed ones. Patch 1 moves the two
flags out of a bitfield they share with the link state written under
phydev->lock. Patch 2 keeps the line of a postponed interrupt balanced
when an edge reruns the IRQ thread or phy_free_interrupt() runs during
the transition. Patch 3 undoes the postponing when phy_suspend() fails
and ends it when the PHY fails to resume. Patch 4 sets irq_suspended
for MAC-managed PHYs too and decides the wakeup event of a postponed
interrupt before the device that owns the MDIO bus suspends.
Not covered: MDIO accesses from closing or opening the interface during
the transition, and a MAC resume that fails to power the bus up. On a
shared line, a postponed PHY interrupt disables the line for its other
users until the PHY resumes; patch 4 extends that to MAC-managed PHYs. A
nested threaded PHY interrupt is not replayed (irq_wake_thread() has no
thread to wake), and mdio_bus_phy_may_suspend() does not ask
phy_may_wakeup() about an attached PHY.
With MAC-managed PM, a postponed interrupt reports a system wakeup only
when Wake-on-LAN is enabled in the PHY. A PHY that leaves its link
interrupt unmasked while armed for Wake-on-LAN can then abort suspend
when the MAC changes the link. Going by their suspend code, BCM54210E
leaves it unmasked, while RTL8211F and AN8801R mask it. Tested on
Helios64 (dwmac-rk, RTL8211F); Haoning Cheng tested v4 on i.MX6 (fec).
Changes in v5:
- v4 patch 2 alone could leave irq_rerun set across
phy_free_interrupt() and a new request, after which a postponed
level interrupt fired without end; it is merged with v4 patch 3 into
patch 2. phy_free_interrupt() re-enables the line after free_irq(),
not before, and only while other users of a shared line remain, so
the handler cannot keep running on a source it cannot quiet;
irq_rerun stays a bool (Sashiko on v4)
- patch 3: when the PHY fails to resume, the line a postponed
interrupt disabled stays off, as before this series, instead of
rerunning a handler that may not reach the PHY (Sashiko on v4)
- patch 4: with mac_managed_pm, only Wake-on-LAN in the PHY makes a
postponed interrupt a wakeup; the ethtool flag may describe
Wake-on-LAN in the MAC, as with fec (Sashiko on v4); for a PHY that
phy_suspend() already suspended, the PHY part of its Wake-on-LAN
state is kept in the new wol_phy
- patch 4: Fixes: now points at 1758bde2e4aa, which added the
postponing after the early return for MAC-managed PHY PM
- comments say that postponing lasts until the transition ends
- Haoning Cheng's Tested-by on v4 kept on patch 1 only: patches 2-4
changed
- rebased on net
- tests rerun on v5
- Link to v4: https://lore.kernel.org/r/20261031-b4-phylib-mac-pm-irq-v3-v4-0-5ba23b3ff9a4@iav.lv
Changes in v4:
- new patches 2-4, one pre-existing defect each
- patch 2: an edge that reruns the IRQ thread no longer disables the
line twice
- patch 3: phy_free_interrupt() during the transition keeps the line
balanced (Sashiko on v3)
- patch 4: a failing PHY PM callback no longer leaves the interrupt
postponed (Sashiko on v2 and v3)
- patch 5: the wakeup event is decided in mdio_bus_phy_suspend(), where
phy_may_wakeup() can still read the PHY (Sashiko on v3); Fixes: now
points at the stmmac commit that took its PHYs out of postponing
- v3 asked phylib or phylink_suspend(): phylib, as macb sets
mac_managed_pm but suspends with phylink_stop()
- tests rerun on v4
- Link to v3: https://lore.kernel.org/r/20261029-b4-phylib-mac-pm-irq-v3-v3-0-5907045f3210@iav.lv
Changes in v3:
- with mac_managed_pm, a postponed interrupt signals a wakeup event only
with Wake-on-LAN; with MAC power/wakeup enabled and no WoL, v2 aborted
s2idle on Helios64 3 of 3 times, v3 0 of 3 (reported by Sashiko)
- phy_free_interrupt(): stop postponing and re-enable the line before
free_irq(), not after it (reported by Sashiko)
- mdio_bus_phy_suspend() comment narrowed to the MDIO bus (reported by
Sashiko)
- patch 1: Andrew suggested taking phydev->lock in phy_interrupt();
the commit message says why that does not close the race
- tests rerun on v3
- Link to v2: https://lore.kernel.org/r/20261026045343.837889-1-iav@iav.lv
Signed-off-by: Igor Velkov <iav@iav.lv>
---
Igor Velkov (4):
net: phy: move irq_suspended and irq_rerun out of the bitfield
net: phy: keep the line of a postponed PHY interrupt balanced
net: phy: stop postponing PHY interrupts when a PHY PM callback fails
net: phy: postpone PHY interrupts during sleep with MAC-managed PM
drivers/net/phy/phy.c | 45 +++++++++++----
drivers/net/phy/phy_device.c | 134 ++++++++++++++++++++++++++++++++++---------
include/linux/phy.h | 35 +++++++++--
3 files changed, 169 insertions(+), 45 deletions(-)
---
base-commit: 8d5ce4751fad9499ea408163af7f410f18a85782
change-id: 20261029-b4-phylib-mac-pm-irq-v3-f656d4e1c64f
Best regards,
--
Igor Velkov <iav@iav.lv>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net v5 1/4] net: phy: move irq_suspended and irq_rerun out of the bitfield
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
@ 2026-11-11 23:48 ` Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 2/4] net: phy: keep the line of a postponed PHY interrupt balanced Igor Velkov via B4 Relay
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-11-11 23:48 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
Igor Velkov
From: Igor Velkov <iav@iav.lv>
irq_suspended and irq_rerun share a word with link, autoneg_complete
and interrupts. phy_interrupt() sets irq_rerun from the IRQ thread
without phydev->lock, while the state machine writes link and
autoneg_complete under it and phy_request_interrupt()/
phy_free_interrupt() write interrupts, so one read-modify-write can
undo another. A lost irq_rerun leaves the PHY interrupt disabled after
resume, as phy_interrupt() has already disabled the line.
The last patch of this series sets irq_suspended for PHYs whose MAC
driver manages PHY PM; with stmmac that happens before the MAC stops
the PHY, which widens the window.
Taking phydev->lock in phy_interrupt() alone does not close it:
phy_suspend() stores suspended in the same word and cannot hold the
lock across phy_may_wakeup(), which may take it, and phy_init_hw() and
mdio_bus_phy_suspend() write the word unlocked too. Locking every
writer, MAC drivers included, is a wide audit, and one missed now or
added later reopens the race.
Make both flags bools.
Fixes: 1758bde2e4aa ("net: phy: Don't trigger state machine while in suspend")
Tested-by: Haoning Cheng <Haoning.CHENG@cn.bosch.com>
Signed-off-by: Igor Velkov <iav@iav.lv>
---
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 6 +++---
include/linux/phy.h | 5 +++--
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index fce9bc7be330..9af303d60bd6 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1430,7 +1430,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
pm_wakeup_dev_event(parent, 0, true);
}
- phydev->irq_rerun = 1;
+ phydev->irq_rerun = true;
disable_irq_nosync(irq);
return IRQ_HANDLED;
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 06c5a8c8cc2a..f00086d72771 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -344,7 +344,7 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
* has resumed. Wait for concurrent interrupt handler to complete.
*/
if (phy_interrupt_is_valid(phydev)) {
- phydev->irq_suspended = 1;
+ phydev->irq_suspended = true;
synchronize_irq(phydev->irq);
}
@@ -394,14 +394,14 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
return ret;
no_resume:
if (phy_interrupt_is_valid(phydev)) {
- phydev->irq_suspended = 0;
+ phydev->irq_suspended = false;
synchronize_irq(phydev->irq);
/* Rerun interrupts which were postponed by phy_interrupt()
* because they occurred during the system sleep transition.
*/
if (phydev->irq_rerun) {
- phydev->irq_rerun = 0;
+ phydev->irq_rerun = false;
enable_irq(phydev->irq);
irq_wake_thread(phydev->irq, phydev);
}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 21afc2082b17..bbe28ff97e51 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -726,8 +726,9 @@ struct phy_device {
/* Interrupts are enabled */
unsigned interrupts:1;
- unsigned irq_suspended:1;
- unsigned irq_rerun:1;
+ /* Written without phydev->lock, so not bitfields */
+ bool irq_suspended;
+ bool irq_rerun;
unsigned default_timestamp:1;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net v5 2/4] net: phy: keep the line of a postponed PHY interrupt balanced
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 1/4] net: phy: move irq_suspended and irq_rerun out of the bitfield Igor Velkov via B4 Relay
@ 2026-11-11 23:48 ` Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 3/4] net: phy: stop postponing PHY interrupts when a PHY PM callback fails Igor Velkov via B4 Relay
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-11-11 23:48 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
Igor Velkov
From: Igor Velkov <iav@iav.lv>
phy_interrupt() postpones interrupts during a system sleep transition:
it sets irq_rerun and disables the line, and mdio_bus_phy_resume()
re-enables the line once and reruns the handler. Two paths leave the
line unbalanced:
- On an edge-triggered line the IRQ core does not mask a ONESHOT
interrupt, so an edge that arrives before disable_irq_nosync() runs
the thread again. That second run disables the line again, and the
line stays disabled after resume.
- phy_free_interrupt() can run between the postponed interrupt and
mdio_bus_phy_resume() and leaves irq_rerun set. Other users of a
shared line stay without interrupts until mdio_bus_phy_resume().
Without other users, a new request starts the line at depth 0, and
the enable_irq() in mdio_bus_phy_resume() is unbalanced.
MAC drivers that close the interface in their suspend callback, such as
cpsw, and ravb with Wake-on-LAN off, reach phy_free_interrupt() through
phy_disconnect(), and so does dev_close() in a kernel-internal reset of
the MAC such as stmmac_reset_subtask(), whose workqueue does not freeze.
These drivers set mac_managed_pm, which a later patch brings under
postponing.
Let only the run that sets irq_rerun disable the line. Let
phy_free_interrupt() consume irq_rerun after free_irq(), which waits for
the handler, and give the depth back with enable_irq() if a postponed
interrupt took it. Other users of a shared line get the line back. A
line the PHY was alone on is left alone: free_irq() has shut it down,
and the next request resets its depth. Re-enabling after free_irq(), not
before, leaves no PHY handler to run again on a source that
phy_disable_interrupts() did not clear.
Add irq_pm_lock, so that phy_free_interrupt() and the rerun after
resume do not both re-enable the line, and move the postponing and the
rerun into helpers. phy_interrupt() never takes the lock, so
synchronize_irq() and free_irq() can wait for the handler under it.
irq_rerun stays a plain bool: one thread runs the handler, and the
other two read it only under the lock, after free_irq() or
synchronize_irq(). Mark the irq_suspended accesses with READ_ONCE() and
WRITE_ONCE(): the handler reads it while the PM callbacks write it.
This does not keep close and open off the MDIO bus: on close,
phy_disconnect() calls phy_stop(), phy_disable_interrupts() and, in
phy_detach(), phy_suspend(); on open, phy_attach_direct() calls
phy_init_hw() and phy_request_interrupt() calls
phy_enable_interrupts(). A MAC driver that powers its MDIO bus down
during sleep must not close or open the interface until the bus is
back.
Fixes: 1758bde2e4aa ("net: phy: Don't trigger state machine while in suspend")
Signed-off-by: Igor Velkov <iav@iav.lv>
---
Haoning Cheng's Tested-by on v4 is not carried: this patch merges v4
patches 2 and 3 and reworks phy_free_interrupt().
---
drivers/net/phy/phy.c | 20 +++++++++++++---
drivers/net/phy/phy_device.c | 56 +++++++++++++++++++++++++++-----------------
include/linux/phy.h | 7 ++++--
3 files changed, 57 insertions(+), 26 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 9af303d60bd6..ea22ebb14a83 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1416,7 +1416,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
/* Wakeup interrupts may occur during a system sleep transition.
* Postpone handling until the PHY has resumed.
*/
- if (IS_ENABLED(CONFIG_PM_SLEEP) && phydev->irq_suspended) {
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && READ_ONCE(phydev->irq_suspended)) {
struct net_device *netdev = phydev->attached_dev;
if (netdev) {
@@ -1430,8 +1430,11 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
pm_wakeup_dev_event(parent, 0, true);
}
- phydev->irq_rerun = true;
- disable_irq_nosync(irq);
+ /* Disable the line only once: an edge can rerun the thread. */
+ if (!phydev->irq_rerun) {
+ phydev->irq_rerun = true;
+ disable_irq_nosync(irq);
+ }
return IRQ_HANDLED;
}
@@ -1507,7 +1510,18 @@ EXPORT_SYMBOL(phy_request_interrupt);
void phy_free_interrupt(struct phy_device *phydev)
{
phy_disable_interrupts(phydev);
+
+ mutex_lock(&phydev->irq_pm_lock);
free_irq(phydev->irq, phydev);
+ /* Give the depth a postponed interrupt took back to the other users of
+ * a shared line; requesting a line we were alone on resets its depth.
+ */
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = false;
+ if (irq_has_action(phydev->irq))
+ enable_irq(phydev->irq);
+ }
+ mutex_unlock(&phydev->irq_pm_lock);
}
EXPORT_SYMBOL(phy_free_interrupt);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f00086d72771..d3815ee21541 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -332,6 +332,38 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
return !phydev->suspended;
}
+/* Wakeup interrupts may occur during the system sleep transition when
+ * the PHY is inaccessible. Set flag to postpone handling until the PHY
+ * has resumed. Wait for concurrent interrupt handler to complete.
+ */
+static __maybe_unused void mdio_bus_phy_suspend_irq(struct phy_device *phydev)
+{
+ if (!phy_interrupt_is_valid(phydev))
+ return;
+
+ WRITE_ONCE(phydev->irq_suspended, true);
+ synchronize_irq(phydev->irq);
+}
+
+/* Rerun interrupts which were postponed by phy_interrupt()
+ * because they occurred during the system sleep transition.
+ */
+static __maybe_unused void mdio_bus_phy_resume_irq(struct phy_device *phydev)
+{
+ WRITE_ONCE(phydev->irq_suspended, false);
+ if (!phy_interrupt_is_valid(phydev))
+ return;
+
+ mutex_lock(&phydev->irq_pm_lock);
+ synchronize_irq(phydev->irq);
+ if (phydev->irq_rerun) {
+ phydev->irq_rerun = false;
+ enable_irq(phydev->irq);
+ irq_wake_thread(phydev->irq, phydev);
+ }
+ mutex_unlock(&phydev->irq_pm_lock);
+}
+
static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
{
struct phy_device *phydev = to_phy_device(dev);
@@ -339,14 +371,7 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (phydev->mac_managed_pm)
return 0;
- /* Wakeup interrupts may occur during the system sleep transition when
- * the PHY is inaccessible. Set flag to postpone handling until the PHY
- * has resumed. Wait for concurrent interrupt handler to complete.
- */
- if (phy_interrupt_is_valid(phydev)) {
- phydev->irq_suspended = true;
- synchronize_irq(phydev->irq);
- }
+ mdio_bus_phy_suspend_irq(phydev);
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
@@ -393,19 +418,7 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
if (ret < 0)
return ret;
no_resume:
- if (phy_interrupt_is_valid(phydev)) {
- phydev->irq_suspended = false;
- synchronize_irq(phydev->irq);
-
- /* Rerun interrupts which were postponed by phy_interrupt()
- * because they occurred during the system sleep transition.
- */
- if (phydev->irq_rerun) {
- phydev->irq_rerun = false;
- enable_irq(phydev->irq);
- irq_wake_thread(phydev->irq, phydev);
- }
- }
+ mdio_bus_phy_resume_irq(phydev);
if (phy_uses_state_machine(phydev))
phy_start_machine(phydev);
@@ -711,6 +724,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
dev->max_n_ports = 1;
mutex_init(&dev->lock);
+ mutex_init(&dev->irq_pm_lock);
INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
/* Request the appropriate module unconditionally; don't
diff --git a/include/linux/phy.h b/include/linux/phy.h
index bbe28ff97e51..a2a4d318e334 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -651,8 +651,9 @@ struct phy_oatc14_sqi_capability {
* @interrupts: Flag interrupts have been enabled
* @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
* handling shall be postponed until PHY has resumed
- * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended,
- * requiring a rerun of the interrupt handler after resume
+ * @irq_rerun: Set by the postponed interrupt that disabled the line
+ * @irq_pm_lock: Serializes phy_free_interrupt() against the rerun of a
+ * postponed interrupt; never taken by phy_interrupt()
* @default_timestamp: Flag indicating whether we are using the phy
* timestamp as the default one
* @interface: enum phy_interface_t value
@@ -729,6 +730,8 @@ struct phy_device {
/* Written without phydev->lock, so not bitfields */
bool irq_suspended;
bool irq_rerun;
+ /* Serializes phy_free_interrupt() against mdio_bus_phy_resume_irq() */
+ struct mutex irq_pm_lock;
unsigned default_timestamp:1;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net v5 3/4] net: phy: stop postponing PHY interrupts when a PHY PM callback fails
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 1/4] net: phy: move irq_suspended and irq_rerun out of the bitfield Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 2/4] net: phy: keep the line of a postponed PHY interrupt balanced Igor Velkov via B4 Relay
@ 2026-11-11 23:48 ` Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 4/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-11-11 23:48 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
Igor Velkov
From: Igor Velkov <iav@iav.lv>
When phy_suspend() fails in mdio_bus_phy_suspend(), irq_suspended
stays set and the state machine stays stopped: the PM core does not
resume a device whose suspend callback failed, and the next PHY
interrupt disables the line until the next resume. When phy_init_hw()
or phy_resume() fail, mdio_bus_phy_resume() returns before the rerun,
with irq_suspended set and a postponed interrupt left disabled.
Undo the postponing and restart the state machine when phy_suspend()
fails. When phy_init_hw() or phy_resume() fail, stop postponing too, but
leave a line that a postponed interrupt disabled off, as before this
patch: the PHY may be out of reach, and its handler could not quiet a
level-triggered source. The line comes back on the next successful
resume; phy_free_interrupt() gives it back to the other users of a
shared line, and a new request restarts it.
Fixes: 1758bde2e4aa ("net: phy: Don't trigger state machine while in suspend")
Signed-off-by: Igor Velkov <iav@iav.lv>
---
Haoning Cheng's Tested-by on v4 is not carried: a failed resume now
leaves the line disabled.
---
drivers/net/phy/phy.c | 2 +-
drivers/net/phy/phy_device.c | 29 ++++++++++++++++++++++++-----
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ea22ebb14a83..62b7f428f9da 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1414,7 +1414,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
irqreturn_t ret;
/* Wakeup interrupts may occur during a system sleep transition.
- * Postpone handling until the PHY has resumed.
+ * Postpone handling until the transition ends.
*/
if (IS_ENABLED(CONFIG_PM_SLEEP) && READ_ONCE(phydev->irq_suspended)) {
struct net_device *netdev = phydev->attached_dev;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index d3815ee21541..110c9dfcbd91 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -333,8 +333,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
}
/* Wakeup interrupts may occur during the system sleep transition when
- * the PHY is inaccessible. Set flag to postpone handling until the PHY
- * has resumed. Wait for concurrent interrupt handler to complete.
+ * the PHY is inaccessible. Set flag to postpone handling until the
+ * transition ends. Wait for concurrent interrupt handler to complete.
*/
static __maybe_unused void mdio_bus_phy_suspend_irq(struct phy_device *phydev)
{
@@ -367,6 +367,7 @@ static __maybe_unused void mdio_bus_phy_resume_irq(struct phy_device *phydev)
static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
{
struct phy_device *phydev = to_phy_device(dev);
+ int ret;
if (phydev->mac_managed_pm)
return 0;
@@ -384,9 +385,20 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
if (!mdio_bus_phy_may_suspend(phydev))
return 0;
+ ret = phy_suspend(phydev);
+ if (ret) {
+ /* The PM core skips the resume callback of a device whose
+ * suspend callback failed.
+ */
+ mdio_bus_phy_resume_irq(phydev);
+ if (phy_uses_state_machine(phydev))
+ phy_start_machine(phydev);
+ return ret;
+ }
+
phydev->suspended_by_mdio_bus = 1;
- return phy_suspend(phydev);
+ return 0;
}
static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
@@ -412,11 +424,11 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
ret = phy_init_hw(phydev);
if (ret < 0)
- return ret;
+ goto err;
ret = phy_resume(phydev);
if (ret < 0)
- return ret;
+ goto err;
no_resume:
mdio_bus_phy_resume_irq(phydev);
@@ -424,6 +436,13 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
phy_start_machine(phydev);
return 0;
+
+err:
+ /* Stop postponing, but leave a line that a postponed interrupt
+ * disabled off: its handler may not reach a PHY that did not resume.
+ */
+ WRITE_ONCE(phydev->irq_suspended, false);
+ return ret;
}
static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend,
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net v5 4/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
` (2 preceding siblings ...)
2026-11-11 23:48 ` [PATCH net v5 3/4] net: phy: stop postponing PHY interrupts when a PHY PM callback fails Igor Velkov via B4 Relay
@ 2026-11-11 23:48 ` Igor Velkov via B4 Relay
2026-11-11 23:51 ` [PATCH net v5 0/4] " netdev-bot+sinfo
2026-11-11 23:53 ` Igor Velkov
5 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-11-11 23:48 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel,
Igor Velkov
From: Igor Velkov <iav@iav.lv>
mdio_bus_phy_suspend() and mdio_bus_phy_resume() return early when the
MAC driver manages PHY PM, so the PHY never gets irq_suspended and
phy_interrupt() runs the PHY driver's handler at any point of the sleep
transition. If the MAC driver powers the MDIO bus down, the MDIO access
in that handler can stall the CPU. This happens on both sides:
- suspend: the MAC's suspend callback stops the PHY, the link goes
down, and the handler runs while the MAC powers down;
- resume: resume_device_irqs() re-enables a pending interrupt before
the MAC resumes.
On Helios64 (dwmac-rk, RTL8211F with its interrupt line described in DT)
both hang the board: the handler reads INSR while the GMAC clocks are
off, after rk_gmac_suspend() or before rk_gmac_resume(). The commit in
the Fixes tag added the postponing after the early return for
MAC-managed PHY PM, and stmmac has set mac_managed_pm since commit
f151c147b3af ("net: stmmac: Enable mac_managed_pm phylink config").
Set irq_suspended for these PHYs too. The PHY device is a child of its
MDIO bus, so mdio_bus_phy_resume() runs after the resume callbacks of
the bus and its parents (with stmmac, the MAC) and replays the postponed
interrupt then. The PM core resumes children of a device whose resume
callback failed, and phylib cannot tell: if the MAC fails to power the
bus up, the replay still reaches the bus. phy_suspend(), phy_resume()
and the state machine stay with the MAC driver, and no MAC driver needs
a change. Doing this in phylink_suspend() instead would miss macb, which
sets mac_managed_pm but suspends with phylink_stop().
A postponed interrupt cannot ask the PHY whether Wake-on-LAN is enabled:
phy_may_wakeup() may read the PHY over MDIO. Decide that in
mdio_bus_phy_suspend() instead, which runs before the suspend callback
of the device that owns the MDIO bus, and store the wakeup event to
report. For a PHY whose MAC manages PHY PM, this MDIO access in the
suspend path is new; phy_suspend() makes the same one for other PHYs. A
PHY on the MDIO bus of another MAC can already be suspended there:
phy_attach_direct() links its MAC to it, so the MAC suspends first. For
a suspended PHY without driver-model wakeup, do not read the PHY: use
wol_phy, where phy_suspend() now keeps the answer of phy_may_wakeup().
wol_enabled also counts Wake-on-LAN in the MAC.
mdio_bus_phy_suspend_irq() sets irq_suspended with a store-release after
writing irq_wake, and phy_interrupt() reads it with a load-acquire, so a
postponed interrupt sees the event decided for it.
A PHY reports a system wakeup when phy_may_wakeup() says Wake-on-LAN is
enabled in it, as phy_suspend() already counts it; this is new for PHYs
without MAC-managed PM too. Otherwise a PHY without MAC-managed PM
reports what phy_interrupt() reports today: Wake-on-LAN set through
ethtool, then the netdev and its parent. A PHY with MAC-managed PM
reports nothing: the MAC stops the PHY itself, its ethtool flag may
describe Wake-on-LAN in the MAC, as with fec, and the MAC device may
wake the system on its own, so a link interrupt the MAC causes must not
abort suspend.
Tested on Helios64 with 7.3.4, s2idle with the link up:
- no Wake-on-LAN, GMAC clocks off in suspend: 10 of 10 cycles suspended
and resumed; on 7.3 without this series the same test hung or reset
the board after the link went down 10 of 10 times;
- MAC power/wakeup enabled, no Wake-on-LAN: 3 of 3 slept;
- Wake-on-LAN in the PHY, so phylink_suspend() also drops the link
speed: a magic packet woke the board 4 of 4 times, no suspend
aborted.
Fixes: 1758bde2e4aa ("net: phy: Don't trigger state machine while in suspend")
Signed-off-by: Igor Velkov <iav@iav.lv>
---
Haoning Cheng's Tested-by on v4 is not carried: the wakeup policy for
MAC-managed PHYs changed.
---
drivers/net/phy/phy.c | 25 ++++++++++++-------
drivers/net/phy/phy_device.c | 57 ++++++++++++++++++++++++++++++++++++++++----
include/linux/phy.h | 23 ++++++++++++++++--
3 files changed, 89 insertions(+), 16 deletions(-)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 62b7f428f9da..1a7648c381f7 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1416,18 +1416,25 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
/* Wakeup interrupts may occur during a system sleep transition.
* Postpone handling until the transition ends.
*/
- if (IS_ENABLED(CONFIG_PM_SLEEP) && READ_ONCE(phydev->irq_suspended)) {
+ if (IS_ENABLED(CONFIG_PM_SLEEP) &&
+ /* Pairs with smp_store_release() in mdio_bus_phy_suspend_irq() */
+ smp_load_acquire(&phydev->irq_suspended)) {
struct net_device *netdev = phydev->attached_dev;
- if (netdev) {
- struct device *parent = netdev->dev.parent;
-
- if (netdev->ethtool->wol_enabled)
- pm_system_wakeup();
- else if (device_may_wakeup(&netdev->dev))
+ switch (phydev->irq_wake) {
+ case PHY_IRQ_WAKE_SYSTEM:
+ pm_system_wakeup();
+ break;
+ case PHY_IRQ_WAKE_NETDEV:
+ if (netdev)
pm_wakeup_dev_event(&netdev->dev, 0, true);
- else if (parent && device_may_wakeup(parent))
- pm_wakeup_dev_event(parent, 0, true);
+ break;
+ case PHY_IRQ_WAKE_PARENT:
+ if (netdev && netdev->dev.parent)
+ pm_wakeup_dev_event(netdev->dev.parent, 0, true);
+ break;
+ case PHY_IRQ_WAKE_NONE:
+ break;
}
/* Disable the line only once: an edge can rerun the thread. */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 110c9dfcbd91..2dc13dd1afb6 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -332,6 +332,44 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev)
return !phydev->suspended;
}
+static __maybe_unused enum phy_irq_wake
+phy_irq_wake_source(struct phy_device *phydev)
+{
+ struct net_device *netdev = phydev->attached_dev;
+ bool phy_wol;
+
+ if (!netdev)
+ return PHY_IRQ_WAKE_NONE;
+
+ /* phy_suspend() cached the answer of a suspended PHY, which may
+ * not be reachable over MDIO.
+ */
+ if (phydev->suspended && !phy_can_wakeup(phydev))
+ phy_wol = phydev->wol_phy;
+ else
+ phy_wol = phy_may_wakeup(phydev);
+
+ if (phy_wol)
+ return PHY_IRQ_WAKE_SYSTEM;
+
+ /* With MAC-managed PM, only Wake-on-LAN in the PHY makes its
+ * interrupt a wakeup: the MAC stops the PHY itself.
+ */
+ if (phydev->mac_managed_pm)
+ return PHY_IRQ_WAKE_NONE;
+
+ if (netdev->ethtool->wol_enabled)
+ return PHY_IRQ_WAKE_SYSTEM;
+
+ if (device_may_wakeup(&netdev->dev))
+ return PHY_IRQ_WAKE_NETDEV;
+
+ if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent))
+ return PHY_IRQ_WAKE_PARENT;
+
+ return PHY_IRQ_WAKE_NONE;
+}
+
/* Wakeup interrupts may occur during the system sleep transition when
* the PHY is inaccessible. Set flag to postpone handling until the
* transition ends. Wait for concurrent interrupt handler to complete.
@@ -341,7 +379,10 @@ static __maybe_unused void mdio_bus_phy_suspend_irq(struct phy_device *phydev)
if (!phy_interrupt_is_valid(phydev))
return;
- WRITE_ONCE(phydev->irq_suspended, true);
+ /* A postponed handler cannot read the PHY: decide the event now */
+ phydev->irq_wake = phy_irq_wake_source(phydev);
+ /* Pairs with smp_load_acquire() in phy_interrupt() */
+ smp_store_release(&phydev->irq_suspended, true);
synchronize_irq(phydev->irq);
}
@@ -369,11 +410,14 @@ static __maybe_unused int mdio_bus_phy_suspend(struct device *dev)
struct phy_device *phydev = to_phy_device(dev);
int ret;
+ /* An interrupt can fire while the MAC has the MDIO bus powered
+ * down, whether or not the MAC manages PHY PM.
+ */
+ mdio_bus_phy_suspend_irq(phydev);
+
if (phydev->mac_managed_pm)
return 0;
- mdio_bus_phy_suspend_irq(phydev);
-
/* We must stop the state machine manually, otherwise it stops out of
* control, possibly with the phydev->lock held. Upon resume, netdev
* may call phy routines that try to grab the same lock, and that may
@@ -406,8 +450,10 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
struct phy_device *phydev = to_phy_device(dev);
int ret;
- if (phydev->mac_managed_pm)
+ if (phydev->mac_managed_pm) {
+ mdio_bus_phy_resume_irq(phydev);
return 0;
+ }
if (!phydev->suspended_by_mdio_bus)
goto no_resume;
@@ -2127,7 +2173,8 @@ int phy_suspend(struct phy_device *phydev)
if (phydev->suspended || !phydrv)
return 0;
- phydev->wol_enabled = phy_may_wakeup(phydev) ||
+ phydev->wol_phy = phy_may_wakeup(phydev);
+ phydev->wol_enabled = phydev->wol_phy ||
(netdev && netdev->ethtool->wol_enabled);
/* If the device has WOL enabled, we cannot suspend the PHY */
if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND))
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a2a4d318e334..b1fdc4504b68 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -573,6 +573,20 @@ struct phy_oatc14_sqi_capability {
u8 sqiplus_bits;
};
+/**
+ * enum phy_irq_wake - wakeup event a postponed PHY interrupt reports
+ * @PHY_IRQ_WAKE_NONE: none
+ * @PHY_IRQ_WAKE_SYSTEM: pm_system_wakeup(), Wake-on-LAN is enabled
+ * @PHY_IRQ_WAKE_NETDEV: pm_wakeup_dev_event() for the attached netdev
+ * @PHY_IRQ_WAKE_PARENT: pm_wakeup_dev_event() for the netdev's parent
+ */
+enum phy_irq_wake {
+ PHY_IRQ_WAKE_NONE,
+ PHY_IRQ_WAKE_SYSTEM,
+ PHY_IRQ_WAKE_NETDEV,
+ PHY_IRQ_WAKE_PARENT,
+};
+
/**
* struct phy_device - An instance of a PHY
*
@@ -600,6 +614,7 @@ struct phy_oatc14_sqi_capability {
* @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.
+ * @wol_phy: Set to true if phy_suspend() found that the PHY may wake the system
* @is_genphy_driven: PHY is driven by one of the generic PHY drivers
* @state: State of the PHY for management purposes
* @dev_flags: Device-specific flags used by the PHY driver.
@@ -649,9 +664,11 @@ struct phy_oatc14_sqi_capability {
* @mdix_ctrl: User setting of crossover
* @pma_extable: Cached value of PMA/PMD Extended Abilities Register
* @interrupts: Flag interrupts have been enabled
- * @irq_suspended: Flag indicating PHY is suspended and therefore interrupt
- * handling shall be postponed until PHY has resumed
+ * @irq_suspended: Flag indicating a system sleep transition in progress, so
+ * interrupt handling shall be postponed until it ends
* @irq_rerun: Set by the postponed interrupt that disabled the line
+ * @irq_wake: Wakeup event a postponed interrupt reports, decided by
+ * mdio_bus_phy_suspend()
* @irq_pm_lock: Serializes phy_free_interrupt() against the rerun of a
* postponed interrupt; never taken by phy_interrupt()
* @default_timestamp: Flag indicating whether we are using the phy
@@ -716,6 +733,7 @@ struct phy_device {
unsigned is_on_sfp_module:1;
unsigned mac_managed_pm:1;
unsigned wol_enabled:1;
+ unsigned wol_phy:1;
unsigned is_genphy_driven:1;
unsigned autoneg:1;
@@ -730,6 +748,7 @@ struct phy_device {
/* Written without phydev->lock, so not bitfields */
bool irq_suspended;
bool irq_rerun;
+ enum phy_irq_wake irq_wake;
/* Serializes phy_free_interrupt() against mdio_bus_phy_resume_irq() */
struct mutex irq_pm_lock;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
` (3 preceding siblings ...)
2026-11-11 23:48 ` [PATCH net v5 4/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
@ 2026-11-11 23:51 ` netdev-bot+sinfo
2026-11-11 23:55 ` Igor Velkov
2026-11-11 23:53 ` Igor Velkov
5 siblings, 1 reply; 9+ messages in thread
From: netdev-bot+sinfo @ 2026-11-11 23:51 UTC (permalink / raw)
To: Igor Velkov
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Chevallier,
Lukas Wunner, Rafael J. Wysocki, Wei Fang, Niklas Söderlund,
Paul Barker, Florian Fainelli, Doug Berger, Thangaraj Samynathan,
Shenwei Wang, Haoning Cheng, netdev, linux-arm-kernel,
linux-rockchip, linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by LLM and not proven at runtime). If it was triggered
please include the symptoms, like the stack trace or kernel messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
` (4 preceding siblings ...)
2026-11-11 23:51 ` [PATCH net v5 0/4] " netdev-bot+sinfo
@ 2026-11-11 23:53 ` Igor Velkov
5 siblings, 0 replies; 9+ messages in thread
From: Igor Velkov @ 2026-11-11 23:53 UTC (permalink / raw)
To: Haoning Cheng
Cc: Igor Velkov, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, netdev,
linux-arm-kernel, linux-rockchip, linux-kernel
Hi Haoning,
Thanks for testing v4. v5 changes patches 2-4 (freeing the interrupt,
a failed resume, the wakeup policy for MAC-managed PHYs), so I kept your
Tested-by on patch 1 only. Could you rerun your fec tests on v5?
Igor
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
2026-11-11 23:51 ` [PATCH net v5 0/4] " netdev-bot+sinfo
@ 2026-11-11 23:55 ` Igor Velkov
2026-11-12 19:17 ` Jakub Kicinski
0 siblings, 1 reply; 9+ messages in thread
From: Igor Velkov @ 2026-11-11 23:55 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: Igor Velkov, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Chevallier, Lukas Wunner, Rafael J. Wysocki, Wei Fang,
Niklas Söderlund, Paul Barker, Florian Fainelli,
Doug Berger, Thangaraj Samynathan, Shenwei Wang, Haoning Cheng,
netdev, linux-arm-kernel, linux-rockchip, linux-kernel
> - Whether the issue was actually triggered, or is only theoretical
Patch 4 fixes a hang seen on Helios64 (dwmac-rk, RTL8211F): in s2idle
without WoL the board hung or reset 10 of 10 times without the series.
The PHY IRQ thread stalls its CPU on an MDIO read while the GMAC clocks
are off, so that CPU never answers the NMI:
watchdog: CPU0: Watchdog detected hard LOCKUP on cpu 1
After 10 seconds, these CPUS still haven't responded to the NMI: 1
Patches 1-3 fix defects found by code inspection and Sashiko review;
they were not triggered.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM
2026-11-11 23:55 ` Igor Velkov
@ 2026-11-12 19:17 ` Jakub Kicinski
0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2026-11-12 19:17 UTC (permalink / raw)
To: Igor Velkov
Cc: netdev-bot+sinfo, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Paolo Abeni, Maxime Chevallier,
Lukas Wunner, Rafael J. Wysocki, Wei Fang, Niklas Söderlund,
Paul Barker, Florian Fainelli, Doug Berger, Thangaraj Samynathan,
Shenwei Wang, Haoning Cheng, netdev, linux-arm-kernel,
linux-rockchip, linux-kernel
On Thu, 12 Nov 2026 01:55:16 +0200 Igor Velkov wrote:
> Patch 4 fixes a hang seen on Helios64 (dwmac-rk, RTL8211F): in s2idle
> without WoL the board hung or reset 10 of 10 times without the series.
> The PHY IRQ thread stalls its CPU on an MDIO read while the GMAC clocks
> are off, so that CPU never answers the NMI:
>
> watchdog: CPU0: Watchdog detected hard LOCKUP on cpu 1
> After 10 seconds, these CPUS still haven't responded to the NMI: 1
>
> Patches 1-3 fix defects found by code inspection and Sashiko review;
> they were not triggered.
please remember to add this to the cover letter
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-11-12 19:17 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 23:48 [PATCH net v5 0/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 1/4] net: phy: move irq_suspended and irq_rerun out of the bitfield Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 2/4] net: phy: keep the line of a postponed PHY interrupt balanced Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 3/4] net: phy: stop postponing PHY interrupts when a PHY PM callback fails Igor Velkov via B4 Relay
2026-11-11 23:48 ` [PATCH net v5 4/4] net: phy: postpone PHY interrupts during sleep with MAC-managed PM Igor Velkov via B4 Relay
2026-11-11 23:51 ` [PATCH net v5 0/4] " netdev-bot+sinfo
2026-11-11 23:55 ` Igor Velkov
2026-11-12 19:17 ` Jakub Kicinski
2026-11-11 23:53 ` Igor Velkov
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®