提交 62335ab0 编写于 作者: S Stephen Hemminger 提交者: Jeff Garzik

sky2: safer transmit timeout

Rather than trying to be "smart" about possible transmit timeout
causes. Just clear all pending frames and reset the PHY.
Signed-off-by: NStephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 4a50a876
...@@ -1840,48 +1840,37 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) ...@@ -1840,48 +1840,37 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
} }
/* Transmit timeout is only called if we are running, carries is up /* Transmit timeout is only called if we are running, carrier is up
* and tx queue is full (stopped). * and tx queue is full (stopped).
* Called with netif_tx_lock held.
*/ */
static void sky2_tx_timeout(struct net_device *dev) static void sky2_tx_timeout(struct net_device *dev)
{ {
struct sky2_port *sky2 = netdev_priv(dev); struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw; struct sky2_hw *hw = sky2->hw;
unsigned txq = txqaddr[sky2->port]; u32 imask;
u16 report, done;
if (netif_msg_timer(sky2)) if (netif_msg_timer(sky2))
printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
done = sky2_read16(hw, Q_ADDR(txq, Q_DONE));
printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n",
dev->name, dev->name, sky2->tx_cons, sky2->tx_prod,
sky2->tx_cons, sky2->tx_prod, report, done); sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
if (report != done) {
printk(KERN_INFO PFX "status burst pending (irq moderation?)\n");
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); sky2_write32(hw, B0_IMSK, 0);
} else if (report != sky2->tx_cons) { sky2_read32(hw, B0_IMSK);
printk(KERN_INFO PFX "status report lost?\n");
netif_tx_lock_bh(dev); netif_poll_disable(hw->dev[0]); /* stop NAPI poll */
sky2_tx_complete(sky2, report); synchronize_irq(hw->pdev->irq);
netif_tx_unlock_bh(dev);
} else {
printk(KERN_INFO PFX "hardware hung? flushing\n");
sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); netif_start_queue(dev); /* don't wakeup during flush */
sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */
sky2_tx_clean(dev); sky2_write32(hw, B0_IMSK, imask);
sky2_qset(hw, txq); sky2_phy_reinit(sky2); /* this clears flow control etc */
sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
}
} }
static int sky2_change_mtu(struct net_device *dev, int new_mtu) static int sky2_change_mtu(struct net_device *dev, int new_mtu)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册