* [PATCH net-next] net: mana: add BQL support
@ 2026-10-08 15:23 Hamza Mahfooz
2026-10-12 15:57 ` netdev-bot+sashiko
0 siblings, 1 reply; 3+ messages in thread
From: Hamza Mahfooz @ 2026-10-08 15:23 UTC (permalink / raw)
To: netdev
Cc: Haiyang Zhang, Wei Liu, Dexuan Cui, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Erni Sri Satya Vennela, Aditya Garg, linux-hyperv, linux-kernel,
Hamza Mahfooz
MANA doesn't support byte queue limits, so each TX queue can hold 256
WQEs by default, and up to 16384, of up to 64 KB TSO packets, before
the qdisc layer sees any backpressure. This adds latency to all the
flows sharing a queue, and defeats AQM qdiscs such as fq_codel, which
rely on BQL to keep the driver queues short.
Report the bytes queued and completed to BQL. XDP_TX and XDP_REDIRECT
packets go through the same SQs, so they are accounted too. BQL doesn't
drop or delay them, since the XDP paths send even when the queue is
stopped; it only holds back the stack's packets.
Reset the BQL state when destroying the queues, once their NAPI is
disabled, since the SKBs still pending after a drain timeout are freed
without being completed.
Lost TX completions can now stop a queue sooner: it also stops when the
bytes in flight exceed the BQL limit, not only when the SQ is full. The
TX watchdog covers the queues stopped by BQL, and its handler resets the
queues along with their BQL state.
Tested on two Standard_D16ds_v6 Azure VMs in a proximity placement
group, where the throughput is capped at 10.6 Gbps, with the DUT
alternately booting net-next (c1c1f0a31712) with and without this
patch applied.
The throughput stays at the cap with 1, 8 and 64 TCP flows, and the
idle TCP_RR latency doesn't change (p50 of 47 us with vs. without the
patch). With 16 senders of 64-byte UDP packets, the DUT sends 3.7 to
4.0 Mpps without the patch and 3.7 to 4.1 Mpps with it. With bulk TCP
flows sharing the queues, the netperf TCP_RR latency drops (medians of
6 runs):
16 queues, 64 flows: p50 4649 -> 2182 us, p99 5621 -> 2677 us
1 queue, 8 flows: p50 2554 -> 418 us, p99 2723 -> 624 us
The standing queue moves from the SQs to fq_codel, which now drops
packets: about 2500 qdisc drops and 88K TCP retransmissions per 48 s
run with 64 flows, against at most 29 retransmissions before. The
retransmissions are about 0.2% of the segments sent. The TCP_RR flows
lose no packets, and the packets of the bulk flows are dropped before
they reach the wire, so the goodput changes by less than 0.01%.
Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 2ba48a1c4b15..67048fe64d63 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -543,6 +543,11 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
err = NETDEV_TX_OK;
atomic_inc(&txq->pending_sends);
+ /* Account the skb in BQL before the doorbell lets the hardware
+ * complete it.
+ */
+ netdev_tx_sent_queue(net_txq, len);
+
mana_gd_wq_ring_doorbell(gd->gdma_context, gdma_sq);
/* skb may be freed after mana_gd_post_work_request. Do not use it. */
@@ -2009,10 +2014,12 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
gdma_wq = txq->gdma_sq;
avail_space = mana_gd_wq_avail_space(gdma_wq);
+ net_txq = txq->net_txq;
+ netdev_tx_completed_queue(net_txq, pkt_transmitted, tx_bytes);
+
/* Ensure tail updated before checking q stop */
smp_mb();
- net_txq = txq->net_txq;
txq_stopped = netif_tx_queue_stopped(net_txq);
/* Ensure checking txq_stopped before apc->port_is_up. */
@@ -2665,6 +2672,13 @@ static void mana_destroy_txq(struct mana_port_context *apc)
apc->tx_qp[i]->txq.napi_initialized = false;
}
+ /* Forget the SKBs freed without being completed after a drain
+ * timeout, now that NAPI can't complete any. Doing it here also
+ * covers the queues that a lower channel count won't recreate,
+ * which could otherwise stay stopped.
+ */
+ netdev_tx_reset_queue(apc->tx_qp[i]->txq.net_txq);
+
if (apc->tx_qp[i]->tx_object != INVALID_MANA_HANDLE)
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i]->tx_object);
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net-next] net: mana: add BQL support
2026-10-08 15:23 [PATCH net-next] net: mana: add BQL support Hamza Mahfooz
@ 2026-10-12 15:57 ` netdev-bot+sashiko
2026-10-12 18:45 ` Hamza Mahfooz
0 siblings, 1 reply; 3+ messages in thread
From: netdev-bot+sashiko @ 2026-10-12 15:57 UTC (permalink / raw)
To: hamzamahfooz
Cc: netdev, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, horms, ernis, gargaditya, linux-hyperv,
linux-kernel
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.
Critical: 0 · High: 0 · Medium: 1 · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [Medium] If TX completions are lost, XDP traffic can keep a BQL-stopped
MANA queue from ever being recovered by the TX watchdog.
--
net: mana: add BQL support
This patch adds byte queue limit accounting to MANA. Queued bytes are
reported in mana_start_xmit() and completed bytes in mana_poll_tx_cq().
XDP_TX and XDP_REDIRECT sends are counted through the same path, and the
BQL state is reset in mana_destroy_txq() after NAPI is disabled.
> diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
> index 2ba48a1c4b15e..67048fe64d63e 100644
> --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> @@ -543,6 +543,11 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
> err = NETDEV_TX_OK;
> atomic_inc(&txq->pending_sends);
>
> + /* Account the skb in BQL before the doorbell lets the hardware
> + * complete it.
> + */
> + netdev_tx_sent_queue(net_txq, len);
> +
[Severity: Medium]
Can XDP traffic stop the TX watchdog from ever recovering a queue that
BQL has stopped? The commit message says:
The TX watchdog covers the queues stopped by BQL, and its handler resets
the queues along with their BQL state.
XDP_TX and XDP_REDIRECT (mana_xdp_xmit()->mana_xdp_xmit_fm()) both reach
mana_start_xmit() through mana_xdp_tx(). That function does not check
whether the queue is stopped:
drivers/net/ethernet/microsoft/mana/mana_bpf.c:mana_xdp_tx() {
...
__netif_tx_lock(ndevtxq, smp_processor_id());
rc = mana_start_xmit(skb, ndev);
...
}
With this patch, each of those sends now calls netdev_tx_sent_queue().
If the queue is over its limit, netdev_tx_sent_queue() always refreshes
trans_start, even when __QUEUE_STATE_STACK_XOFF is already set:
include/linux/netdevice.h:netdev_tx_sent_queue() {
...
/* Paired with READ_ONCE() from dev_watchdog() */
WRITE_ONCE(dev_queue->trans_start, jiffies);
...
set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);
...
}
dev_watchdog() only fires when trans_start is older than watchdog_timeo.
MANA sets watchdog_timeo to 15 * HZ. One XDP packet every 15 seconds on
that queue seems to be enough to stop mana_tx_timeout() from ever
running.
In that state, what clears STACK_XOFF? mana_poll_tx_cq() matches CQEs to
SKBs in FIFO order with skb_dequeue(). If completions are lost, the lost
bytes become a permanent debt D in num_queued - num_completed.
netdev_tx_completed_queue() only clears STACK_XOFF when dql_avail() >= 0,
so the limit would have to reach D.
In dql_completed(), the limit only grows here:
if ((ovlimit && !inprogress) ||
(dql->prev_ovlimit && all_prev_completed)) {
The first condition can't be true while inprogress >= D. The second
needs one poll to complete at least the bytes that were in flight at the
previous poll. A low-rate XDP flow with one completion per poll won't
meet that.
For example, take equal R-byte packets, a learned limit of R, and two
lost completions (D = 2R). The limit never grows, and the decrease
branch can shrink it further.
netif_tx_wake_queue() only clears DRV_XOFF. The only
netdev_tx_reset_queue() call is in mana_destroy_txq().
Would stack traffic on that queue then stay blocked indefinitely while
XDP traffic keeps flowing?
Hardware faults are not the only source of lost completions. The early
returns in mana_poll_tx_cq() exit after some SKBs have already been
dequeued and freed, but before netdev_tx_completed_queue() runs:
drivers/net/ethernet/microsoft/mana/mana_en.c:mana_poll_tx_cq() {
...
if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num))
return;
skb = skb_dequeue(&txq->pending_skbs);
if (WARN_ON_ONCE(!skb))
return;
...
}
Before this patch, a few leaked WQEs did not block stack traffic on the
queue as long as the SQ was not full.
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008152302.3192778-1-hamzamahfooz%40linux.microsoft.com
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH net-next] net: mana: add BQL support
2026-10-12 15:57 ` netdev-bot+sashiko
@ 2026-10-12 18:45 ` Hamza Mahfooz
0 siblings, 0 replies; 3+ messages in thread
From: Hamza Mahfooz @ 2026-10-12 18:45 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: netdev, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, horms, ernis, gargaditya, linux-hyperv,
linux-kernel
On Mon, Oct 12, 2026 at 03:57:45PM +0000, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 0 · Medium: 1 · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [Medium] If TX completions are lost, XDP traffic can keep a BQL-stopped
> MANA queue from ever being recovered by the TX watchdog.
>
> --
>
> net: mana: add BQL support
>
> This patch adds byte queue limit accounting to MANA. Queued bytes are
> reported in mana_start_xmit() and completed bytes in mana_poll_tx_cq().
> XDP_TX and XDP_REDIRECT sends are counted through the same path, and the
> BQL state is reset in mana_destroy_txq() after NAPI is disabled.
>
> > diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > index 2ba48a1c4b15e..67048fe64d63e 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > @@ -543,6 +543,11 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
> > err = NETDEV_TX_OK;
> > atomic_inc(&txq->pending_sends);
> >
> > + /* Account the skb in BQL before the doorbell lets the hardware
> > + * complete it.
> > + */
> > + netdev_tx_sent_queue(net_txq, len);
> > +
>
> [Severity: Medium]
> Can XDP traffic stop the TX watchdog from ever recovering a queue that
> BQL has stopped? The commit message says:
>
> The TX watchdog covers the queues stopped by BQL, and its handler resets
> the queues along with their BQL state.
>
> XDP_TX and XDP_REDIRECT (mana_xdp_xmit()->mana_xdp_xmit_fm()) both reach
> mana_start_xmit() through mana_xdp_tx(). That function does not check
> whether the queue is stopped:
>
> drivers/net/ethernet/microsoft/mana/mana_bpf.c:mana_xdp_tx() {
> ...
> __netif_tx_lock(ndevtxq, smp_processor_id());
>
> rc = mana_start_xmit(skb, ndev);
> ...
> }
>
> With this patch, each of those sends now calls netdev_tx_sent_queue().
> If the queue is over its limit, netdev_tx_sent_queue() always refreshes
> trans_start, even when __QUEUE_STATE_STACK_XOFF is already set:
>
> include/linux/netdevice.h:netdev_tx_sent_queue() {
> ...
> /* Paired with READ_ONCE() from dev_watchdog() */
> WRITE_ONCE(dev_queue->trans_start, jiffies);
> ...
> set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);
> ...
> }
>
> dev_watchdog() only fires when trans_start is older than watchdog_timeo.
> MANA sets watchdog_timeo to 15 * HZ. One XDP packet every 15 seconds on
> that queue seems to be enough to stop mana_tx_timeout() from ever
> running.
>
> In that state, what clears STACK_XOFF? mana_poll_tx_cq() matches CQEs to
> SKBs in FIFO order with skb_dequeue(). If completions are lost, the lost
> bytes become a permanent debt D in num_queued - num_completed.
> netdev_tx_completed_queue() only clears STACK_XOFF when dql_avail() >= 0,
> so the limit would have to reach D.
>
> In dql_completed(), the limit only grows here:
>
> if ((ovlimit && !inprogress) ||
> (dql->prev_ovlimit && all_prev_completed)) {
>
> The first condition can't be true while inprogress >= D. The second
> needs one poll to complete at least the bytes that were in flight at the
> previous poll. A low-rate XDP flow with one completion per poll won't
> meet that.
>
> For example, take equal R-byte packets, a learned limit of R, and two
> lost completions (D = 2R). The limit never grows, and the decrease
> branch can shrink it further.
>
> netif_tx_wake_queue() only clears DRV_XOFF. The only
> netdev_tx_reset_queue() call is in mana_destroy_txq().
>
> Would stack traffic on that queue then stay blocked indefinitely while
> XDP traffic keeps flowing?
>
Ack, I'll spin up a v2 to address this.
> Hardware faults are not the only source of lost completions. The early
> returns in mana_poll_tx_cq() exit after some SKBs have already been
> dequeued and freed, but before netdev_tx_completed_queue() runs:
>
The early returns are all WARN_ON_ONCE() paths (for completions that
shouldn't happen). mana_gd_poll_cq() has already consumed the rest of
the batch (by the time we hit one of those paths), so the SKBs can't be
matched back to completions anymore. Completing the SKBs already dequeued
wouldn't avoid that, so I think it makes more sense to leave those paths
as they are and rely on the watchdog reset to recover the queue.
pw-bot: cr
> drivers/net/ethernet/microsoft/mana/mana_en.c:mana_poll_tx_cq() {
> ...
> if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num))
> return;
>
> skb = skb_dequeue(&txq->pending_skbs);
> if (WARN_ON_ONCE(!skb))
> return;
> ...
> }
>
> Before this patch, a few leaked WQEs did not block stack traffic on the
> queue as long as the SQ was not full.
>
> [ ... ]
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008152302.3192778-1-hamzamahfooz%40linux.microsoft.com
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-12 18:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08 15:23 [PATCH net-next] net: mana: add BQL support Hamza Mahfooz
2026-10-12 15:57 ` netdev-bot+sashiko
2026-10-12 18:45 ` Hamza Mahfooz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox