aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorSathya Perla <sathya.perla@emulex.com>2013-01-11 17:47:02 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-12 18:33:01 -0500
commitd0b9cec3e27d0e9fda2fbf6aaacece68c99b1104 (patch)
tree5404dd2b246bf672e4e2a6fe7fd175b8ab4aa4bd /drivers/net/ethernet
parentdd38bd853082355641d0034aaf368e13ef2438f8 (diff)
be2net: fix unconditionally returning IRQ_HANDLED in INTx
commit e49cc34f introduced an unconditional IRQ_HANDLED return in be_intx() to workaround Lancer and BE2 HW issues. This is bad as it prevents the kernel from detecting interrupt storms due to broken HW. The BE2/Lancer HW issues are: 1) In Lancer, there is no means for the driver to detect if the interrupt belonged to device, other than counting and notifying events. 2) In Lancer de-asserting INTx takes a while, causing the INTx irq handler to be called multiple times till the de-assert happens. 3) In BE2, we see an occasional interrupt even when EQs are unarmed. Issue (1) can cause the notified events to be orphaned, if NAPI was already running. This patch fixes this issue by scheduling NAPI only if it is not scheduled already. Doing this also takes care of possible events_get() race that may be caused due to issue (2) and (3). Also, IRQ_HANDLED is returned only the first time zero events are detected. (Thanks Ben H. for the feedback and suggestions.) Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h1
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c29
2 files changed, 21 insertions, 9 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 3bc1912afba9..4eba17b83ba8 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -190,6 +190,7 @@ struct be_eq_obj {
190 190
191 u8 idx; /* array index */ 191 u8 idx; /* array index */
192 u16 tx_budget; 192 u16 tx_budget;
193 u16 spurious_intr;
193 struct napi_struct napi; 194 struct napi_struct napi;
194 struct be_adapter *adapter; 195 struct be_adapter *adapter;
195} ____cacheline_aligned_in_smp; 196} ____cacheline_aligned_in_smp;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9dca22be8125..5c995700e534 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev)
2026 struct be_adapter *adapter = eqo->adapter; 2026 struct be_adapter *adapter = eqo->adapter;
2027 int num_evts = 0; 2027 int num_evts = 0;
2028 2028
2029 /* On Lancer, clear-intr bit of the EQ DB does not work. 2029 /* IRQ is not expected when NAPI is scheduled as the EQ
2030 * INTx is de-asserted only on notifying num evts. 2030 * will not be armed.
2031 * But, this can happen on Lancer INTx where it takes
2032 * a while to de-assert INTx or in BE2 where occasionaly
2033 * an interrupt may be raised even when EQ is unarmed.
2034 * If NAPI is already scheduled, then counting & notifying
2035 * events will orphan them.
2031 */ 2036 */
2032 if (lancer_chip(adapter)) 2037 if (napi_schedule_prep(&eqo->napi)) {
2033 num_evts = events_get(eqo); 2038 num_evts = events_get(eqo);
2039 __napi_schedule(&eqo->napi);
2040 if (num_evts)
2041 eqo->spurious_intr = 0;
2042 }
2043 be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
2034 2044
2035 /* The EQ-notify may not de-assert INTx rightaway, causing 2045 /* Return IRQ_HANDLED only for the the first spurious intr
2036 * the ISR to be invoked again. So, return HANDLED even when 2046 * after a valid intr to stop the kernel from branding
2037 * num_evts is zero. 2047 * this irq as a bad one!
2038 */ 2048 */
2039 be_eq_notify(adapter, eqo->q.id, false, true, num_evts); 2049 if (num_evts || eqo->spurious_intr++ == 0)
2040 napi_schedule(&eqo->napi); 2050 return IRQ_HANDLED;
2041 return IRQ_HANDLED; 2051 else
2052 return IRQ_NONE;
2042} 2053}
2043 2054
2044static irqreturn_t be_msix(int irq, void *dev) 2055static irqreturn_t be_msix(int irq, void *dev)