sky2: check for more work before leaving NAPI
authorStephen Hemminger <shemminger@linux-foundation.org>
Mon, 9 Jul 2007 22:33:36 +0000 (15:33 -0700)
committerJeff Garzik <jeff@garzik.org>
Tue, 10 Jul 2007 16:22:29 +0000 (12:22 -0400)
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>
drivers/net/sky2.c

index 90b1b970817853fd25fc6d14d92465a8859ce476..c8e51cf5af71847518c7fa745d3c048a31c8061a 100644 (file)
@@ -2477,8 +2477,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
 static int sky2_poll(struct net_device *dev0, int *budget)
 {
        struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
-       int work_limit = min(dev0->quota, *budget);
-       int work_done = 0;
+       int work_done;
        u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
        if (unlikely(status & Y2_IS_ERROR))
@@ -2490,25 +2489,25 @@ static int sky2_poll(struct net_device *dev0, int *budget)
        if (status & Y2_IS_IRQ_PHY2)
                sky2_phy_intr(hw, 1);
 
-       work_done = sky2_status_intr(hw, work_limit);
-       if (work_done < work_limit) {
-               /* Bug/Errata workaround?
-                * Need to kick the TX irq moderation timer.
-                */
-               if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
-                       sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
-                       sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
-               }
-               netif_rx_complete(dev0);
+       work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
+       *budget -= work_done;
+       dev0->quota -= work_done;
 
-               /* end of interrupt, re-enables also acts as I/O synchronization */
-               sky2_read32(hw, B0_Y2_SP_LISR);
-               return 0;
-       } else {
-               *budget -= work_done;
-               dev0->quota -= work_done;
+       /* More work? */
+       if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
                return 1;
+
+       /* Bug/Errata workaround?
+        * Need to kick the TX irq moderation timer.
+        */
+       if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+               sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+               sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
        }
+       netif_rx_complete(dev0);
+
+       sky2_read32(hw, B0_Y2_SP_LISR);
+       return 0;
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id)