diff options
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 29 |
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 | ||
2044 | static irqreturn_t be_msix(int irq, void *dev) | 2055 | static irqreturn_t be_msix(int irq, void *dev) |