From: Stephen Hemminger Fix a hang on Yukon-EC (0xb6) rev 1 where suddenly no more interrupts were delivered. I don't know the real cause of the hang due to lack of docs, but the patch has been running stable for a few hours whereas the unmodified driver will hang after less than 2 minutes. Signed-off-by: Carl-Daniel Hailfinger Signed-off-by: Stephen Hemminger Signed-off-by: Andrew Morton --- drivers/net/sky2.c | 23 +++++++++++++++++------ 1 files changed, 17 insertions(+), 6 deletions(-) diff -puN drivers/net/sky2.c~sky2-fix-a-hang-on-yukon-ec-0xb6-rev-1 drivers/net/sky2.c --- devel/drivers/net/sky2.c~sky2-fix-a-hang-on-yukon-ec-0xb6-rev-1 2006-02-10 16:06:13.000000000 -0800 +++ devel-akpm/drivers/net/sky2.c 2006-02-10 16:06:13.000000000 -0800 @@ -1831,6 +1831,7 @@ static int sky2_poll(struct net_device * unsigned int work_done = 0; u16 hwidx; u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS }; + int done; sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); @@ -1913,25 +1914,35 @@ static int sky2_poll(struct net_device * } exit_loop: + + *budget -= work_done; + dev0->quota -= work_done; + sky2_tx_check(hw, 0, tx_done[0]); sky2_tx_check(hw, 1, tx_done[1]); - if (likely(work_done < to_do)) { + done = sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx; + if (done) { /* need to restart TX timer */ if (is_ec_a1(hw)) { sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); } + /* Kick status timer, it seems that status timer is not + * reset on clear?? + */ + if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_START) { + sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START); + } + netif_rx_complete(dev0); hw->intr_mask |= Y2_IS_STAT_BMU; sky2_write32(hw, B0_IMSK, hw->intr_mask); - return 0; - } else { - *budget -= work_done; - dev0->quota -= work_done; - return 1; } + + return !done; } static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) _