]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/sched/sch_generic.c
net: this_cpu_xxx conversions
[net-next-2.6.git] / net / sched / sch_generic.c
index ff4dd53eeff013f875330d8fbeb24e3a6e299e5a..2aeb3a4386a10f499f020c961bada4803653985b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <net/pkt_sched.h>
+#include <net/dst.h>
 
 /* Main transmission queue. */
 
@@ -40,6 +41,7 @@
 
 static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
 {
+       skb_dst_force(skb);
        q->gso_skb = skb;
        q->qstats.requeues++;
        q->q.qlen++;    /* it's still part of the queue */
@@ -94,7 +96,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
                 * Another cpu is holding lock, requeue & delay xmits for
                 * some time.
                 */
-               __get_cpu_var(netdev_rx_stat).cpu_collision++;
+               __this_cpu_inc(softnet_data.cpu_collision);
                ret = dev_requeue_skb(skb, q);
        }
 
@@ -179,7 +181,7 @@ static inline int qdisc_restart(struct Qdisc *q)
        skb = dequeue_skb(q);
        if (unlikely(!skb))
                return 0;
-
+       WARN_ON_ONCE(skb_dst_is_noref(skb));
        root_lock = qdisc_lock(q);
        dev = qdisc_dev(q);
        txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
@@ -203,7 +205,7 @@ void __qdisc_run(struct Qdisc *q)
                }
        }
 
-       clear_bit(__QDISC_STATE_RUNNING, &q->state);
+       qdisc_run_end(q);
 }
 
 unsigned long dev_trans_start(struct net_device *dev)
@@ -325,6 +327,24 @@ void netif_carrier_off(struct net_device *dev)
 }
 EXPORT_SYMBOL(netif_carrier_off);
 
+/**
+ *     netif_notify_peers - notify network peers about existence of @dev
+ *     @dev: network device
+ *
+ * Generate traffic such that interested network peers are aware of
+ * @dev, such as by generating a gratuitous ARP. This may be used when
+ * a device wants to inform the rest of the network about some sort of
+ * reconfiguration such as a failover event or virtual machine
+ * migration.
+ */
+void netif_notify_peers(struct net_device *dev)
+{
+       rtnl_lock();
+       call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
+       rtnl_unlock();
+}
+EXPORT_SYMBOL(netif_notify_peers);
+
 /* "NOOP" scheduler: the best scheduler, recommended for all interfaces
    under all circumstances. It is difficult to invent anything faster or
    cheaper.
@@ -529,7 +549,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
        unsigned int size;
        int err = -ENOBUFS;
 
-       /* ensure that the Qdisc and the private data are 32-byte aligned */
+       /* ensure that the Qdisc and the private data are 64-byte aligned */
        size = QDISC_ALIGN(sizeof(*sch));
        size += ops->priv_size + (QDISC_ALIGNTO - 1);
 
@@ -541,6 +561,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 
        INIT_LIST_HEAD(&sch->list);
        skb_queue_head_init(&sch->q);
+       spin_lock_init(&sch->busylock);
        sch->ops = ops;
        sch->enqueue = ops->enqueue;
        sch->dequeue = ops->dequeue;
@@ -591,6 +612,13 @@ void qdisc_reset(struct Qdisc *qdisc)
 }
 EXPORT_SYMBOL(qdisc_reset);
 
+static void qdisc_rcu_free(struct rcu_head *head)
+{
+       struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head);
+
+       kfree((char *) qdisc - qdisc->padded);
+}
+
 void qdisc_destroy(struct Qdisc *qdisc)
 {
        const struct Qdisc_ops  *ops = qdisc->ops;
@@ -614,7 +642,11 @@ void qdisc_destroy(struct Qdisc *qdisc)
        dev_put(qdisc_dev(qdisc));
 
        kfree_skb(qdisc->gso_skb);
-       kfree((char *) qdisc - qdisc->padded);
+       /*
+        * gen_estimator est_timer() might access qdisc->q.lock,
+        * wait a RCU grace period before freeing qdisc.
+        */
+       call_rcu(&qdisc->rcu_head, qdisc_rcu_free);
 }
 EXPORT_SYMBOL(qdisc_destroy);
 
@@ -766,7 +798,7 @@ static bool some_qdisc_is_busy(struct net_device *dev)
 
                spin_lock_bh(root_lock);
 
-               val = (test_bit(__QDISC_STATE_RUNNING, &q->state) ||
+               val = (qdisc_is_running(q) ||
                       test_bit(__QDISC_STATE_SCHED, &q->state));
 
                spin_unlock_bh(root_lock);