diff options
| -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)); |
