diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_gred.c | 2 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 27 | ||||
-rw-r--r-- | net/sched/sch_taprio.c | 3 |
3 files changed, 21 insertions, 11 deletions
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index a661b062cca8..872d127c9db4 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -377,6 +377,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch) /* Even if driver returns failure adjust the stats - in case offload * ended but driver still wants to adjust the values. */ + sch_tree_lock(sch); for (i = 0; i < MAX_DPs; i++) { if (!table->tab[i]) continue; @@ -393,6 +394,7 @@ static int gred_offload_dump_stats(struct Qdisc *sch) sch->qstats.overlimits += hw_stats->stats.qstats[i].overlimits; } _bstats_update(&sch->bstats, bytes, packets); + sch_tree_unlock(sch); kfree(hw_stats); return ret; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 2238edece1a4..f46643850df8 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1549,7 +1549,7 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl, struct tc_htb_qopt_offload offload_opt; struct netdev_queue *dev_queue; struct Qdisc *q = cl->leaf.q; - struct Qdisc *old = NULL; + struct Qdisc *old; int err; if (cl->level) @@ -1557,14 +1557,17 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl, WARN_ON(!q); dev_queue = htb_offload_get_queue(cl); - old = htb_graft_helper(dev_queue, NULL); - if (destroying) - /* Before HTB is destroyed, the kernel grafts noop_qdisc to - * all queues. + /* When destroying, caller qdisc_graft grafts the new qdisc and invokes + * qdisc_put for the qdisc being destroyed. htb_destroy_class_offload + * does not need to graft or qdisc_put the qdisc being destroyed. + */ + if (!destroying) { + old = htb_graft_helper(dev_queue, NULL); + /* Last qdisc grafted should be the same as cl->leaf.q when + * calling htb_delete. */ - WARN_ON(!(old->flags & TCQ_F_BUILTIN)); - else WARN_ON(old != q); + } if (cl->parent) { _bstats_update(&cl->parent->bstats_bias, @@ -1581,10 +1584,12 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl, }; err = htb_offload(qdisc_dev(sch), &offload_opt); - if (!err || destroying) - qdisc_put(old); - else - htb_graft_helper(dev_queue, old); + if (!destroying) { + if (!err) + qdisc_put(old); + else + htb_graft_helper(dev_queue, old); + } if (last_child) return err; diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 570389f6cdd7..9a11a499ea2d 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1700,6 +1700,8 @@ static void taprio_reset(struct Qdisc *sch) int i; hrtimer_cancel(&q->advance_timer); + qdisc_synchronize(sch); + if (q->qdiscs) { for (i = 0; i < dev->num_tx_queues; i++) if (q->qdiscs[i]) @@ -1720,6 +1722,7 @@ static void taprio_destroy(struct Qdisc *sch) * happens in qdisc_create(), after taprio_init() has been called. */ hrtimer_cancel(&q->advance_timer); + qdisc_synchronize(sch); taprio_disable_offload(dev, q, NULL); |