net: sched: avoid unnecessary seqcount operation for lockless qdisc
authorYunsheng Lin <linyunsheng@huawei.com>
Tue, 22 Jun 2021 06:49:55 +0000 (14:49 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Jun 2021 19:17:35 +0000 (12:17 -0700)
qdisc->running seqcount operation is mainly used to do heuristic
locking on q->busylock for locked qdisc, see qdisc_is_running()
and __dev_xmit_skb().

So avoid doing seqcount operation for qdisc with TCQ_F_NOLOCK
flag.

Acked-by: Jakub Kicinski <kuba@kernel.org>
Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> # flexcan
Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/sch_generic.h

index 1e625519ae9687608c087ceee6b30aac82513fca..3ed6bcc4be722a083e8d8bae6318a8540fb4b129 100644 (file)
@@ -188,6 +188,7 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 
 nolock_empty:
                WRITE_ONCE(qdisc->empty, false);
+               return true;
        } else if (qdisc_is_running(qdisc)) {
                return false;
        }
@@ -201,7 +202,6 @@ nolock_empty:
 
 static inline void qdisc_run_end(struct Qdisc *qdisc)
 {
-       write_seqcount_end(&qdisc->running);
        if (qdisc->flags & TCQ_F_NOLOCK) {
                spin_unlock(&qdisc->seqlock);
 
@@ -210,6 +210,8 @@ static inline void qdisc_run_end(struct Qdisc *qdisc)
                        clear_bit(__QDISC_STATE_MISSED, &qdisc->state);
                        __netif_schedule(qdisc);
                }
+       } else {
+               write_seqcount_end(&qdisc->running);
        }
 }