aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-02-15 19:40:33 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-17 15:30:47 -0500
commit819067916d785cac0369b8d6e187b4a83fd17785 (patch)
tree565bd507b92755f2f75682a8b87fb96c506a2f5d /drivers/net
parentda4c1ff475d82585e3206f0270cb1ba55bcf3c74 (diff)
sky2: transmit timeout
The transmit timeout code could hang, and it would not clear out problems if the hardware was stuck. Change the code to effectively do a device down/up similar to the suspend/resume code. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sky2.c65
-rw-r--r--drivers/net/sky2.h1
2 files changed, 50 insertions, 16 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2c9118125b5e..fafa4021bb8a 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1866,16 +1866,13 @@ out:
1866 spin_unlock(&sky2->phy_lock); 1866 spin_unlock(&sky2->phy_lock);
1867} 1867}
1868 1868
1869
1870/* Transmit timeout is only called if we are running, carrier is up 1869/* Transmit timeout is only called if we are running, carrier is up
1871 * and tx queue is full (stopped). 1870 * and tx queue is full (stopped).
1872 * Called with netif_tx_lock held.
1873 */ 1871 */
1874static void sky2_tx_timeout(struct net_device *dev) 1872static void sky2_tx_timeout(struct net_device *dev)
1875{ 1873{
1876 struct sky2_port *sky2 = netdev_priv(dev); 1874 struct sky2_port *sky2 = netdev_priv(dev);
1877 struct sky2_hw *hw = sky2->hw; 1875 struct sky2_hw *hw = sky2->hw;
1878 u32 imask;
1879 1876
1880 if (netif_msg_timer(sky2)) 1877 if (netif_msg_timer(sky2))
1881 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); 1878 printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
@@ -1885,19 +1882,8 @@ static void sky2_tx_timeout(struct net_device *dev)
1885 sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), 1882 sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
1886 sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); 1883 sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE)));
1887 1884
1888 imask = sky2_read32(hw, B0_IMSK); /* block IRQ in hw */ 1885 /* can't restart safely under softirq */
1889 sky2_write32(hw, B0_IMSK, 0); 1886 schedule_work(&hw->restart_work);
1890 sky2_read32(hw, B0_IMSK);
1891
1892 netif_poll_disable(hw->dev[0]); /* stop NAPI poll */
1893 synchronize_irq(hw->pdev->irq);
1894
1895 netif_start_queue(dev); /* don't wakeup during flush */
1896 sky2_tx_complete(sky2, sky2->tx_prod); /* Flush transmit queue */
1897
1898 sky2_write32(hw, B0_IMSK, imask);
1899
1900 sky2_phy_reinit(sky2); /* this clears flow control etc */
1901} 1887}
1902 1888
1903static int sky2_change_mtu(struct net_device *dev, int new_mtu) 1889static int sky2_change_mtu(struct net_device *dev, int new_mtu)
@@ -2651,6 +2637,49 @@ static void sky2_reset(struct sky2_hw *hw)
2651 sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); 2637 sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
2652} 2638}
2653 2639
2640static void sky2_restart(struct work_struct *work)
2641{
2642 struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work);
2643 struct net_device *dev;
2644 int i, err;
2645
2646 dev_dbg(&hw->pdev->dev, "restarting\n");
2647
2648 del_timer_sync(&hw->idle_timer);
2649
2650 rtnl_lock();
2651 sky2_write32(hw, B0_IMSK, 0);
2652 sky2_read32(hw, B0_IMSK);
2653
2654 netif_poll_disable(hw->dev[0]);
2655
2656 for (i = 0; i < hw->ports; i++) {
2657 dev = hw->dev[i];
2658 if (netif_running(dev))
2659 sky2_down(dev);
2660 }
2661
2662 sky2_reset(hw);
2663 sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
2664 netif_poll_enable(hw->dev[0]);
2665
2666 for (i = 0; i < hw->ports; i++) {
2667 dev = hw->dev[i];
2668 if (netif_running(dev)) {
2669 err = sky2_up(dev);
2670 if (err) {
2671 printk(KERN_INFO PFX "%s: could not restart %d\n",
2672 dev->name, err);
2673 dev_close(dev);
2674 }
2675 }
2676 }
2677
2678 sky2_idle_start(hw);
2679
2680 rtnl_unlock();
2681}
2682
2654static inline u8 sky2_wol_supported(const struct sky2_hw *hw) 2683static inline u8 sky2_wol_supported(const struct sky2_hw *hw)
2655{ 2684{
2656 return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; 2685 return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0;
@@ -3613,6 +3642,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
3613 } 3642 }
3614 3643
3615 setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); 3644 setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
3645 INIT_WORK(&hw->restart_work, sky2_restart);
3646
3616 sky2_idle_start(hw); 3647 sky2_idle_start(hw);
3617 3648
3618 pci_set_drvdata(pdev, hw); 3649 pci_set_drvdata(pdev, hw);
@@ -3649,6 +3680,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
3649 3680
3650 del_timer_sync(&hw->idle_timer); 3681 del_timer_sync(&hw->idle_timer);
3651 3682
3683 flush_scheduled_work();
3684
3652 sky2_write32(hw, B0_IMSK, 0); 3685 sky2_write32(hw, B0_IMSK, 0);
3653 synchronize_irq(hw->pdev->irq); 3686 synchronize_irq(hw->pdev->irq);
3654 3687
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index cbca27abe105..ac24bdc42976 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1933,6 +1933,7 @@ struct sky2_hw {
1933 dma_addr_t st_dma; 1933 dma_addr_t st_dma;
1934 1934
1935 struct timer_list idle_timer; 1935 struct timer_list idle_timer;
1936 struct work_struct restart_work;
1936 int msi; 1937 int msi;
1937 wait_queue_head_t msi_wait; 1938 wait_queue_head_t msi_wait;
1938}; 1939};