FAILED: patch "[PATCH] net: phy: microchip: force IRQ polling mode for lan88xx" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 30a41ed32d3088cd0d682a13d7f30b23baed7e93
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025042824-quiver-could-ffa2@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 30a41ed32d3088cd0d682a13d7f30b23baed7e93 Mon Sep 17 00:00:00 2001
From: Fiona Klute <[email protected]>
Date: Wed, 16 Apr 2025 12:24:13 +0200
Subject: [PATCH] net: phy: microchip: force IRQ polling mode for lan88xx
With lan88xx based devices the lan78xx driver can get stuck in an interrupt loop while bringing the device up, flooding the kernel log with messages like the following:
lan78xx 2-3:1.0 enp1s0u3: kevent 4 may have been dropped
Removing interrupt support from the lan88xx PHY driver forces the driver to use polling instead, which avoids the problem.
The issue has been observed with Raspberry Pi devices at least since 4.14 (see [1], bug report for their downstream kernel), as well as with Nvidia devices [2] in 2020, where disabling interrupts was the vendor-suggested workaround (together with the claim that phylib changes in 4.9 made the interrupt handling in lan78xx incompatible).
Iperf reports well over 900Mbits/sec per direction with client in --dualtest mode, so there does not seem to be a significant impact on throughput (lan88xx device connected via switch to the peer).
[1] https://github.com/raspberrypi/linux/issues/2447
[2] https://forums.developer.nvidia.com/t/jetson-xavier-and-lan7800-problem/142134/11
drivers/net/phy/microchip.c +3 -43
@@ -37,47 +37,6 @@ static int lan88xx_write_page(struct phy_device *phydev, int page)return __phy_write (phydev,LAN88XX_EXT_PAGE_ACCESS , page); } -static int lan88xx_phy_config_intr (struct phy_device *phydev) -{ -int rc; - -if (phydev->interrupts ==PHY_INTERRUPT_ENABLED ) { -/* unmask all source and clear them before enable */ - rc =phy_write (phydev,LAN88XX_INT_MASK ,0x7FFF ); - rc =phy_read (phydev,LAN88XX_INT_STS ); - rc =phy_write (phydev,LAN88XX_INT_MASK , -LAN88XX_INT_MASK_MDINTPIN_EN_ | -LAN88XX_INT_MASK_LINK_CHANGE_ ); - }else { - rc =phy_write (phydev,LAN88XX_INT_MASK ,0 ); -if (rc) -return rc; - -/* Ack interrupts after they have been disabled */ - rc =phy_read (phydev,LAN88XX_INT_STS ); - } - -return rc <0 ? rc :0 ; -} - -static irqreturn_t lan88xx_handle_interrupt (struct phy_device *phydev) -{ -int irq_status; - - irq_status =phy_read (phydev,LAN88XX_INT_STS ); -if (irq_status <0 ) { -phy_error (phydev); -return IRQ_NONE ; - } - -if (!(irq_status &LAN88XX_INT_STS_LINK_CHANGE_ )) -return IRQ_NONE ; - -phy_trigger_machine (phydev); - -return IRQ_HANDLED ; -} -static int lan88xx_suspend (struct phy_device *phydev) {struct lan88xx_priv *priv = phydev->priv;
@@ -528,8 +487,9 @@ static struct phy_driver microchip_phy_driver[] = { .config_aneg = lan88xx_config_aneg, .link_change_notify = lan88xx_link_change_notify, - .config_intr = lan88xx_phy_config_intr, - .handle_interrupt = lan88xx_handle_interrupt, +/* Interrupt handling is broken, do not define related +* functions to force polling. +*/ .suspend = lan88xx_suspend, .resume = genphy_resume,
Sasha Levin
maintainerPATCH 1/3 net: phy: microchip: implement generic .handle_interrupt() callback
From: Ioana Ciornei <[email protected]>
[ Upstream commit e01a3feb8f69ab620b0016498603cad364f65224 ]
In an attempt to actually support shared IRQs in phylib, we now move the responsibility of triggering the phylib state machine or just returning IRQ_NONE, based on the IRQ status register, to the PHY driver. Having 3 different IRQ handling callbacks (.handle_interrupt(), .did_interrupt() and .ack_interrupt() ) is confusing so let the PHY driver implement directly an IRQ handler like any other device driver. Make this driver follow the new convention.
Stable-dep-of: 30a41ed32d30 ("net: phy: microchip: force IRQ polling mode for lan88xx")
--- drivers/net/phy/microchip.c | 19 +++++++++++++++++++ drivers/net/phy/microchip_t1.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+)
drivers/net/phy/microchip.c +19 -0
@@ -56,6 +56,24 @@ static int lan88xx_phy_ack_interrupt(struct phy_device *phydev)return rc <0 ? rc :0 ; } +static irqreturn_t lan88xx_handle_interrupt (struct phy_device *phydev) +{ +int irq_status; + + irq_status =phy_read (phydev,LAN88XX_INT_STS ); +if (irq_status <0 ) { +phy_error (phydev); +return IRQ_NONE ; + } + +if (!(irq_status &LAN88XX_INT_STS_LINK_CHANGE_ )) +return IRQ_NONE ; + +phy_trigger_machine (phydev); + +return IRQ_HANDLED ; +} +static int lan88xx_suspend (struct phy_device *phydev) {struct lan88xx_priv *priv = phydev->priv;
@@ -374,6 +392,7 @@ static struct phy_driver microchip_phy_driver[] = { .ack_interrupt = lan88xx_phy_ack_interrupt, .config_intr = lan88xx_phy_config_intr, + .handle_interrupt = lan88xx_handle_interrupt, .suspend = lan88xx_suspend, .resume = genphy_resume,
drivers/net/phy/microchip_t1.c +19 -0
@@ -203,6 +203,24 @@ static int lan87xx_phy_ack_interrupt(struct phy_device *phydev)return rc <0 ? rc :0 ; } +static irqreturn_t lan87xx_handle_interrupt (struct phy_device *phydev) +{ +int irq_status; + + irq_status =phy_read (phydev,LAN87XX_INTERRUPT_SOURCE ); +if (irq_status <0 ) { +phy_error (phydev); +return IRQ_NONE ; + } + +if (irq_status ==0 ) +return IRQ_NONE ; + +phy_trigger_machine (phydev); + +return IRQ_HANDLED ; +} +static int lan87xx_config_init (struct phy_device *phydev) {int rc =lan87xx_phy_init (phydev);
@@ -223,6 +241,7 @@ static struct phy_driver microchip_t1_phy_driver[] = { .ack_interrupt = lan87xx_phy_ack_interrupt, .config_intr = lan87xx_phy_config_intr, + .handle_interrupt = lan87xx_handle_interrupt, .suspend = genphy_suspend, .resume = genphy_resume,
Signature · 1 line
2.50.1
Sasha Levin
maintainerPATCH 2/3 net: phy: microchip: remove the use of .ack_interrupt()
From: Ioana Ciornei <[email protected]>
[ Upstream commit cf499391982d877e9313d2adeedcf5f1ffe05d6e ]
In preparation of removing the .ack_interrupt() callback, we must replace its occurrences (aka phy_clear_interrupt), from the 2 places where it is called from (phy_enable_interrupts and phy_disable_interrupts), with equivalent functionality.
This means that clearing interrupts now becomes something that the PHY driver is responsible of doing, before enabling interrupts and after clearing them. Make this driver follow the new contract.
Stable-dep-of: 30a41ed32d30 ("net: phy: microchip: force IRQ polling mode for lan88xx")
--- drivers/net/phy/microchip.c | 13 +++++-------- drivers/net/phy/microchip_t1.c | 17 +++++++---------- 2 files changed, 12 insertions(+), 18 deletions(-)
drivers/net/phy/microchip.c +5 -8
@@ -44,14 +44,12 @@ static int lan88xx_phy_config_intr(struct phy_device *phydev) LAN88XX_INT_MASK_LINK_CHANGE_); }else { rc =phy_write (phydev,LAN88XX_INT_MASK ,0 ); - } - -return rc <0 ? rc :0 ; -} +if (rc) +return rc; -static int lan88xx_phy_ack_interrupt (struct phy_device *phydev) -{ -int rc =phy_read (phydev,LAN88XX_INT_STS ); +/* Ack interrupts after they have been disabled */ + rc =phy_read (phydev,LAN88XX_INT_STS ); + }return rc <0 ? rc :0 ; }
@@ -390,7 +388,6 @@ static struct phy_driver microchip_phy_driver[] = { .config_aneg = lan88xx_config_aneg, .link_change_notify = lan88xx_link_change_notify, - .ack_interrupt = lan88xx_phy_ack_interrupt, .config_intr = lan88xx_phy_config_intr, .handle_interrupt = lan88xx_handle_interrupt,
drivers/net/phy/microchip_t1.c +7 -10
@@ -189,16 +189,14 @@ static int lan87xx_phy_config_intr(struct phy_device *phydev) rc =phy_write (phydev,LAN87XX_INTERRUPT_MASK ,0x7FFF ); rc =phy_read (phydev,LAN87XX_INTERRUPT_SOURCE ); val =LAN87XX_MASK_LINK_UP |LAN87XX_MASK_LINK_DOWN ; - } - - rc =phy_write (phydev,LAN87XX_INTERRUPT_MASK , val); - -return rc <0 ? rc :0 ; -} + rc =phy_write (phydev,LAN87XX_INTERRUPT_MASK , val); + }else { + rc =phy_write (phydev,LAN87XX_INTERRUPT_MASK , val); +if (rc) +return rc; -static int lan87xx_phy_ack_interrupt (struct phy_device *phydev) -{ -int rc =phy_read (phydev,LAN87XX_INTERRUPT_SOURCE ); + rc =phy_read (phydev,LAN87XX_INTERRUPT_SOURCE ); + }return rc <0 ? rc :0 ; }
@@ -239,7 +237,6 @@ static struct phy_driver microchip_t1_phy_driver[] = { .config_init = lan87xx_config_init, .config_aneg = genphy_config_aneg, - .ack_interrupt = lan87xx_phy_ack_interrupt, .config_intr = lan87xx_phy_config_intr, .handle_interrupt = lan87xx_handle_interrupt,
Signature · 1 line
2.50.1
Sasha Levin
maintainerPATCH 3/3 net: phy: microchip: force IRQ polling mode for lan88xx
In reply to Sasha LevinFrom: Fiona Klute <[email protected]>
[ Upstream commit 30a41ed32d3088cd0d682a13d7f30b23baed7e93 ]
With lan88xx based devices the lan78xx driver can get stuck in an interrupt loop while bringing the device up, flooding the kernel log with messages like the following:
lan78xx 2-3:1.0 enp1s0u3: kevent 4 may have been dropped
Removing interrupt support from the lan88xx PHY driver forces the driver to use polling instead, which avoids the problem.
The issue has been observed with Raspberry Pi devices at least since 4.14 (see [1], bug report for their downstream kernel), as well as with Nvidia devices [2] in 2020, where disabling interrupts was the vendor-suggested workaround (together with the claim that phylib changes in 4.9 made the interrupt handling in lan78xx incompatible).
Iperf reports well over 900Mbits/sec per direction with client in --dualtest mode, so there does not seem to be a significant impact on throughput (lan88xx device connected via switch to the peer).
[1] https://github.com/raspberrypi/linux/issues/2447
[2] https://forums.developer.nvidia.com/t/jetson-xavier-and-lan7800-problem/142134/11
--- drivers/net/phy/microchip.c | 46 +++---------------------------------- 1 file changed, 3 insertions(+), 43 deletions(-)
drivers/net/phy/microchip.c +3 -43
@@ -31,47 +31,6 @@ static int lan88xx_write_page(struct phy_device *phydev, int page)return __phy_write (phydev,LAN88XX_EXT_PAGE_ACCESS , page); } -static int lan88xx_phy_config_intr (struct phy_device *phydev) -{ -int rc; - -if (phydev->interrupts ==PHY_INTERRUPT_ENABLED ) { -/* unmask all source and clear them before enable */ - rc =phy_write (phydev,LAN88XX_INT_MASK ,0x7FFF ); - rc =phy_read (phydev,LAN88XX_INT_STS ); - rc =phy_write (phydev,LAN88XX_INT_MASK , -LAN88XX_INT_MASK_MDINTPIN_EN_ | -LAN88XX_INT_MASK_LINK_CHANGE_ ); - }else { - rc =phy_write (phydev,LAN88XX_INT_MASK ,0 ); -if (rc) -return rc; - -/* Ack interrupts after they have been disabled */ - rc =phy_read (phydev,LAN88XX_INT_STS ); - } - -return rc <0 ? rc :0 ; -} - -static irqreturn_t lan88xx_handle_interrupt (struct phy_device *phydev) -{ -int irq_status; - - irq_status =phy_read (phydev,LAN88XX_INT_STS ); -if (irq_status <0 ) { -phy_error (phydev); -return IRQ_NONE ; - } - -if (!(irq_status &LAN88XX_INT_STS_LINK_CHANGE_ )) -return IRQ_NONE ; - -phy_trigger_machine (phydev); - -return IRQ_HANDLED ; -} -static int lan88xx_suspend (struct phy_device *phydev) {struct lan88xx_priv *priv = phydev->priv;
@@ -388,8 +347,9 @@ static struct phy_driver microchip_phy_driver[] = { .config_aneg = lan88xx_config_aneg, .link_change_notify = lan88xx_link_change_notify, - .config_intr = lan88xx_phy_config_intr, - .handle_interrupt = lan88xx_handle_interrupt, +/* Interrupt handling is broken, do not define related +* functions to force polling. +*/ .suspend = lan88xx_suspend, .resume = genphy_resume,
Signature · 1 line
2.50.1