* if no default DP has been configured. This
                         * allows for DP flows to be left untouched.
                         */
-                       if (skb_queue_len(&sch->q) < qdisc_dev(sch)->tx_queue_len)
+                       if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <=
+                                       sch->limit))
                                return qdisc_enqueue_tail(skb, sch);
                        else
                                goto drop;
 
        q->DP = dp;
        q->prio = prio;
-       q->limit = ctl->limit;
+       if (ctl->limit > sch->limit)
+               q->limit = sch->limit;
+       else
+               q->limit = ctl->limit;
 
        if (q->backlog == 0)
                red_end_of_idle_period(&q->vars);
        [TCA_GRED_STAB]         = { .len = 256 },
        [TCA_GRED_DPS]          = { .len = sizeof(struct tc_gred_sopt) },
        [TCA_GRED_MAX_P]        = { .type = NLA_U32 },
+       [TCA_GRED_LIMIT]        = { .type = NLA_U32 },
 };
 
 static int gred_change(struct Qdisc *sch, struct nlattr *opt)
        if (err < 0)
                return err;
 
-       if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL)
+       if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL) {
+               if (tb[TCA_GRED_LIMIT] != NULL)
+                       sch->limit = nla_get_u32(tb[TCA_GRED_LIMIT]);
                return gred_change_table_def(sch, opt);
+       }
 
        if (tb[TCA_GRED_PARMS] == NULL ||
-           tb[TCA_GRED_STAB] == NULL)
+           tb[TCA_GRED_STAB] == NULL ||
+           tb[TCA_GRED_LIMIT] != NULL)
                return -EINVAL;
 
        max_P = tb[TCA_GRED_MAX_P] ? nla_get_u32(tb[TCA_GRED_MAX_P]) : 0;
        if (tb[TCA_GRED_PARMS] || tb[TCA_GRED_STAB])
                return -EINVAL;
 
+       if (tb[TCA_GRED_LIMIT])
+               sch->limit = nla_get_u32(tb[TCA_GRED_LIMIT]);
+       else {
+               u32 qlen = qdisc_dev(sch)->tx_queue_len ? : 1;
+
+               sch->limit = qlen * psched_mtu(qdisc_dev(sch));
+       }
+
        return gred_change_table_def(sch, tb[TCA_GRED_DPS]);
 }
 
        if (nla_put(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p))
                goto nla_put_failure;
 
+       if (nla_put_u32(skb, TCA_GRED_LIMIT, sch->limit))
+               goto nla_put_failure;
+
        parms = nla_nest_start(skb, TCA_GRED_PARMS);
        if (parms == NULL)
                goto nla_put_failure;