aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index ffe3aa7e2ab..ab36a7460a2 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1328,7 +1328,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1328 } 1328 }
1329 1329
1330 sky2->tx_cons = put; 1330 sky2->tx_cons = put;
1331 if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE) 1331 if (tx_avail(sky2) > MAX_SKB_TX_LE)
1332 netif_wake_queue(dev); 1332 netif_wake_queue(dev);
1333} 1333}
1334 1334
@@ -1651,17 +1651,40 @@ static void sky2_tx_timeout(struct net_device *dev)
1651 struct sky2_port *sky2 = netdev_priv(dev); 1651 struct sky2_port *sky2 = netdev_priv(dev);
1652 struct sky2_hw *hw = sky2->hw; 1652 struct sky2_hw *hw = sky2->hw;
1653 unsigned txq = txqaddr[sky2->port]; 1653 unsigned txq = txqaddr[sky2->port];
1654 u16 report, done;
1654 1655
1655 if (netif_msg_timer(sky2)) 1656 if (netif_msg_timer(sky2))
1656 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); 1657 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
1657 1658
1658 sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); 1659 report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
1659 sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); 1660 done = sky2_read16(hw, Q_ADDR(txq, Q_DONE));
1660 1661
1661 sky2_tx_clean(sky2); 1662 printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n",
1663 dev->name,
1664 sky2->tx_cons, sky2->tx_prod, report, done);
1665
1666 if (report != done) {
1667 printk(KERN_INFO PFX "status burst pending (irq moderation?)\n");
1668
1669 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
1670 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
1671 } else if (report != sky2->tx_cons) {
1672 printk(KERN_INFO PFX "status report lost?\n");
1662 1673
1663 sky2_qset(hw, txq); 1674 spin_lock_bh(&sky2->tx_lock);
1664 sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1); 1675 sky2_tx_complete(sky2, report);
1676 spin_unlock_bh(&sky2->tx_lock);
1677 } else {
1678 printk(KERN_INFO PFX "hardware hung? flushing\n");
1679
1680 sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
1681 sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
1682
1683 sky2_tx_clean(sky2);
1684
1685 sky2_qset(hw, txq);
1686 sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
1687 }
1665} 1688}
1666 1689
1667 1690
@@ -2097,6 +2120,8 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
2097 prefetch(&hw->st_le[hw->st_idx]); 2120 prefetch(&hw->st_le[hw->st_idx]);
2098 if (likely(__netif_rx_schedule_prep(dev0))) 2121 if (likely(__netif_rx_schedule_prep(dev0)))
2099 __netif_rx_schedule(dev0); 2122 __netif_rx_schedule(dev0);
2123 else
2124 printk(KERN_DEBUG PFX "irq race detected\n");
2100 2125
2101 return IRQ_HANDLED; 2126 return IRQ_HANDLED;
2102} 2127}