aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.c32
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl1.h10
2 files changed, 29 insertions, 13 deletions
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 93c92291da9..f17cecae59e 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2460,20 +2460,33 @@ static int atl1_rings_clean(struct napi_struct *napi, int budget)
2460 2460
2461 napi_complete(napi); 2461 napi_complete(napi);
2462 /* re-enable Interrupt */ 2462 /* re-enable Interrupt */
2463 iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); 2463 if (likely(adapter->int_enabled))
2464 atlx_imr_set(adapter, IMR_NORMAL_MASK);
2464 return work_done; 2465 return work_done;
2465} 2466}
2466 2467
2467static inline int atl1_sched_rings_clean(struct atl1_adapter* adapter) 2468static inline int atl1_sched_rings_clean(struct atl1_adapter* adapter)
2468{ 2469{
2469 if (likely(napi_schedule_prep(&adapter->napi))) { 2470 if (!napi_schedule_prep(&adapter->napi))
2470 __napi_schedule(&adapter->napi); 2471 /* It is possible in case even the RX/TX ints are disabled via IMR
2472 * register the ISR bits are set anyway (but do not produce IRQ).
2473 * To handle such situation the napi functions used to check is
2474 * something scheduled or not.
2475 */
2476 return 0;
2477
2478 __napi_schedule(&adapter->napi);
2479
2480 /*
2481 * Disable RX/TX ints via IMR register if it is
2482 * allowed. NAPI handler must reenable them in same
2483 * way.
2484 */
2485 if (!adapter->int_enabled)
2471 return 1; 2486 return 1;
2472 }
2473 2487
2474 dev_printk(KERN_ERR, &adapter->pdev->dev, 2488 atlx_imr_set(adapter, IMR_NORXTX_MASK);
2475 "rx: INTs must be disabled!"); 2489 return 1;
2476 return 0;
2477} 2490}
2478 2491
2479/* 2492/*
@@ -2538,8 +2551,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
2538 /* transmit or receive event */ 2551 /* transmit or receive event */
2539 if (status & (ISR_CMB_TX | ISR_CMB_RX) && 2552 if (status & (ISR_CMB_TX | ISR_CMB_RX) &&
2540 atl1_sched_rings_clean(adapter)) 2553 atl1_sched_rings_clean(adapter))
2541 /* Go away with INTs disabled */ 2554 break;
2542 return IRQ_HANDLED;
2543 2555
2544 /* rx exception */ 2556 /* rx exception */
2545 if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | 2557 if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN |
@@ -2551,7 +2563,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
2551 "rx exception, ISR = 0x%x\n", 2563 "rx exception, ISR = 0x%x\n",
2552 status); 2564 status);
2553 if (atl1_sched_rings_clean(adapter)) 2565 if (atl1_sched_rings_clean(adapter))
2554 return IRQ_HANDLED; 2566 break;
2555 } 2567 }
2556 2568
2557 if (--max_ints < 0) 2569 if (--max_ints < 0)
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h
index 117a0da360b..1cb658b2ff9 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.h
+++ b/drivers/net/ethernet/atheros/atlx/atl1.h
@@ -275,13 +275,17 @@ static u32 atl1_check_link(struct atl1_adapter *adapter);
275#define ISR_DIS_SMB 0x20000000 275#define ISR_DIS_SMB 0x20000000
276#define ISR_DIS_DMA 0x40000000 276#define ISR_DIS_DMA 0x40000000
277 277
278/* Normal Interrupt mask */ 278/* Normal Interrupt mask without RX/TX enabled */
279#define IMR_NORMAL_MASK (\ 279#define IMR_NORXTX_MASK (\
280 ISR_SMB |\ 280 ISR_SMB |\
281 ISR_GPHY |\ 281 ISR_GPHY |\
282 ISR_PHY_LINKDOWN|\ 282 ISR_PHY_LINKDOWN|\
283 ISR_DMAR_TO_RST |\ 283 ISR_DMAR_TO_RST |\
284 ISR_DMAW_TO_RST |\ 284 ISR_DMAW_TO_RST)
285
286/* Normal Interrupt mask */
287#define IMR_NORMAL_MASK (\
288 IMR_NORXTX_MASK |\
285 ISR_CMB_TX |\ 289 ISR_CMB_TX |\
286 ISR_CMB_RX) 290 ISR_CMB_RX)
287 291