diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-31 07:59:37 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-31 07:59:37 -0500 |
commit | a15e0384dd22ee08f56d62761ce9d770488f6f4e (patch) | |
tree | 28c9fb9ad86295ca87f9bc6df6042727ddaf68c9 /drivers/net/8139too.c | |
parent | e2f2e58e7968f8446b1078a20a18bf8ea12b4fbc (diff) |
[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 { | |||
590 | spinlock_t lock; | 590 | spinlock_t lock; |
591 | spinlock_t rx_lock; | 591 | spinlock_t rx_lock; |
592 | chip_t chipset; | 592 | chip_t chipset; |
593 | pid_t thr_pid; | ||
594 | wait_queue_head_t thr_wait; | ||
595 | struct completion thr_exited; | ||
596 | u32 rx_config; | 593 | u32 rx_config; |
597 | struct rtl_extra_stats xstats; | 594 | struct rtl_extra_stats xstats; |
598 | int time_to_die; | 595 | |
596 | struct work_struct thread; | ||
597 | long time_to_die; /* -1 no thr, 0 thr active, 1 thr cancel */ | ||
598 | |||
599 | struct mii_if_info mii; | 599 | struct mii_if_info mii; |
600 | unsigned int regs_len; | 600 | unsigned int regs_len; |
601 | unsigned long fifo_copy_timeout; | 601 | unsigned long fifo_copy_timeout; |
@@ -620,7 +620,7 @@ static int rtl8139_open (struct net_device *dev); | |||
620 | static int mdio_read (struct net_device *dev, int phy_id, int location); | 620 | static int mdio_read (struct net_device *dev, int phy_id, int location); |
621 | static void mdio_write (struct net_device *dev, int phy_id, int location, | 621 | static void mdio_write (struct net_device *dev, int phy_id, int location, |
622 | int val); | 622 | int val); |
623 | static void rtl8139_start_thread(struct net_device *dev); | 623 | static void rtl8139_start_thread(struct rtl8139_private *tp); |
624 | static void rtl8139_tx_timeout (struct net_device *dev); | 624 | static void rtl8139_tx_timeout (struct net_device *dev); |
625 | static void rtl8139_init_ring (struct net_device *dev); | 625 | static void rtl8139_init_ring (struct net_device *dev); |
626 | static int rtl8139_start_xmit (struct sk_buff *skb, | 626 | 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); | |||
637 | static void rtl8139_set_rx_mode (struct net_device *dev); | 637 | static void rtl8139_set_rx_mode (struct net_device *dev); |
638 | static void __set_rx_mode (struct net_device *dev); | 638 | static void __set_rx_mode (struct net_device *dev); |
639 | static void rtl8139_hw_start (struct net_device *dev); | 639 | static void rtl8139_hw_start (struct net_device *dev); |
640 | static void rtl8139_thread (void *_data); | ||
640 | static struct ethtool_ops rtl8139_ethtool_ops; | 641 | static struct ethtool_ops rtl8139_ethtool_ops; |
641 | 642 | ||
642 | /* write MMIO register, with flush */ | 643 | /* write MMIO register, with flush */ |
@@ -1007,8 +1008,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, | |||
1007 | (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); | 1008 | (debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1)); |
1008 | spin_lock_init (&tp->lock); | 1009 | spin_lock_init (&tp->lock); |
1009 | spin_lock_init (&tp->rx_lock); | 1010 | spin_lock_init (&tp->rx_lock); |
1010 | init_waitqueue_head (&tp->thr_wait); | 1011 | INIT_WORK(&tp->thread, rtl8139_thread, dev); |
1011 | init_completion (&tp->thr_exited); | ||
1012 | tp->mii.dev = dev; | 1012 | tp->mii.dev = dev; |
1013 | tp->mii.mdio_read = mdio_read; | 1013 | tp->mii.mdio_read = mdio_read; |
1014 | tp->mii.mdio_write = mdio_write; | 1014 | tp->mii.mdio_write = mdio_write; |
@@ -1345,7 +1345,7 @@ static int rtl8139_open (struct net_device *dev) | |||
1345 | dev->irq, RTL_R8 (MediaStatus), | 1345 | dev->irq, RTL_R8 (MediaStatus), |
1346 | tp->mii.full_duplex ? "full" : "half"); | 1346 | tp->mii.full_duplex ? "full" : "half"); |
1347 | 1347 | ||
1348 | rtl8139_start_thread(dev); | 1348 | rtl8139_start_thread(tp); |
1349 | 1349 | ||
1350 | return 0; | 1350 | return 0; |
1351 | } | 1351 | } |
@@ -1594,56 +1594,45 @@ static inline void rtl8139_thread_iter (struct net_device *dev, | |||
1594 | RTL_R8 (Config1)); | 1594 | RTL_R8 (Config1)); |
1595 | } | 1595 | } |
1596 | 1596 | ||
1597 | static int rtl8139_thread (void *data) | 1597 | static void rtl8139_thread (void *_data) |
1598 | { | 1598 | { |
1599 | struct net_device *dev = data; | 1599 | struct net_device *dev = _data; |
1600 | struct rtl8139_private *tp = netdev_priv(dev); | 1600 | struct rtl8139_private *tp = netdev_priv(dev); |
1601 | unsigned long timeout; | ||
1602 | |||
1603 | daemonize("%s", dev->name); | ||
1604 | allow_signal(SIGTERM); | ||
1605 | |||
1606 | while (1) { | ||
1607 | timeout = next_tick; | ||
1608 | do { | ||
1609 | timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); | ||
1610 | /* make swsusp happy with our thread */ | ||
1611 | try_to_freeze(); | ||
1612 | } while (!signal_pending (current) && (timeout > 0)); | ||
1613 | 1601 | ||
1614 | if (signal_pending (current)) { | 1602 | if ((tp->time_to_die == 0) && |
1615 | flush_signals(current); | 1603 | (rtnl_lock_interruptible() == 0)) { |
1616 | } | ||
1617 | |||
1618 | if (tp->time_to_die) | ||
1619 | break; | ||
1620 | |||
1621 | if (rtnl_lock_interruptible ()) | ||
1622 | break; | ||
1623 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); | 1604 | rtl8139_thread_iter (dev, tp, tp->mmio_addr); |
1624 | rtnl_unlock (); | 1605 | rtnl_unlock (); |
1625 | } | 1606 | } |
1626 | 1607 | ||
1627 | complete_and_exit (&tp->thr_exited, 0); | 1608 | if (tp->time_to_die == 0) |
1609 | schedule_delayed_work(&tp->thread, next_tick); | ||
1628 | } | 1610 | } |
1629 | 1611 | ||
1630 | static void rtl8139_start_thread(struct net_device *dev) | 1612 | static void rtl8139_start_thread(struct rtl8139_private *tp) |
1631 | { | 1613 | { |
1632 | struct rtl8139_private *tp = netdev_priv(dev); | ||
1633 | |||
1634 | tp->thr_pid = -1; | ||
1635 | tp->twistie = 0; | 1614 | tp->twistie = 0; |
1636 | tp->time_to_die = 0; | 1615 | tp->time_to_die = -1; |
1637 | if (tp->chipset == CH_8139_K) | 1616 | if (tp->chipset == CH_8139_K) |
1638 | tp->twistie = 1; | 1617 | tp->twistie = 1; |
1639 | else if (tp->drv_flags & HAS_LNK_CHNG) | 1618 | else if (tp->drv_flags & HAS_LNK_CHNG) |
1640 | return; | 1619 | return; |
1641 | 1620 | ||
1642 | tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES); | 1621 | tp->time_to_die = 0; |
1643 | if (tp->thr_pid < 0) { | 1622 | |
1644 | printk (KERN_WARNING "%s: unable to start kernel thread\n", | 1623 | schedule_delayed_work(&tp->thread, next_tick); |
1645 | dev->name); | 1624 | } |
1646 | } | 1625 | |
1626 | static void rtl8139_stop_thread(struct rtl8139_private *tp) | ||
1627 | { | ||
1628 | if (tp->time_to_die < 0) | ||
1629 | return; | ||
1630 | |||
1631 | tp->time_to_die = 1; | ||
1632 | wmb(); | ||
1633 | |||
1634 | if (cancel_delayed_work(&tp->thread) == 0) | ||
1635 | flush_scheduled_work(); | ||
1647 | } | 1636 | } |
1648 | 1637 | ||
1649 | static inline void rtl8139_tx_clear (struct rtl8139_private *tp) | 1638 | static inline void rtl8139_tx_clear (struct rtl8139_private *tp) |
@@ -2224,22 +2213,12 @@ static int rtl8139_close (struct net_device *dev) | |||
2224 | { | 2213 | { |
2225 | struct rtl8139_private *tp = netdev_priv(dev); | 2214 | struct rtl8139_private *tp = netdev_priv(dev); |
2226 | void __iomem *ioaddr = tp->mmio_addr; | 2215 | void __iomem *ioaddr = tp->mmio_addr; |
2227 | int ret = 0; | ||
2228 | unsigned long flags; | 2216 | unsigned long flags; |
2229 | 2217 | ||
2230 | netif_stop_queue (dev); | 2218 | netif_stop_queue (dev); |
2231 | 2219 | ||
2232 | if (tp->thr_pid >= 0) { | 2220 | rtl8139_stop_thread(tp); |
2233 | tp->time_to_die = 1; | 2221 | |
2234 | wmb(); | ||
2235 | ret = kill_proc (tp->thr_pid, SIGTERM, 1); | ||
2236 | if (ret) { | ||
2237 | printk (KERN_ERR "%s: unable to signal thread\n", dev->name); | ||
2238 | return ret; | ||
2239 | } | ||
2240 | wait_for_completion (&tp->thr_exited); | ||
2241 | } | ||
2242 | |||
2243 | if (netif_msg_ifdown(tp)) | 2222 | if (netif_msg_ifdown(tp)) |
2244 | printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", | 2223 | printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n", |
2245 | dev->name, RTL_R16 (IntrStatus)); | 2224 | dev->name, RTL_R16 (IntrStatus)); |