On Mon, Oct 12, 2026 at 3:50 AM Tathagat Priyadarshi
<[email protected]> wrote:
>
> The DPDK GVE driver previously tracked transmitted packet count (re_cnt)
> at the end of each burst rather than tracking descriptor intervals per
> packet against GVE_TX_MIN_RE_INTERVAL (32).
>
> In multi-segment and TSO transmissions, each packet consumes multiple
> descriptors. The descriptor ring could exhaust before 32 packets were
> sent, resulting in zero descriptors requesting report_event and
> preventing the hardware DMA engine from returning GVE_COMPL_TYPE_DQO_DESC
> completions. Without these completions, txq->nb_free was never
> replenished, permanently stalling the TX queue.
>
> Align with the Linux kernel driver (gve_tx_update_tail()) by tracking
> descriptor indices with last_re_idx:
> - Replace re_cnt with last_re_idx in struct gve_tx_queue.
> - Reset last_re_idx = 0 in gve_reset_tx_ring_state_dqo().
> - On each packet transmission, check descriptor interval
> (last_desc_idx - last_re_idx) & mask >= GVE_TX_MIN_RE_INTERVAL.
> When met, set report_event on the packet's last descriptor and
> update last_re_idx.
>
> Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
> Fixes: 403c671a46b6 ("net/gve: support TSO in DQO RDA")
> Cc: [email protected]
>
> Acked-by: Joshua Washington <[email protected]>
> Signed-off-by: Tathagat Priyadarshi <[email protected]>
> ---
> drivers/net/gve/gve_ethdev.h | 2 +-
> drivers/net/gve/gve_tx_dqo.c | 18 ++++++++++--------
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
> index c9a176ff17..2033f49444 100644
> --- a/drivers/net/gve/gve_ethdev.h
> +++ b/drivers/net/gve/gve_ethdev.h
> @@ -193,8 +193,8 @@ struct gve_tx_queue {
> uint16_t sw_size;
> uint8_t cur_gen_bit;
> uint32_t last_desc_cleaned;
> + uint32_t last_re_idx;
> void **txqs;
> - uint16_t re_cnt;
>
> /* Only valid for DQO_RDA queue format */
> struct gve_tx_queue *complq;
> diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
> index c864d722d9..a8382ff3c4 100644
> --- a/drivers/net/gve/gve_tx_dqo.c
> +++ b/drivers/net/gve/gve_tx_dqo.c
> @@ -264,6 +264,8 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf
> **tx_pkts, uint16_t nb_pkts)
> uint16_t nb_descs;
> bool csum, tso;
> uint16_t tx_id;
> + uint32_t last_desc_idx;
> + uint32_t last_re_interval;
Minor nit: in this driver, the common practice is to follow reverse
Christmas tree declaration ordering where practical.
>
> pkts = txq->pkt_ring_dqo;
> txr = txq->tx_ring;
> @@ -331,20 +333,19 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf
> **tx_pkts, uint16_t nb_pkts)
> txd = &txr[(tx_id - 1) & mask];
> txd->pkt.end_of_packet = 1;
>
> + last_desc_idx = (tx_id - 1) & mask;
> + last_re_interval = (last_desc_idx - txq->last_re_idx) & mask;
> + if (unlikely(last_re_interval >= GVE_TX_MIN_RE_INTERVAL)) {
> + txd->pkt.report_event = true;
> + txq->last_re_idx = last_desc_idx;
Should we write the tail here? Allowing the device to start processing
packets right away instead of only at the end of TX might save some
failed bursts if dealing with a bursts of many-descriptor TSO packets.
The MMIO writes would also be amortized over RE_INTERVAL descriptors.
> + }
> +
> txq->nb_free -= nb_descs;
> txq->nb_used += nb_descs;
> }
>
> /* update the tail pointer if any packets were processed */
> if (nb_tx > 0) {
> - /* Request a descriptor completion on the last descriptor */
> - txq->re_cnt += nb_tx;
> - if (txq->re_cnt >= GVE_TX_MIN_RE_INTERVAL) {
> - txd = &txr[(tx_id - 1) & mask];
> - txd->pkt.report_event = true;
> - txq->re_cnt = 0;
> - }
> -
> rte_write32(tx_id, txq->qtx_tail);
> txq->tx_tail = tx_id;
>
> @@ -445,6 +446,7 @@ gve_reset_tx_ring_state_dqo(struct gve_tx_queue *txq)
> txq->nb_used = 0;
>
> txq->last_desc_cleaned = 0;
> + txq->last_re_idx = 0;
> txq->nb_free = txq->nb_tx_desc - 1;
>
> txq->complq_tail = 0;
> --
> 2.43.0
>