fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / 8139too.c
index e4f4eaf..99304b2 100644 (file)
@@ -90,7 +90,7 @@
 */
 
 #define DRV_NAME       "8139too"
-#define DRV_VERSION    "0.9.27"
+#define DRV_VERSION    "0.9.28"
 
 
 #include <linux/module.h>
@@ -594,7 +594,7 @@ struct rtl8139_private {
        u32 rx_config;
        struct rtl_extra_stats xstats;
 
-       struct work_struct thread;
+       struct delayed_work thread;
 
        struct mii_if_info mii;
        unsigned int regs_len;
@@ -629,17 +629,16 @@ static int rtl8139_poll(struct net_device *dev, int *budget);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void rtl8139_poll_controller(struct net_device *dev);
 #endif
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
-                              struct pt_regs *regs);
+static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance);
 static int rtl8139_close (struct net_device *dev);
 static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 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 void rtl8139_tx_timeout_task(void *_data);
-static struct ethtool_ops rtl8139_ethtool_ops;
+static void rtl8139_thread (struct work_struct *work);
+static void rtl8139_tx_timeout_task(struct work_struct *work);
+static const struct ethtool_ops rtl8139_ethtool_ops;
 
 /* write MMIO register, with flush */
 /* Flush avoids rtl8139 bug w/ posted MMIO writes */
@@ -1011,7 +1010,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_WORK(&tp->thread, rtl8139_thread, dev);
+       INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
        tp->mii.dev = dev;
        tp->mii.mdio_read = mdio_read;
        tp->mii.mdio_write = mdio_write;
@@ -1110,6 +1109,8 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 
        assert (dev != NULL);
 
+       flush_scheduled_work();
+
        unregister_netdev (dev);
 
        __rtl8139_cleanup_dev (dev);
@@ -1597,24 +1598,28 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
                 RTL_R8 (Config1));
 }
 
-static void rtl8139_thread (void *_data)
+static void rtl8139_thread (struct work_struct *work)
 {
-       struct net_device *dev = _data;
-       struct rtl8139_private *tp = netdev_priv(dev);
+       struct rtl8139_private *tp =
+               container_of(work, struct rtl8139_private, thread.work);
+       struct net_device *dev = tp->mii.dev;
        unsigned long thr_delay = next_tick;
 
+       rtnl_lock();
+
+       if (!netif_running(dev))
+               goto out_unlock;
+
        if (tp->watchdog_fired) {
                tp->watchdog_fired = 0;
-               rtl8139_tx_timeout_task(_data);
-       } else if (rtnl_trylock()) {
-               rtl8139_thread_iter (dev, tp, tp->mmio_addr);
-               rtnl_unlock ();
-       } else {
-               /* unlikely race.  mitigate with fast poll. */
-               thr_delay = HZ / 2;
-       }
+               rtl8139_tx_timeout_task(work);
+       } else
+               rtl8139_thread_iter(dev, tp, tp->mmio_addr);
 
-       schedule_delayed_work(&tp->thread, thr_delay);
+       if (tp->have_thread)
+               schedule_delayed_work(&tp->thread, thr_delay);
+out_unlock:
+       rtnl_unlock ();
 }
 
 static void rtl8139_start_thread(struct rtl8139_private *tp)
@@ -1626,19 +1631,11 @@ static void rtl8139_start_thread(struct rtl8139_private *tp)
                return;
 
        tp->have_thread = 1;
+       tp->watchdog_fired = 0;
 
        schedule_delayed_work(&tp->thread, next_tick);
 }
 
-static void rtl8139_stop_thread(struct rtl8139_private *tp)
-{
-       if (tp->have_thread) {
-               cancel_rearming_delayed_work(&tp->thread);
-               tp->have_thread = 0;
-       } else
-               flush_scheduled_work();
-}
-
 static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
 {
        tp->cur_tx = 0;
@@ -1647,10 +1644,11 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
        /* XXX account for unsent Tx packets in tp->stats.tx_dropped */
 }
 
-static void rtl8139_tx_timeout_task (void *_data)
+static void rtl8139_tx_timeout_task (struct work_struct *work)
 {
-       struct net_device *dev = _data;
-       struct rtl8139_private *tp = netdev_priv(dev);
+       struct rtl8139_private *tp =
+               container_of(work, struct rtl8139_private, thread.work);
+       struct net_device *dev = tp->mii.dev;
        void __iomem *ioaddr = tp->mmio_addr;
        int i;
        u8 tmp8;
@@ -1695,12 +1693,11 @@ static void rtl8139_tx_timeout (struct net_device *dev)
 {
        struct rtl8139_private *tp = netdev_priv(dev);
 
+       tp->watchdog_fired = 1;
        if (!tp->have_thread) {
-               INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev);
+               INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
                schedule_delayed_work(&tp->thread, next_tick);
-       } else
-               tp->watchdog_fired = 1;
-
+       }
 }
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
@@ -2130,14 +2127,15 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
        }
 
        if (done) {
+               unsigned long flags;
                /*
                 * Order is important since data can get interrupted
                 * again when we think we are done.
                 */
-               local_irq_disable();
+               local_irq_save(flags);
                RTL_W16_F(IntrMask, rtl8139_intr_mask);
                __netif_rx_complete(dev);
-               local_irq_enable();
+               local_irq_restore(flags);
        }
        spin_unlock(&tp->rx_lock);
 
@@ -2146,8 +2144,7 @@ static int rtl8139_poll(struct net_device *dev, int *budget)
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
-                              struct pt_regs *regs)
+static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
 {
        struct net_device *dev = (struct net_device *) dev_instance;
        struct rtl8139_private *tp = netdev_priv(dev);
@@ -2219,7 +2216,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
 static void rtl8139_poll_controller(struct net_device *dev)
 {
        disable_irq(dev->irq);
-       rtl8139_interrupt(dev->irq, dev, NULL);
+       rtl8139_interrupt(dev->irq, dev);
        enable_irq(dev->irq);
 }
 #endif
@@ -2232,8 +2229,6 @@ static int rtl8139_close (struct net_device *dev)
 
        netif_stop_queue (dev);
 
-       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));
@@ -2446,7 +2441,7 @@ static void rtl8139_get_strings(struct net_device *dev, u32 stringset, u8 *data)
        memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
 }
 
-static struct ethtool_ops rtl8139_ethtool_ops = {
+static const struct ethtool_ops rtl8139_ethtool_ops = {
        .get_drvinfo            = rtl8139_get_drvinfo,
        .get_settings           = rtl8139_get_settings,
        .set_settings           = rtl8139_set_settings,
@@ -2512,9 +2507,6 @@ static void __set_rx_mode (struct net_device *dev)
 
        /* Note: do not reorder, GCC is clever about common statements. */
        if (dev->flags & IFF_PROMISC) {
-               /* Unconditionally log net taps. */
-               printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-                       dev->name);
                rx_mode =
                    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
                    AcceptAllPhys;
@@ -2629,7 +2621,7 @@ static int __init rtl8139_init_module (void)
        printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
 #endif
 
-       return pci_module_init (&rtl8139_pci_driver);
+       return pci_register_driver(&rtl8139_pci_driver);
 }