net: sched: Add multi-queue support to sch_tree_lock
The existing qdiscs that set TCQ_F_MQROOT don't use sch_tree_lock. However, hardware-offloaded HTB will start setting this flag while also using sch_tree_lock. The current implementation of sch_tree_lock basically locks on qdisc->dev_queue->qdisc, and it works fine when the tree is attached to some queue. However, it's not the case for MQROOT qdiscs: such a qdisc is the root itself, and its dev_queue just points to queue 0, while not actually being used, because there are real per-queue qdiscs. This patch changes the logic of sch_tree_lock and sch_tree_unlock to lock the qdisc itself if it's the MQROOT. Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com> Reviewed-by: Tariq Toukan <tariqt@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
04a886372a
commit
ca1e4ab199
@ -552,14 +552,20 @@ static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
|
||||
return qdisc->dev_queue->dev;
|
||||
}
|
||||
|
||||
static inline void sch_tree_lock(const struct Qdisc *q)
|
||||
static inline void sch_tree_lock(struct Qdisc *q)
|
||||
{
|
||||
spin_lock_bh(qdisc_root_sleeping_lock(q));
|
||||
if (q->flags & TCQ_F_MQROOT)
|
||||
spin_lock_bh(qdisc_lock(q));
|
||||
else
|
||||
spin_lock_bh(qdisc_root_sleeping_lock(q));
|
||||
}
|
||||
|
||||
static inline void sch_tree_unlock(const struct Qdisc *q)
|
||||
static inline void sch_tree_unlock(struct Qdisc *q)
|
||||
{
|
||||
spin_unlock_bh(qdisc_root_sleeping_lock(q));
|
||||
if (q->flags & TCQ_F_MQROOT)
|
||||
spin_unlock_bh(qdisc_lock(q));
|
||||
else
|
||||
spin_unlock_bh(qdisc_root_sleeping_lock(q));
|
||||
}
|
||||
|
||||
extern struct Qdisc noop_qdisc;
|
||||
|
Loading…
Reference in New Issue
Block a user