--- x/net/sched/sch_taprio.c +++ y/net/sched/sch_taprio.c @@ -1941,6 +1941,9 @@ static int taprio_change(struct Qdisc *s /* Protects against enqueue()/dequeue() */ spin_lock_bh(qdisc_lock(sch)); + spin_lock_irqsave(&q->current_entry_lock, flags); + oper = rtnl_dereference(q->oper_sched); + admin = rtnl_dereference(q->admin_sched); if (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]) { if (!TXTIME_ASSIST_IS_ENABLED(q->flags)) { @@ -1981,17 +1984,12 @@ static int taprio_change(struct Qdisc *s } else { setup_first_end_time(q, new_admin, start); - /* Protects against advance_sched() */ - spin_lock_irqsave(&q->current_entry_lock, flags); - taprio_start_sched(sch, start, new_admin); rcu_assign_pointer(q->admin_sched, new_admin); if (admin) call_rcu(&admin->rcu, taprio_free_sched_cb); - spin_unlock_irqrestore(&q->current_entry_lock, flags); - if (FULL_OFFLOAD_IS_ENABLED(q->flags)) taprio_offload_config_changed(q); } @@ -2004,6 +2002,7 @@ static int taprio_change(struct Qdisc *s "Size table not specified, frame length estimations may be inaccurate"); unlock: + spin_unlock_irqrestore(&q->current_entry_lock, flags); spin_unlock_bh(qdisc_lock(sch)); free_sched: @@ -2393,7 +2392,9 @@ static int taprio_dump(struct Qdisc *sch struct sched_gate_list *oper, *admin; struct tc_mqprio_qopt opt = { 0 }; struct nlattr *nest, *sched_nest; + unsigned long flags; + spin_lock_irqsave(&q->current_entry_lock, flags); oper = rtnl_dereference(q->oper_sched); admin = rtnl_dereference(q->admin_sched); @@ -2436,6 +2437,7 @@ static int taprio_dump(struct Qdisc *sch nla_nest_end(skb, sched_nest); done: + spin_unlock_irqrestore(&q->current_entry_lock, flags); return nla_nest_end(skb, nest); admin_error: @@ -2445,6 +2447,7 @@ options_error: nla_nest_cancel(skb, nest); start_error: + spin_unlock_irqrestore(&q->current_entry_lock, flags); return -ENOSPC; }