diff options
-rw-r--r-- | drivers/net/sky2.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ffe3aa7e2ab2..ab36a7460a26 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 | } |