Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: ti: take into account all possible interrupt sources

The previous implementation of .handle_interrupt() did not take into
account the fact that all the interrupt status registers should be
acknowledged since multiple interrupt sources could be asserted.

Fix this by reading all the status registers before exiting with
IRQ_NONE or triggering the PHY state machine.

Fixes: 1d1ae3c6ca3f ("net: phy: ti: implement generic .handle_interrupt() callback")
Reported-by: Sven Schuchmann <schuchmann@schleissheimer.de>
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Link: https://lore.kernel.org/r/20210226153020.867852-1-ciorneiioana@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Ioana Ciornei and committed by
Jakub Kicinski
73f476aa 447621e3

+11 -9
+5 -4
drivers/net/phy/dp83822.c
··· 290 290 291 291 static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev) 292 292 { 293 + bool trigger_machine = false; 293 294 int irq_status; 294 295 295 296 /* The MISR1 and MISR2 registers are holding the interrupt status in ··· 306 305 return IRQ_NONE; 307 306 } 308 307 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 309 - goto trigger_machine; 308 + trigger_machine = true; 310 309 311 310 irq_status = phy_read(phydev, MII_DP83822_MISR2); 312 311 if (irq_status < 0) { ··· 314 313 return IRQ_NONE; 315 314 } 316 315 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 317 - goto trigger_machine; 316 + trigger_machine = true; 318 317 319 - return IRQ_NONE; 318 + if (!trigger_machine) 319 + return IRQ_NONE; 320 320 321 - trigger_machine: 322 321 phy_trigger_machine(phydev); 323 322 324 323 return IRQ_HANDLED;
+6 -5
drivers/net/phy/dp83tc811.c
··· 264 264 265 265 static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev) 266 266 { 267 + bool trigger_machine = false; 267 268 int irq_status; 268 269 269 270 /* The INT_STAT registers 1, 2 and 3 are holding the interrupt status ··· 280 279 return IRQ_NONE; 281 280 } 282 281 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 283 - goto trigger_machine; 282 + trigger_machine = true; 284 283 285 284 irq_status = phy_read(phydev, MII_DP83811_INT_STAT2); 286 285 if (irq_status < 0) { ··· 288 287 return IRQ_NONE; 289 288 } 290 289 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 291 - goto trigger_machine; 290 + trigger_machine = true; 292 291 293 292 irq_status = phy_read(phydev, MII_DP83811_INT_STAT3); 294 293 if (irq_status < 0) { ··· 296 295 return IRQ_NONE; 297 296 } 298 297 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 299 - goto trigger_machine; 298 + trigger_machine = true; 300 299 301 - return IRQ_NONE; 300 + if (!trigger_machine) 301 + return IRQ_NONE; 302 302 303 - trigger_machine: 304 303 phy_trigger_machine(phydev); 305 304 306 305 return IRQ_HANDLED;