Skip to content

Commit 4aea7a5

Browse files
gobenjiJeff Kirsher
authored andcommitted
e1000e: Avoid receiver overrun interrupt bursts
When e1000e_poll() is not fast enough to keep up with incoming traffic, the adapter (when operating in msix mode) raises the Other interrupt to signal Receiver Overrun. This is a double problem because 1) at the moment e1000_msix_other() assumes that it is only called in case of Link Status Change and 2) if the condition persists, the interrupt is repeatedly raised again in quick succession. Ideally we would configure the Other interrupt to not be raised in case of receiver overrun but this doesn't seem possible on this adapter. Instead, we handle the first part of the problem by reverting to the practice of reading ICR in the other interrupt handler, like before commit 16ecba5 ("e1000e: Do not read ICR in Other interrupt"). Thanks to commit 0a8047a ("e1000e: Fix msi-x interrupt automask") which cleared IAME from CTRL_EXT, reading ICR doesn't interfere with RxQ0, TxQ0 interrupts anymore. We handle the second part of the problem by not re-enabling the Other interrupt right away when there is overrun. Instead, we wait until traffic subsides, napi polling mode is exited and interrupts are re-enabled. Reported-by: Lennart Sorensen <[email protected]> Fixes: 16ecba5 ("e1000e: Do not read ICR in Other interrupt") Signed-off-by: Benjamin Poirier <[email protected]> Tested-by: Aaron Brown <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 19110cf commit 4aea7a5

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

drivers/net/ethernet/intel/e1000e/defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@
398398
#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
399399
#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */
400400
#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
401+
#define E1000_ICR_RXO 0x00000040 /* Receiver Overrun */
401402
#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
402403
#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */
403404
/* If this bit asserted, the driver should claim the interrupt */

drivers/net/ethernet/intel/e1000e/netdev.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,14 +1910,30 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
19101910
struct net_device *netdev = data;
19111911
struct e1000_adapter *adapter = netdev_priv(netdev);
19121912
struct e1000_hw *hw = &adapter->hw;
1913+
u32 icr;
1914+
bool enable = true;
1915+
1916+
icr = er32(ICR);
1917+
if (icr & E1000_ICR_RXO) {
1918+
ew32(ICR, E1000_ICR_RXO);
1919+
enable = false;
1920+
/* napi poll will re-enable Other, make sure it runs */
1921+
if (napi_schedule_prep(&adapter->napi)) {
1922+
adapter->total_rx_bytes = 0;
1923+
adapter->total_rx_packets = 0;
1924+
__napi_schedule(&adapter->napi);
1925+
}
1926+
}
1927+
if (icr & E1000_ICR_LSC) {
1928+
ew32(ICR, E1000_ICR_LSC);
1929+
hw->mac.get_link_status = true;
1930+
/* guard against interrupt when we're going down */
1931+
if (!test_bit(__E1000_DOWN, &adapter->state))
1932+
mod_timer(&adapter->watchdog_timer, jiffies + 1);
1933+
}
19131934

1914-
hw->mac.get_link_status = true;
1915-
1916-
/* guard against interrupt when we're going down */
1917-
if (!test_bit(__E1000_DOWN, &adapter->state)) {
1918-
mod_timer(&adapter->watchdog_timer, jiffies + 1);
1935+
if (enable && !test_bit(__E1000_DOWN, &adapter->state))
19191936
ew32(IMS, E1000_IMS_OTHER);
1920-
}
19211937

19221938
return IRQ_HANDLED;
19231939
}
@@ -2687,7 +2703,8 @@ static int e1000e_poll(struct napi_struct *napi, int weight)
26872703
napi_complete_done(napi, work_done);
26882704
if (!test_bit(__E1000_DOWN, &adapter->state)) {
26892705
if (adapter->msix_entries)
2690-
ew32(IMS, adapter->rx_ring->ims_val);
2706+
ew32(IMS, adapter->rx_ring->ims_val |
2707+
E1000_IMS_OTHER);
26912708
else
26922709
e1000_irq_enable(adapter);
26932710
}
@@ -4204,7 +4221,7 @@ static void e1000e_trigger_lsc(struct e1000_adapter *adapter)
42044221
struct e1000_hw *hw = &adapter->hw;
42054222

42064223
if (adapter->msix_entries)
4207-
ew32(ICS, E1000_ICS_OTHER);
4224+
ew32(ICS, E1000_ICS_LSC | E1000_ICS_OTHER);
42084225
else
42094226
ew32(ICS, E1000_ICS_LSC);
42104227
}

0 commit comments

Comments
 (0)