[NETPOLL]: fix initialization/NAPI race
[safe/jmp/linux-2.6] / net / core / dev.c
index 1a64508..faf59b0 100644 (file)
@@ -901,8 +901,7 @@ int dev_close(struct net_device *dev)
        smp_mb__after_clear_bit(); /* Commit netif_running(). */
        while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
                /* No hurry. */
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               msleep(1);
        }
 
        /*
@@ -1127,7 +1126,7 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 extern void skb_release_data(struct sk_buff *);
 
 /* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, int gfp_mask)
+int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp_mask)
 {
        unsigned int size;
        u8 *data;
@@ -1346,7 +1345,8 @@ out:
                        Receiver routines
   =======================================================================*/
 
-int netdev_max_backlog = 300;
+int netdev_max_backlog = 1000;
+int netdev_budget = 300;
 int weight_p = 64;            /* old backlog weight */
 
 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
@@ -1695,9 +1695,9 @@ static void net_rx_action(struct softirq_action *h)
 {
        struct softnet_data *queue = &__get_cpu_var(softnet_data);
        unsigned long start_time = jiffies;
-       int budget = netdev_max_backlog;
+       int budget = netdev_budget;
+       void *have;
 
-       
        local_irq_disable();
 
        while (!list_empty(&queue->poll_list)) {
@@ -1710,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h)
 
                dev = list_entry(queue->poll_list.next,
                                 struct net_device, poll_list);
-               netpoll_poll_lock(dev);
+               have = netpoll_poll_lock(dev);
 
                if (dev->quota <= 0 || dev->poll(dev, &budget)) {
-                       netpoll_poll_unlock(dev);
+                       netpoll_poll_unlock(have);
                        local_irq_disable();
                        list_del(&dev->poll_list);
                        list_add_tail(&dev->poll_list, &queue->poll_list);
@@ -1722,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h)
                        else
                                dev->quota = dev->weight;
                } else {
-                       netpoll_poll_unlock(dev);
+                       netpoll_poll_unlock(have);
                        dev_put(dev);
                        local_irq_disable();
                }
@@ -2089,10 +2089,11 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
 {
        unsigned short old_flags = dev->flags;
 
-       dev->flags |= IFF_PROMISC;
        if ((dev->promiscuity += inc) == 0)
                dev->flags &= ~IFF_PROMISC;
-       if (dev->flags ^ old_flags) {
+       else
+               dev->flags |= IFF_PROMISC;
+       if (dev->flags != old_flags) {
                dev_mc_upload(dev);
                printk(KERN_INFO "device %s %s promiscuous mode\n",
                       dev->name, (dev->flags & IFF_PROMISC) ? "entered" :