sis190: RTNL and flush_scheduled_work deadlock
authorFrancois Romieu <romieu@fr.zoreil.com>
Thu, 15 Feb 2007 22:37:29 +0000 (23:37 +0100)
committerJeff Garzik <jeff@garzik.org>
Tue, 20 Feb 2007 16:18:12 +0000 (11:18 -0500)
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/sis190.c

index 45d91b1591001f67d0135b31765811345c69f396..b08508b358339131da79709561cd2a339746482e 100644 (file)
@@ -909,6 +909,9 @@ static void sis190_phy_task(struct work_struct *work)
 
        rtnl_lock();
 
+       if (!netif_running(dev))
+               goto out_unlock;
+
        val = mdio_read(ioaddr, phy_id, MII_BMCR);
        if (val & BMCR_RESET) {
                // FIXME: needlessly high ?  -- FR 02/07/2005
@@ -981,6 +984,7 @@ static void sis190_phy_task(struct work_struct *work)
                netif_carrier_on(dev);
        }
 
+out_unlock:
        rtnl_unlock();
 }
 
@@ -1102,8 +1106,6 @@ static void sis190_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       flush_scheduled_work();
-
        do {
                spin_lock_irq(&tp->lock);
 
@@ -1857,6 +1859,7 @@ static void __devexit sis190_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
 
        sis190_mii_remove(dev);
+       flush_scheduled_work();
        unregister_netdev(dev);
        sis190_release_board(pdev);
        pci_set_drvdata(pdev, NULL);