Skip to content

Commit b336369

Browse files
Joshua Hokedavem330
authored andcommitted
macb: Don't re-enable interrupts while in polling mode
On a busy network, the macb driver could get stuck in the interrupt handler, quickly triggering the watchdog, due to a confluence of factors: 1. macb_poll re-enables interrupts unconditionally, even when it will be called again because it exhausted its rx budget 2. macb_interrupt only disables interrupts after scheduling macb_poll, but scheduling fails when macb_poll is already scheduled because it didn't call napi_complete 3. macb_interrupt loops until the interrupt status register is clear, which will never happen in this case if the driver doesn't disable the RX interrupt Since macb_interrupt runs in interrupt context, this effectively locks up the machine, triggering the hardware watchdog. This issue was readily reproducible on a flooded network with a modified 2.6.27.48 kernel. The same problem appears to still be in the 2.6.36-rc8 driver code, so I am submitting this patch against that version. I have not tested this version of the patch except to make sure the kernel compiles. Signed-off-by: Joshua Hoke <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c6ce2f4 commit b336369

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

drivers/net/macb.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -515,14 +515,15 @@ static int macb_poll(struct napi_struct *napi, int budget)
515515
(unsigned long)status, budget);
516516

517517
work_done = macb_rx(bp, budget);
518-
if (work_done < budget)
518+
if (work_done < budget) {
519519
napi_complete(napi);
520520

521-
/*
522-
* We've done what we can to clean the buffers. Make sure we
523-
* get notified when new packets arrive.
524-
*/
525-
macb_writel(bp, IER, MACB_RX_INT_FLAGS);
521+
/*
522+
* We've done what we can to clean the buffers. Make sure we
523+
* get notified when new packets arrive.
524+
*/
525+
macb_writel(bp, IER, MACB_RX_INT_FLAGS);
526+
}
526527

527528
/* TODO: Handle errors */
528529

@@ -550,12 +551,16 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
550551
}
551552

552553
if (status & MACB_RX_INT_FLAGS) {
554+
/*
555+
* There's no point taking any more interrupts
556+
* until we have processed the buffers. The
557+
* scheduling call may fail if the poll routine
558+
* is already scheduled, so disable interrupts
559+
* now.
560+
*/
561+
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
562+
553563
if (napi_schedule_prep(&bp->napi)) {
554-
/*
555-
* There's no point taking any more interrupts
556-
* until we have processed the buffers
557-
*/
558-
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
559564
dev_dbg(&bp->pdev->dev,
560565
"scheduling RX softirq\n");
561566
__napi_schedule(&bp->napi);

0 commit comments

Comments
 (0)