]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/sched/sch_generic.c
net_sched: move dev_graft_qdisc() to sch_generic.c
[net-next-2.6.git] / net / sched / sch_generic.c
index a91f079fb47a4077d6cb4dcf624c5b8ea67df5f7..e7c47ceb009817f4f8347291104bd26cfa6f7566 100644 (file)
@@ -623,6 +623,31 @@ void qdisc_destroy(struct Qdisc *qdisc)
 }
 EXPORT_SYMBOL(qdisc_destroy);
 
+/* Attach toplevel qdisc to device queue. */
+struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
+                             struct Qdisc *qdisc)
+{
+       struct Qdisc *oqdisc = dev_queue->qdisc_sleeping;
+       spinlock_t *root_lock;
+
+       root_lock = qdisc_lock(oqdisc);
+       spin_lock_bh(root_lock);
+
+       /* Prune old scheduler */
+       if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
+               qdisc_reset(oqdisc);
+
+       /* ... and graft new one */
+       if (qdisc == NULL)
+               qdisc = &noop_qdisc;
+       dev_queue->qdisc_sleeping = qdisc;
+       rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
+
+       spin_unlock_bh(root_lock);
+
+       return oqdisc;
+}
+
 static void attach_one_default_qdisc(struct net_device *dev,
                                     struct netdev_queue *dev_queue,
                                     void *_unused)