The GVNIC DQO hardware DMA engine prefetches descriptors in cacheline
units (64 bytes = 4 descriptors of 16 bytes each). When producer tail
and consumer head indices share a cacheline, CPU and device DMA memory
collisions can occur.
Align with the Linux driver (gve_has_tx_slots_available()) by requiring
GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP (4 descriptors) headroom when
checking descriptor availability before enqueueing packets.
Fixes: 4022f9999f56 ("net/gve: support basic Tx data path for DQO")
Cc: [email protected]
Signed-off-by: Tathagat Priyadarshi <[email protected]>
Acked-by: Joshua Washington <[email protected]>
---
drivers/net/gve/gve_tx_dqo.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 0839179d7f..eee1f10df1 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -260,6 +260,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts)
uint64_t bytes = 0;
const char *reason;
uint16_t compl_tag;
+ uint16_t req_descs;
uint64_t ol_flags;
uint16_t nb_descs;
uint16_t tx_id;
@@ -291,14 +292,17 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf
**tx_pkts, uint16_t nb_pkts)
nb_descs = gve_tx_pkt_nb_data_descs(tx_pkt);
nb_descs += tso;
+ req_descs = nb_descs + GVE_TX_MIN_DESC_PREVENT_CACHE_OVERLAP;
- /* Clean if there aren't enough descriptors to send the packet.
*/
- if (unlikely(!gve_can_tx(txq, nb_descs, 1))) {
+ /* Clean if there aren't enough descriptors to send the packet
+ * while maintaining the cacheline overlap margin.
+ */
+ if (unlikely(!gve_can_tx(txq, req_descs, 1))) {
int nb_to_clean = RTE_MAX(DQO_TX_MULTIPLIER *
txq->rs_thresh,
- nb_descs);
+ (int)req_descs);
gve_tx_clean_descs_dqo(txq, nb_to_clean);
- if (!gve_can_tx(txq, nb_descs, 1))
+ if (!gve_can_tx(txq, req_descs, 1))
break;
}
--
2.43.0