Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[powerpc.git] / drivers / net / 8139too.c
index 9de58e2..adfba44 100644 (file)
@@ -505,7 +505,7 @@ enum chip_flags {
 #define HW_REVID_MASK  HW_REVID(1, 1, 1, 1, 1, 1, 1)
 
 /* directly indexed by chip_t, above */
-const static struct {
+static const struct {
        const char *name;
        u32 version; /* from RTL8139C/RTL8139D docs */
        u32 flags;
@@ -586,7 +586,8 @@ struct rtl8139_private {
        dma_addr_t tx_bufs_dma;
        signed char phys[4];            /* MII device addresses. */
        char twistie, twist_row, twist_col;     /* Twister tune state. */
-       unsigned int default_port:4;    /* Last dev->if_port value. */
+       unsigned int default_port : 4;  /* Last dev->if_port value. */
+       unsigned int have_thread : 1;
        spinlock_t lock;
        spinlock_t rx_lock;
        chip_t chipset;
@@ -594,7 +595,6 @@ struct rtl8139_private {
        struct rtl_extra_stats xstats;
 
        struct work_struct thread;
-       long time_to_die;       /* -1 no thr, 0 thr active, 1 thr cancel */
 
        struct mii_if_info mii;
        unsigned int regs_len;
@@ -1598,41 +1598,40 @@ static void rtl8139_thread (void *_data)
 {
        struct net_device *dev = _data;
        struct rtl8139_private *tp = netdev_priv(dev);
+       unsigned long thr_delay;
 
-       if ((tp->time_to_die == 0) &&
-           (rtnl_lock_interruptible() == 0)) {
+       if (rtnl_shlock_nowait() == 0) {
                rtl8139_thread_iter (dev, tp, tp->mmio_addr);
                rtnl_unlock ();
+
+               thr_delay = next_tick;
+       } else {
+               /* unlikely race.  mitigate with fast poll. */
+               thr_delay = HZ / 2;
        }
 
-       if (tp->time_to_die == 0)
-               schedule_delayed_work(&tp->thread, next_tick);
+       schedule_delayed_work(&tp->thread, thr_delay);
 }
 
 static void rtl8139_start_thread(struct rtl8139_private *tp)
 {
        tp->twistie = 0;
-       tp->time_to_die = -1;
        if (tp->chipset == CH_8139_K)
                tp->twistie = 1;
        else if (tp->drv_flags & HAS_LNK_CHNG)
                return;
 
-       tp->time_to_die = 0;
+       tp->have_thread = 1;
 
        schedule_delayed_work(&tp->thread, next_tick);
 }
 
 static void rtl8139_stop_thread(struct rtl8139_private *tp)
 {
-       if (tp->time_to_die < 0)
-               return;
-
-       tp->time_to_die = 1;
-       wmb();
-
-       if (cancel_delayed_work(&tp->thread) == 0)
-               flush_scheduled_work();
+       if (tp->have_thread) {
+               cancel_rearming_delayed_work(&tp->thread);
+               tp->have_thread = 0;
+       }
 }
 
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)