git: 55153512e9ab - stable/14 - iflib: Do not ring the transmit doorbell when nothing is pending
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 28 Oct 2026 20:41:30 UTC
The branch stable/14 has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=55153512e9abd9ec4daa7888a6a62fc8038d70ce
commit 55153512e9abd9ec4daa7888a6a62fc8038d70ce
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-10-05 15:17:13 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-28 20:38:05 +0000
iflib: Do not ring the transmit doorbell when nothing is pending
For a lightly used ring iflib_txd_db_check() may defer zero descriptors,
so its "pending >= limit" test is true even when nothing has been queued
since the last doorbell. iflib_txq_drain() calls it before, inside and
after its loop, so a sender that drains its own packet wrote the tail
register three times per packet, twice with the value the hardware
already had.
The log of 81be655266fa ("iflib: ensure that tx interrupts enabled and
cleanups") calls skipping the doorbell when db_pending is zero "an
obvious missing optimization"; the comparison against a limit of zero
defeated it. vmx(4) and mgb(4) have dropped such repeated requests in
the driver since 2019. Return early when nothing is pending.
Reviewed by: gallatin
MFC after: 2 weeks
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D60290
(cherry picked from commit 4a0ec469934a5de60b9b540689703a698ac44105)
---
sys/net/iflib.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index e90709e84e6f..ed2813458ebe 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -3134,6 +3134,13 @@ iflib_txd_db_check(iflib_txq_t txq, int ring)
if_ctx_t ctx = txq->ift_ctx;
qidx_t dbval, max;
+ /*
+ * Nothing has been queued since the last doorbell. The threshold is
+ * zero for a lightly used ring, so the test below would not catch this.
+ */
+ if (txq->ift_db_pending == 0)
+ return (false);
+
max = TXQ_MAX_DB_DEFERRED(txq, txq->ift_in_use);
/* force || threshold exceeded || at the edge of the ring */