aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-02-06 13:45:42 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-07 18:50:44 -0500
commit62335ab013d9eaef502bd402eb2eb72e8cff58f1 (patch)
tree0b8fbb6019b4e3002a9d7e64838b04761376d2ba /drivers
parent4a50a876ac325a45de1b582571c1248648801b52 (diff)
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: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sky2.c41
1 files changed, 15 insertions, 26 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index e97dc299b563..c96362dae800 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1840,48 +1840,37 @@ out:
1840} 1840}
1841 1841
1842 1842
1843/* Transmit timeout is only called if we are running, carries is up 1843/* Transmit timeout is only called if we are running, carrier is up
1844 * and tx queue is full (stopped). 1844 * and tx queue is full (stopped).
1845 * Called with netif_tx_lock held.
1845 */ 1846 */
1846static void sky2_tx_timeout(struct net_device *dev) 1847static void sky2_tx_timeout(struct net_device *dev)
1847{ 1848{
1848 struct sky2_port *sky2 = netdev_priv(dev); 1849 struct sky2_port *sky2 = netdev_priv(dev);
1849 struct sky2_hw *hw = sky2->hw; 1850 struct sky2_hw *hw = sky2->hw;
1850 unsigned txq = txqaddr[sky2->port]; 1851 u32 imask;
1851 u16 report, done;
1852 1852
1853 if (netif_msg_timer(sky2)) 1853 if (netif_msg_timer(sky2))
1854 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); 1854 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
1855 1855
1856 report = sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
1857 done = sky2_read16(hw, Q_ADDR(txq, Q_DONE));
1858
1859 printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", 1856 printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n",
1860 dev->name, 1857 dev->name, sky2->tx_cons, sky2->tx_prod,
1861 sky2->tx_cons, sky2->tx_prod, report, done); 1858 sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
1862 1859 sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
1863 if (report != done) {
1864 printk(KERN_INFO PFX "status burst pending (irq moderation?)\n");
1865 1860
1866 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); 1861 imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */
1867 sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); 1862 sky2_write32(hw, B0_IMSK, 0);
1868 } else if (report != sky2->tx_cons) { 1863 sky2_read32(hw, B0_IMSK);
1869 printk(KERN_INFO PFX "status report lost?\n");
1870 1864
1871 netif_tx_lock_bh(dev); 1865 netif_poll_disable(hw->dev[0]); /* stop NAPI poll */
1872 sky2_tx_complete(sky2, report); 1866 synchronize_irq(hw->pdev->irq);
1873 netif_tx_unlock_bh(dev);
1874 } else {
1875 printk(KERN_INFO PFX "hardware hung? flushing\n");
1876 1867
1877 sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP); 1868 netif_start_queue(dev); /* don't wakeup during flush */
1878 sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET); 1869 sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */
1879 1870
1880 sky2_tx_clean(dev); 1871 sky2_write32(hw, B0_IMSK, imask);
1881 1872
1882 sky2_qset(hw, txq); 1873 sky2_phy_reinit(sky2); /* this clears flow control etc */
1883 sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
1884 }
1885} 1874}
1886 1875
1887static int sky2_change_mtu(struct net_device *dev, int new_mtu) 1876static int sky2_change_mtu(struct net_device *dev, int new_mtu)