The TX timeout handling has been observed to trigger RX IRQ storms. And since cp_interrupt() just keeps saying that it handled the interrupt, the machine then dies. Fix the return value from cp_interrupt(), and the offending IRQ gets disabled and the machine survives.
Signed-off-by: David Woodhouse <david.woodho...@intel.com> --- ... and I have to make fewer trips to the cupboard under the stairs. There follows a fix to prevent the IRQ storm from happening at all. drivers/net/ethernet/realtek/8139cp.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index ba3dab7..f1054ad 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -371,7 +371,7 @@ struct cp_private { static void __cp_set_rx_mode (struct net_device *dev); -static void cp_tx (struct cp_private *cp); +static int cp_tx (struct cp_private *cp); static void cp_clean_rings (struct cp_private *cp); #ifdef CONFIG_NET_POLL_CONTROLLER static void cp_poll_controller(struct net_device *dev); @@ -587,8 +587,6 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) if (!status || (status == 0xFFFF)) goto out_unlock; - handled = 1; - netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n", status, cpr8(Cmd), cpr16(CpCmd)); @@ -596,25 +594,30 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) /* close possible race's with dev_close */ if (unlikely(!netif_running(dev))) { + handled = 1; cpw16(IntrMask, 0); goto out_unlock; } - if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) + if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) { if (napi_schedule_prep(&cp->napi)) { + handled = 1; cpw16_f(IntrMask, cp_norx_intr_mask); __napi_schedule(&cp->napi); } - + } if (status & (TxOK | TxErr | TxEmpty | SWInt)) - cp_tx(cp); - if (status & LinkChg) - mii_check_media(&cp->mii_if, netif_msg_link(cp), false); + handled |= cp_tx(cp); + if (status & LinkChg) { + handled = 1; + mii_check_media(&cp->mii_if, netif_msg_link(cp), false); + } if (status & PciErr) { u16 pci_status; + handled = 1; pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status); pci_write_config_word(cp->pdev, PCI_STATUS, pci_status); netdev_err(dev, "PCI bus error, status=%04x, PCI status=%04x\n", @@ -645,11 +648,12 @@ static void cp_poll_controller(struct net_device *dev) } #endif -static void cp_tx (struct cp_private *cp) +static int cp_tx (struct cp_private *cp) { unsigned tx_head = cp->tx_head; unsigned tx_tail = cp->tx_tail; unsigned bytes_compl = 0, pkts_compl = 0; + int handled = 0; while (tx_tail != tx_head) { struct cp_desc *txd = cp->tx_ring + tx_tail; @@ -661,6 +665,7 @@ static void cp_tx (struct cp_private *cp) if (status & DescOwn) break; + handled = 1; skb = cp->tx_skb[tx_tail]; BUG_ON(!skb); @@ -704,6 +709,8 @@ static void cp_tx (struct cp_private *cp) netdev_completed_queue(cp->dev, pkts_compl, bytes_compl); if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1)) netif_wake_queue(cp->dev); + + return handled; } static inline u32 cp_tx_vlan_tag(struct sk_buff *skb) -- 2.4.3 -- David Woodhouse Open Source Technology Centre david.woodho...@intel.com Intel Corporation
smime.p7s
Description: S/MIME cryptographic signature