[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1442844109.7367.5.camel@infradead.org>
Date: Mon, 21 Sep 2015 15:01:49 +0100
From: David Woodhouse <dwmw2@...radead.org>
To: netdev@...r.kernel.org
Cc: romieu@...zoreil.com
Subject: [PATCH 1/7] 8139cp: Improve accuracy of cp_interrupt() return, to
survive IRQ storms
From: David Woodhouse <David.Woodhouse@...el.com>
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.Woodhouse@...el.com>
---
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.Woodhouse@...el.com Intel Corporation
Download attachment "smime.p7s" of type "application/x-pkcs7-signature" (5691 bytes)
Powered by blists - more mailing lists