Skip to content

Commit 6d92ac9

Browse files
airtower-lunagregkh
authored andcommitted
net: phy: microchip: force IRQ polling mode for lan88xx
[ Upstream commit 30a41ed ] 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] raspberrypi/linux#2447 [2] https://forums.developer.nvidia.com/t/jetson-xavier-and-lan7800-problem/142134/11 Link: https://lore.kernel.org/[email protected] Fixes: 792aec4 ("add microchip LAN88xx phy driver") Signed-off-by: Fiona Klute <[email protected]> Cc: [email protected] Cc: [email protected] Reviewed-by: Andrew Lunn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent c7786ab commit 6d92ac9

File tree

1 file changed

+3
-43
lines changed

1 file changed

+3
-43
lines changed

drivers/net/phy/microchip.c

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -31,47 +31,6 @@ static int lan88xx_write_page(struct phy_device *phydev, int page)
3131
return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
3232
}
3333

34-
static int lan88xx_phy_config_intr(struct phy_device *phydev)
35-
{
36-
int rc;
37-
38-
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
39-
/* unmask all source and clear them before enable */
40-
rc = phy_write(phydev, LAN88XX_INT_MASK, 0x7FFF);
41-
rc = phy_read(phydev, LAN88XX_INT_STS);
42-
rc = phy_write(phydev, LAN88XX_INT_MASK,
43-
LAN88XX_INT_MASK_MDINTPIN_EN_ |
44-
LAN88XX_INT_MASK_LINK_CHANGE_);
45-
} else {
46-
rc = phy_write(phydev, LAN88XX_INT_MASK, 0);
47-
if (rc)
48-
return rc;
49-
50-
/* Ack interrupts after they have been disabled */
51-
rc = phy_read(phydev, LAN88XX_INT_STS);
52-
}
53-
54-
return rc < 0 ? rc : 0;
55-
}
56-
57-
static irqreturn_t lan88xx_handle_interrupt(struct phy_device *phydev)
58-
{
59-
int irq_status;
60-
61-
irq_status = phy_read(phydev, LAN88XX_INT_STS);
62-
if (irq_status < 0) {
63-
phy_error(phydev);
64-
return IRQ_NONE;
65-
}
66-
67-
if (!(irq_status & LAN88XX_INT_STS_LINK_CHANGE_))
68-
return IRQ_NONE;
69-
70-
phy_trigger_machine(phydev);
71-
72-
return IRQ_HANDLED;
73-
}
74-
7534
static int lan88xx_suspend(struct phy_device *phydev)
7635
{
7736
struct lan88xx_priv *priv = phydev->priv;
@@ -392,8 +351,9 @@ static struct phy_driver microchip_phy_driver[] = {
392351
.config_aneg = lan88xx_config_aneg,
393352
.link_change_notify = lan88xx_link_change_notify,
394353

395-
.config_intr = lan88xx_phy_config_intr,
396-
.handle_interrupt = lan88xx_handle_interrupt,
354+
/* Interrupt handling is broken, do not define related
355+
* functions to force polling.
356+
*/
397357

398358
.suspend = lan88xx_suspend,
399359
.resume = genphy_resume,

0 commit comments

Comments
 (0)