aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-07-09 18:33:36 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-10 12:22:29 -0400
commit5c11ce700f77fada15b6264417d72462da4bbb1c (patch)
treedef8f016cf2003c010c1ce31bc7e5df5b6ebf270
parent3cf267539f1f133eb6ba63d074da18cb58cdf89a (diff)
sky2: check for more work before leaving NAPI
This patch avoids generating another IRQ if more packets arrive while in the NAPI poll routine. Before marking device as finished, it rechecks that the status ring is empty. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/sky2.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 90b1b970817..c8e51cf5af7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2477,8 +2477,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
2477static int sky2_poll(struct net_device *dev0, int *budget) 2477static int sky2_poll(struct net_device *dev0, int *budget)
2478{ 2478{
2479 struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; 2479 struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
2480 int work_limit = min(dev0->quota, *budget); 2480 int work_done;
2481 int work_done = 0;
2482 u32 status = sky2_read32(hw, B0_Y2_SP_EISR); 2481 u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
2483 2482
2484 if (unlikely(status & Y2_IS_ERROR)) 2483 if (unlikely(status & Y2_IS_ERROR))
@@ -2490,25 +2489,25 @@ static int sky2_poll(struct net_device *dev0, int *budget)
2490 if (status & Y2_IS_IRQ_PHY2) 2489 if (status & Y2_IS_IRQ_PHY2)
2491 sky2_phy_intr(hw, 1); 2490 sky2_phy_intr(hw, 1);
2492 2491
2493 work_done = sky2_status_intr(hw, work_limit); 2492 work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
2494 if (work_done < work_limit) { 2493 *budget -= work_done;
2495 /* Bug/Errata workaround? 2494 dev0->quota -= work_done;
2496 * Need to kick the TX irq moderation timer.
2497 */
2498 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2499 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2500 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2501 }
2502 netif_rx_complete(dev0);
2503 2495
2504 /* end of interrupt, re-enables also acts as I/O synchronization */ 2496 /* More work? */
2505 sky2_read32(hw, B0_Y2_SP_LISR); 2497 if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
2506 return 0;
2507 } else {
2508 *budget -= work_done;
2509 dev0->quota -= work_done;
2510 return 1; 2498 return 1;
2499
2500 /* Bug/Errata workaround?
2501 * Need to kick the TX irq moderation timer.
2502 */
2503 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2504 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2505 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2511 } 2506 }
2507 netif_rx_complete(dev0);
2508
2509 sky2_read32(hw, B0_Y2_SP_LISR);
2510 return 0;
2512} 2511}
2513 2512
2514static irqreturn_t sky2_intr(int irq, void *dev_id) 2513static irqreturn_t sky2_intr(int irq, void *dev_id)