| From stable-bounces@linux.kernel.org Thu Aug 16 07:05:07 2007 |
| From: Stephen Hemminger <shemminger@linux-foundation.org> |
| Date: Thu, 16 Aug 2007 09:12:47 -0400 |
| Subject: sky2: check for more work before leaving NAPI |
| To: stable@kernel.org |
| Cc: netdev@vger.kernel.org |
| Message-ID: <20070816131348.583665704@linux-foundation.org> |
| Content-Disposition: inline; filename=sky2-napi-fill.patch |
| |
| From: Stephen Hemminger <shemminger@linux-foundation.org> |
| |
| Backport of commit 5c11ce700f77fada15b6264417d72462da4bbb1c |
| |
| 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: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/net/sky2.c | 35 +++++++++++++++++------------------ |
| 1 file changed, 17 insertions(+), 18 deletions(-) |
| |
| --- a/drivers/net/sky2.c |
| +++ b/drivers/net/sky2.c |
| @@ -2428,8 +2428,7 @@ static void sky2_err_intr(struct sky2_hw |
| 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)) |
| @@ -2441,25 +2440,25 @@ static int sky2_poll(struct net_device * |
| 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) |