diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-31 15:59:37 +0300 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-31 15:59:37 +0300 |
commit | a15e0384dd22ee08f56d62761ce9d770488f6f4e (patch) | |
tree | 28c9fb9ad86295ca87f9bc6df6042727ddaf68c9 /drivers/net/8139too.c | |
parent | e2f2e58e7968f8446b1078a20a18bf8ea12b4fbc (diff) | |
download | linux-a15e0384dd22ee08f56d62761ce9d770488f6f4e.tar.xz |
[netdrvr 8139too] replace hand-crafted kernel thread with workqueue
Gone are the days when 8139too was a shining example of how to use
kernel threads. Delayed workqueues are easier, and map precisely to
our task: running code from a kernel thread, after a periodic sleep.
Diffstat (limited to 'drivers/net/8139too.c')
-rw-r--r-- | drivers/net/8139too.c | 87 |
1 files changed, 33 insertions, 54 deletions
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 30bee11c48bd..9de58e249bc3 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -590,12 +590,12 @@ struct rtl8139_private { spinlock_t lock; spinlock_t rx_lock; chip_t chipset; - pid_t thr_pid; - wait_queue_head_t thr_wait; - struct completion thr_exited; u32 rx_config; struct rtl_extra_stats xstats; - int time_to_die; + + 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; unsigned long fifo_copy_timeout; @@ -620,7 +620,7 @@ static int rtl8139_open (struct net_device *dev); static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, int val); -static void rtl8139_start_thread(struct net_device *dev); +static void rtl8139_start_thread(struct rtl8139_private *tp); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, @@ -637,6 +637,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev); static void rtl8139_set_rx_mode (struct net_device *dev); static void __set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); +static void rtl8139_thread (void *_data); static struct ethtool_ops rtl8139_ethtool_ops; /* write MMIO register, with flush */ @@ -1007,8 +1008,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); spin_lock_init (&tp->lock); spin_lock_init (&tp->rx_lock); - init_waitqueue_head (&tp->thr_wait); - init_completion (&tp->thr_exited); + INIT_WORK(&tp->thread, rtl8139_thread, dev); tp->mii.dev = dev; tp->mii.mdio_read = mdio_read; tp->mii.mdio_write = mdio_write; @@ -1345,7 +1345,7 @@ static int rtl8139_open (struct net_device *dev) dev->irq, RTL_R8 (MediaStatus), tp->mii.full_duplex ? "full" : "half"); - rtl8139_start_thread(dev); + rtl8139_start_thread(tp); return 0; } @@ -1594,56 +1594,45 @@ static inline void rtl8139_thread_iter (struct net_device *dev, RTL_R8 (Config1)); } -static int rtl8139_thread (void *data) +static void rtl8139_thread (void *_data) { - struct net_device *dev = data; + struct net_device *dev = _data; struct rtl8139_private *tp = netdev_priv(dev); - unsigned long timeout; - - daemonize("%s", dev->name); - allow_signal(SIGTERM); - - while (1) { - timeout = next_tick; - do { - timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); - /* make swsusp happy with our thread */ - try_to_freeze(); - } while (!signal_pending (current) && (timeout > 0)); - if (signal_pending (current)) { - flush_signals(current); - } - - if (tp->time_to_die) - break; - - if (rtnl_lock_interruptible ()) - break; + if ((tp->time_to_die == 0) && + (rtnl_lock_interruptible() == 0)) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); } - complete_and_exit (&tp->thr_exited, 0); + if (tp->time_to_die == 0) + schedule_delayed_work(&tp->thread, next_tick); } -static void rtl8139_start_thread(struct net_device *dev) +static void rtl8139_start_thread(struct rtl8139_private *tp) { - struct rtl8139_private *tp = netdev_priv(dev); - - tp->thr_pid = -1; tp->twistie = 0; - tp->time_to_die = 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->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); - if (tp->thr_pid < 0) { - printk (KERN_WARNING "%s: unable to start kernel thread\n", - dev->name); - } + tp->time_to_die = 0; + + 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(); } static inline void rtl8139_tx_clear (struct rtl8139_private *tp) @@ -2224,22 +2213,12 @@ static int rtl8139_close (struct net_device *dev) { struct rtl8139_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; unsigned long flags; netif_stop_queue (dev); - if (tp->thr_pid >= 0) { - tp->time_to_die = 1; - wmb(); - ret = kill_proc (tp->thr_pid, SIGTERM, 1); - if (ret) { - printk (KERN_ERR "%s: unable to signal thread\n", dev->name); - return ret; - } - wait_for_completion (&tp->thr_exited); - } - + rtl8139_stop_thread(tp); + if (netif_msg_ifdown(tp)) printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", dev->name, RTL_R16 (IntrStatus)); |