#include <uapi/linux/netdevice.h>
 #include <uapi/linux/if_bonding.h>
 #include <uapi/linux/pkt_cls.h>
+#include <linux/hashtable.h>
 
 struct netpoll_info;
 struct device;
        unsigned int            num_tx_queues;
        unsigned int            real_num_tx_queues;
        struct Qdisc            *qdisc;
+#ifdef CONFIG_NET_SCHED
+       DECLARE_HASHTABLE       (qdisc_hash, 4);
+#endif
        unsigned long           tx_queue_len;
        spinlock_t              tx_global_lock;
        int                     watchdog_timeo;
 
 void qdisc_get_default(char *id, size_t len);
 int qdisc_set_default(const char *id);
 
-void qdisc_list_add(struct Qdisc *q);
-void qdisc_list_del(struct Qdisc *q);
+void qdisc_hash_add(struct Qdisc *q);
+void qdisc_hash_del(struct Qdisc *q);
 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
 struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
 struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
 
 #include <linux/hrtimer.h>
 #include <linux/lockdep.h>
 #include <linux/slab.h>
+#include <linux/hashtable.h>
 
 #include <net/net_namespace.h>
 #include <net/sock.h>
            root->handle == handle)
                return root;
 
-       list_for_each_entry_rcu(q, &root->list, list) {
+       hash_for_each_possible_rcu(qdisc_dev(root)->qdisc_hash, q, hash, handle) {
                if (q->handle == handle)
                        return q;
        }
        return NULL;
 }
 
-void qdisc_list_add(struct Qdisc *q)
+void qdisc_hash_add(struct Qdisc *q)
 {
        if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
                struct Qdisc *root = qdisc_dev(q)->qdisc;
 
                WARN_ON_ONCE(root == &noop_qdisc);
                ASSERT_RTNL();
-               list_add_tail_rcu(&q->list, &root->list);
+               hash_add_rcu(qdisc_dev(q)->qdisc_hash, &q->hash, q->handle);
        }
 }
-EXPORT_SYMBOL(qdisc_list_add);
+EXPORT_SYMBOL(qdisc_hash_add);
 
-void qdisc_list_del(struct Qdisc *q)
+void qdisc_hash_del(struct Qdisc *q)
 {
        if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
                ASSERT_RTNL();
-               list_del_rcu(&q->list);
+               hash_del_rcu(&q->hash);
        }
 }
-EXPORT_SYMBOL(qdisc_list_del);
+EXPORT_SYMBOL(qdisc_hash_del);
 
 struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
                                goto err_out4;
                }
 
-               qdisc_list_add(sch);
+               qdisc_hash_add(sch);
 
                return sch;
        }
 {
        int ret = 0, q_idx = *q_idx_p;
        struct Qdisc *q;
+       int b;
 
        if (!root)
                return 0;
                        goto done;
                q_idx++;
        }
-       list_for_each_entry(q, &root->list, list) {
+       hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
                if (q_idx < s_q_idx) {
                        q_idx++;
                        continue;
                               int *t_p, int s_t)
 {
        struct Qdisc *q;
+       int b;
 
        if (!root)
                return 0;
        if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0)
                return -1;
 
-       list_for_each_entry(q, &root->list, list) {
+       hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
                if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
                        return -1;
        }
 
        .dequeue        =       noop_dequeue,
        .flags          =       TCQ_F_BUILTIN,
        .ops            =       &noop_qdisc_ops,
-       .list           =       LIST_HEAD_INIT(noop_qdisc.list),
        .q.lock         =       __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock),
        .dev_queue      =       &noop_netdev_queue,
        .running        =       SEQCNT_ZERO(noop_qdisc.running),
                sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
                sch->padded = (char *) sch - (char *) p;
        }
-       INIT_LIST_HEAD(&sch->list);
        skb_queue_head_init(&sch->q);
 
        spin_lock_init(&sch->busylock);
                return;
 
 #ifdef CONFIG_NET_SCHED
-       qdisc_list_del(qdisc);
+       qdisc_hash_del(qdisc);
 
        qdisc_put_stab(rtnl_dereference(qdisc->stab));
 #endif
                        qdisc->ops->attach(qdisc);
                }
        }
+#ifdef CONFIG_NET_SCHED
+       if (dev->qdisc)
+               qdisc_hash_add(dev->qdisc);
+#endif
 }
 
 static void transition_one_qdisc(struct net_device *dev,