aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c41
1 files changed, 17 insertions, 24 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 4e569fa0f96c..0a3203465415 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2245,15 +2245,13 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
2245} 2245}
2246 2246
2247/* Process status response ring */ 2247/* Process status response ring */
2248static int sky2_status_intr(struct sky2_hw *hw, int to_do) 2248static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2249{ 2249{
2250 int work_done = 0; 2250 int work_done = 0;
2251 unsigned rx[2] = { 0, 0 }; 2251 unsigned rx[2] = { 0, 0 };
2252 u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
2253 2252
2254 rmb(); 2253 rmb();
2255 2254 do {
2256 while (hw->st_idx != hwidx) {
2257 struct sky2_port *sky2; 2255 struct sky2_port *sky2;
2258 struct sky2_status_le *le = hw->st_le + hw->st_idx; 2256 struct sky2_status_le *le = hw->st_le + hw->st_idx;
2259 unsigned port = le->css & CSS_LINK_BIT; 2257 unsigned port = le->css & CSS_LINK_BIT;
@@ -2364,7 +2362,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2364 printk(KERN_WARNING PFX 2362 printk(KERN_WARNING PFX
2365 "unknown status opcode 0x%x\n", le->opcode); 2363 "unknown status opcode 0x%x\n", le->opcode);
2366 } 2364 }
2367 } 2365 } while (hw->st_idx != idx);
2368 2366
2369 /* Fully processed status ring so clear irq */ 2367 /* Fully processed status ring so clear irq */
2370 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); 2368 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
@@ -2607,6 +2605,7 @@ static int sky2_poll(struct napi_struct *napi, int work_limit)
2607 struct sky2_hw *hw = container_of(napi, struct sky2_hw, napi); 2605 struct sky2_hw *hw = container_of(napi, struct sky2_hw, napi);
2608 u32 status = sky2_read32(hw, B0_Y2_SP_EISR); 2606 u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
2609 int work_done = 0; 2607 int work_done = 0;
2608 u16 idx;
2610 2609
2611 if (unlikely(status & Y2_IS_ERROR)) 2610 if (unlikely(status & Y2_IS_ERROR))
2612 sky2_err_intr(hw, status); 2611 sky2_err_intr(hw, status);
@@ -2617,29 +2616,23 @@ static int sky2_poll(struct napi_struct *napi, int work_limit)
2617 if (status & Y2_IS_IRQ_PHY2) 2616 if (status & Y2_IS_IRQ_PHY2)
2618 sky2_phy_intr(hw, 1); 2617 sky2_phy_intr(hw, 1);
2619 2618
2620 for(;;) { 2619 while ((idx = sky2_read16(hw, STAT_PUT_IDX)) != hw->st_idx) {
2621 work_done += sky2_status_intr(hw, work_limit); 2620 work_done += sky2_status_intr(hw, work_limit - work_done, idx);
2622 2621
2623 if (work_done >= work_limit) 2622 if (work_done >= work_limit)
2624 break; 2623 goto done;
2625 2624 }
2626 /* More work? */
2627 if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
2628 continue;
2629
2630 /* Bug/Errata workaround?
2631 * Need to kick the TX irq moderation timer.
2632 */
2633 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2634 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2635 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2636 }
2637
2638 napi_complete(napi);
2639 sky2_read32(hw, B0_Y2_SP_LISR);
2640 break;
2641 2625
2626 /* Bug/Errata workaround?
2627 * Need to kick the TX irq moderation timer.
2628 */
2629 if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
2630 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
2631 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
2642 } 2632 }
2633 napi_complete(napi);
2634 sky2_read32(hw, B0_Y2_SP_LISR);
2635done:
2643 2636
2644 return work_done; 2637 return work_done;
2645} 2638}