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]

Acked-by: Joshua Washington <[email protected]>
Signed-off-by: Tathagat Priyadarshi <[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 a8382ff3c4..9210b02eb1 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -261,6 +261,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, 
uint16_t nb_pkts)
        uint16_t nb_tx = 0;
        uint64_t bytes = 0;
        uint64_t ol_flags;
+       uint16_t req_descs;
        uint16_t nb_descs;
        bool csum, tso;
        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

Reply via email to