Skip to content

Commit

Permalink
sky2: safer transmit timeout
Browse files Browse the repository at this point in the history
Rather than trying to be "smart" about possible transmit timeout
causes. Just clear all pending frames and reset the PHY.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Stephen Hemminger authored and Jeff Garzik committed Feb 7, 2007
1 parent 4a50a87 commit 62335ab
Showing 1 changed file with 15 additions and 26 deletions.
41 changes: 15 additions & 26 deletions drivers/net/sky2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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).
* Called with netif_tx_lock held.
*/
static void sky2_tx_timeout(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned txq = txqaddr[sky2->port];
u16 report, done;
u32 imask;

if (netif_msg_timer(sky2))
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",
dev->name,
sky2->tx_cons, sky2->tx_prod, report, done);

if (report != done) {
printk(KERN_INFO PFX "status burst pending (irq moderation?)\n");
dev->name, sky2->tx_cons, sky2->tx_prod,
sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));

sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
} else if (report != sky2->tx_cons) {
printk(KERN_INFO PFX "status report lost?\n");
imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */
sky2_write32(hw, B0_IMSK, 0);
sky2_read32(hw, B0_IMSK);

netif_tx_lock_bh(dev);
sky2_tx_complete(sky2, report);
netif_tx_unlock_bh(dev);
} else {
printk(KERN_INFO PFX "hardware hung? flushing\n");
netif_poll_disable(hw->dev[0]); /* stop NAPI poll */
synchronize_irq(hw->pdev->irq);

sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
netif_start_queue(dev); /* don't wakeup during flush */
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_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
}
sky2_phy_reinit(sky2); /* this clears flow control etc */
}

static int sky2_change_mtu(struct net_device *dev, int new_mtu)
Expand Down

0 comments on commit 62335ab

Please sign in to comment.