Skip to content

Commit

Permalink
sky2: status irq hang fix
Browse files Browse the repository at this point in the history
The status interrupt flag should be cleared before processing,
not afterwards to avoid race. Need to process in poll routine
even if no new interrupt status. This is a normal occurrence when
more than 64 frames (NAPI weight) are processed in one poll routine.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
  • Loading branch information
Stephen Hemminger committed May 8, 2006
1 parent d324031 commit 1e5f128
Showing 1 changed file with 25 additions and 28 deletions.
53 changes: 25 additions & 28 deletions drivers/net/sky2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2105,45 +2105,42 @@ static int sky2_poll(struct net_device *dev0, int *budget)
int work_done = 0;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);

if (unlikely(status & ~Y2_IS_STAT_BMU)) {
if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw);
if (status & Y2_IS_HW_ERR)
sky2_hw_intr(hw);

if (status & Y2_IS_IRQ_PHY1)
sky2_phy_intr(hw, 0);
if (status & Y2_IS_IRQ_PHY1)
sky2_phy_intr(hw, 0);

if (status & Y2_IS_IRQ_PHY2)
sky2_phy_intr(hw, 1);
if (status & Y2_IS_IRQ_PHY2)
sky2_phy_intr(hw, 1);

if (status & Y2_IS_IRQ_MAC1)
sky2_mac_intr(hw, 0);
if (status & Y2_IS_IRQ_MAC1)
sky2_mac_intr(hw, 0);

if (status & Y2_IS_IRQ_MAC2)
sky2_mac_intr(hw, 1);
if (status & Y2_IS_IRQ_MAC2)
sky2_mac_intr(hw, 1);

if (status & Y2_IS_CHK_RX1)
sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
if (status & Y2_IS_CHK_RX1)
sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);

if (status & Y2_IS_CHK_RX2)
sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
if (status & Y2_IS_CHK_RX2)
sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);

if (status & Y2_IS_CHK_TXA1)
sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
if (status & Y2_IS_CHK_TXA1)
sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);

if (status & Y2_IS_CHK_TXA2)
sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
}
if (status & Y2_IS_CHK_TXA2)
sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);

if (status & Y2_IS_STAT_BMU) {
work_done = sky2_status_intr(hw, work_limit);
*budget -= work_done;
dev0->quota -= work_done;
if (status & Y2_IS_STAT_BMU)
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);

if (work_done >= work_limit)
return 1;
work_done = sky2_status_intr(hw, work_limit);
*budget -= work_done;
dev0->quota -= work_done;

sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
}
if (work_done >= work_limit)
return 1;

mod_timer(&hw->idle_timer, jiffies + HZ);

Expand Down

0 comments on commit 1e5f128

Please sign in to comment.