aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2009-03-25 22:05:41 +0000
committerDavid S. Miller <davem@davemloft.net>2009-03-26 01:09:59 -0700
commita3c69fef7a7775b0bcfbb8249845a25598cfe951 (patch)
tree1bed059e5df99f24dcb4479b3cc41cc0cc231708
parenta72d2b2cc63994cb8d592a004bf5331be6905814 (diff)
e1000e: fix close interrupt race
As noticed by Alan Cox, it is possible for e1000e to exit its interrupt handler or NAPI with interrupts enabled even when the driver is unloading or being configured administratively down. fix related to fix for: http://bugzilla.kernel.org/show_bug.cgi?id=12876 Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> CC: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/e1000e/netdev.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 17974121912..b4ae0465121 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -1261,7 +1261,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
u32 icr = er32(ICR);
if (!(icr & E1000_ICR_INT_ASSERTED)) {
- ew32(IMS, E1000_IMS_OTHER);
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+ ew32(IMS, E1000_IMS_OTHER);
return IRQ_NONE;
}
@@ -1278,7 +1279,8 @@ static irqreturn_t e1000_msix_other(int irq, void *data)
}
no_link_interrupt:
- ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
+ if (!test_bit(__E1000_DOWN, &adapter->state))
+ ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER);
return IRQ_HANDLED;
}
@@ -2015,10 +2017,12 @@ clean_rx:
if (adapter->itr_setting & 3)
e1000_set_itr(adapter);
napi_complete(napi);
- if (adapter->msix_entries)
- ew32(IMS, adapter->rx_ring->ims_val);
- else
- e1000_irq_enable(adapter);
+ if (!test_bit(__E1000_DOWN, &adapter->state)) {
+ if (adapter->msix_entries)
+ ew32(IMS, adapter->rx_ring->ims_val);
+ else
+ e1000_irq_enable(adapter);
+ }
}
return work_done;