]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/r8169.c
r8169: RTNL and flush_scheduled_work deadlock
[linux-2.6-omap-h63xx.git] / drivers / net / r8169.c
index 148910025f74db080f0d62379304facbd7df6c6d..13cf06ee97f71389d82f591851be53a9deaac069 100644 (file)
@@ -1733,6 +1733,8 @@ rtl8169_remove_one(struct pci_dev *pdev)
        assert(dev != NULL);
        assert(tp != NULL);
 
+       flush_scheduled_work();
+
        unregister_netdev(dev);
        rtl8169_release_board(pdev, dev, tp->mmio_addr);
        pci_set_drvdata(pdev, NULL);
@@ -1882,7 +1884,6 @@ static void rtl8169_hw_start(struct net_device *dev)
            (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
            (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
            (tp->mac_version == RTL_GIGA_MAC_VER_04))
-               RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
                rtl8169_set_rx_tx_config_registers(tp);
 
        cmd = RTL_R16(CPlusCmd);
@@ -2017,7 +2018,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
        if (!skb)
                goto err_out;
 
-       skb_reserve(skb, (align - 1) & (u32)skb->data);
+       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
        *sk_buff = skb;
 
        mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
@@ -2162,10 +2163,13 @@ static void rtl8169_reinit_task(struct work_struct *work)
        struct net_device *dev = tp->dev;
        int ret;
 
-       if (netif_running(dev)) {
-               rtl8169_wait_for_quiescence(dev);
-               rtl8169_close(dev);
-       }
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
+       rtl8169_wait_for_quiescence(dev);
+       rtl8169_close(dev);
 
        ret = rtl8169_open(dev);
        if (unlikely(ret < 0)) {
@@ -2180,6 +2184,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
                }
                rtl8169_schedule_work(dev, rtl8169_reinit_task);
        }
+
+out_unlock:
+       rtnl_unlock();
 }
 
 static void rtl8169_reset_task(struct work_struct *work)
@@ -2188,8 +2195,10 @@ static void rtl8169_reset_task(struct work_struct *work)
                container_of(work, struct rtl8169_private, task.work);
        struct net_device *dev = tp->dev;
 
+       rtnl_lock();
+
        if (!netif_running(dev))
-               return;
+               goto out_unlock;
 
        rtl8169_wait_for_quiescence(dev);
 
@@ -2211,6 +2220,9 @@ static void rtl8169_reset_task(struct work_struct *work)
                }
                rtl8169_schedule_work(dev, rtl8169_reset_task);
        }
+
+out_unlock:
+       rtnl_unlock();
 }
 
 static void rtl8169_tx_timeout(struct net_device *dev)
@@ -2488,7 +2500,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
 
                skb = dev_alloc_skb(pkt_size + align);
                if (skb) {
-                       skb_reserve(skb, (align - 1) & (u32)skb->data);
+                       skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
                        eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
                        *sk_buff = skb;
                        rtl8169_mark_to_asic(desc, rx_buf_sz);
@@ -2723,8 +2735,6 @@ static void rtl8169_down(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       flush_scheduled_work();
-
 core_down:
        spin_lock_irq(&tp->lock);