aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000e/netdev.c
diff options
context:
space:
mode:
authorBenjamin Poirier <bpoirier@suse.com>2018-02-08 15:47:14 +0900
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-03-05 10:08:20 -0800
commit116f4a640b3197401bc93b8adc6c35040308ceff (patch)
tree23900b859d705a00642a20bbc86a8ffffb138618 /drivers/net/ethernet/intel/e1000e/netdev.c
parente1000e: Fix queue interrupt re-raising in Other interrupt (diff)
downloadlinux-dev-116f4a640b3197401bc93b8adc6c35040308ceff.tar.xz
linux-dev-116f4a640b3197401bc93b8adc6c35040308ceff.zip
e1000e: Avoid missed interrupts following ICR read
The 82574 specification update errata 12 states that interrupts may be missed if ICR is read while INT_ASSERTED is not set. Avoid that problem by setting all bits related to events that can trigger the Other interrupt in IMS. The Other interrupt is raised for such events regardless of whether or not they are set in IMS. However, only when they are set is the INT_ASSERTED bit also set in ICR. By doing this, we ensure that INT_ASSERTED is always set when we read ICR in e1000_msix_other() and steer clear of the errata. This also ensures that ICR will automatically be cleared on read, therefore we no longer need to clear bits explicitly. Signed-off-by: Benjamin Poirier <bpoirier@suse.com> Acked-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/netdev.c')
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 2c9609bee2ae..9fd4050a91ca 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -1914,16 +1914,12 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 icr;
-
- icr = er32(ICR);
- ew32(ICR, E1000_ICR_OTHER);
+ u32 icr = er32(ICR);
if (icr & adapter->eiac_mask)
ew32(ICS, (icr & adapter->eiac_mask));
if (icr & E1000_ICR_LSC) {
- ew32(ICR, E1000_ICR_LSC);
hw->mac.get_link_status = true;
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -1931,7 +1927,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
}
if (!test_bit(__E1000_DOWN, &adapter->state))
- ew32(IMS, E1000_IMS_OTHER);
+ ew32(IMS, E1000_IMS_OTHER | IMS_OTHER_MASK);
return IRQ_HANDLED;
}
@@ -2258,7 +2254,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
if (adapter->msix_entries) {
ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
- ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
+ ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER |
+ IMS_OTHER_MASK);
} else if (hw->mac.type >= e1000_pch_lpt) {
ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
} else {