summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2015-09-23 09:43:41 +0100
committerDavid S. Miller <davem@davemloft.net>2015-09-23 14:47:12 -0700
commitaaa0062ecf4877a26dea66bee1039c6eaf906c94 (patch)
tree905b388e3298f20a4ebe13808edaa50059851f5e /drivers
parent3c6cb3acee6a2350c79df29e1cfb56ad1c9a3e9e (diff)
downloadlinux-aaa0062ecf4877a26dea66bee1039c6eaf906c94.tar.bz2
8139cp: Do not re-enable RX interrupts in cp_tx_timeout()
If an RX interrupt was already received but NAPI has not yet run when the RX timeout happens, we end up in cp_tx_timeout() with RX interrupts already disabled. Blindly re-enabling them will cause an IRQ storm. (This is made particularly horrid by the fact that cp_interrupt() always returns that it's handled the interrupt, even when it hasn't actually done anything. If it didn't do that, the core IRQ code would have detected the storm and handled it, I'd have had a clear smoking gun backtrace instead of just a spontaneously resetting router, and I'd have at *least* two days of my life back. Changing the return value of cp_interrupt() will be argued about under separate cover.) Unconditionally leave RX interrupts disabled after the reset, and schedule NAPI to check the receive ring and re-enable them. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/realtek/8139cp.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index ba3dab721806..947932d4b79e 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -1262,9 +1262,10 @@ static void cp_tx_timeout(struct net_device *dev)
rc = cp_init_rings(cp);
cp_start_hw(cp);
__cp_set_rx_mode(dev);
- cp_enable_irq(cp);
+ cpw16_f(IntrMask, cp_norx_intr_mask);
netif_wake_queue(dev);
+ napi_schedule_irqoff(&cp->napi);
spin_unlock_irqrestore(&cp->lock, flags);
}