From: Mohammad Shuab Siddique <[email protected]> Hardware already reports an invalid/bad DMA address on a Tx BD via the TX_CMPL_ERRORS_DMA_ERROR bit in the Tx completion record, but the driver never inspected it, so a bad mbuf->buf_iova on Tx completed silently with no visibility.
Check the bit in bnxt_handle_tx_cp() and in the AVX2/SSE vector Tx-completion handlers, and count occurrences in a new per-queue tx_dma_err counter. The counter is folded into the standard oerrors stat and also exposed as a named xstat (tx_dma_err_pkts) for finer-grained visibility. Signed-off-by: Mohammad Shuab Siddique <[email protected]> --- drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 6 ++++++ drivers/net/bnxt/bnxt_rxtx_vec_sse.c | 6 ++++++ drivers/net/bnxt/bnxt_stats.c | 20 ++++++++++++++++++++ drivers/net/bnxt/bnxt_stats.h | 3 +++ drivers/net/bnxt/bnxt_txq.h | 1 + drivers/net/bnxt/bnxt_txr.c | 6 ++++++ 6 files changed, 42 insertions(+) diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c index 50b3602839..7f07b0a3e1 100644 --- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c +++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c @@ -743,6 +743,12 @@ bnxt_handle_tx_cp_vec(struct bnxt_tx_queue *txq) if (!bnxt_cpr_cmp_valid(txcmp, raw_cons, ring_mask + 1)) break; + uint16_t errors_v = rte_le_to_cpu_16(txcmp->errors_v); + + if (unlikely(errors_v & TX_CMPL_ERRORS_DMA_ERROR)) + rte_atomic_fetch_add_explicit(&txq->tx_dma_err, 1, + rte_memory_order_relaxed); + nb_tx_pkts += txcmp->opaque; raw_cons = NEXT_RAW_CMP(raw_cons); } while (nb_tx_pkts < ring_mask); diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_sse.c b/drivers/net/bnxt/bnxt_rxtx_vec_sse.c index 7d455b6f56..a97ff6f5fe 100644 --- a/drivers/net/bnxt/bnxt_rxtx_vec_sse.c +++ b/drivers/net/bnxt/bnxt_rxtx_vec_sse.c @@ -577,6 +577,12 @@ bnxt_handle_tx_cp_vec(struct bnxt_tx_queue *txq) if (!bnxt_cpr_cmp_valid(txcmp, raw_cons, ring_mask + 1)) break; + uint16_t errors_v = rte_le_to_cpu_16(txcmp->errors_v); + + if (unlikely(errors_v & TX_CMPL_ERRORS_DMA_ERROR)) + rte_atomic_fetch_add_explicit(&txq->tx_dma_err, 1, + rte_memory_order_relaxed); + if (likely(CMP_TYPE(txcmp) == TX_CMPL_TYPE_TX_L2)) nb_tx_pkts += txcmp->opaque; else diff --git a/drivers/net/bnxt/bnxt_stats.c b/drivers/net/bnxt/bnxt_stats.c index ba858710a5..52d2456b66 100644 --- a/drivers/net/bnxt/bnxt_stats.c +++ b/drivers/net/bnxt/bnxt_stats.c @@ -697,6 +697,8 @@ static int bnxt_stats_get_ext(struct rte_eth_dev *eth_dev, bnxt_stats->oerrors += rte_atomic_load_explicit(&txq->tx_mbuf_drop, rte_memory_order_relaxed); + bnxt_stats->oerrors += rte_atomic_load_explicit(&txq->tx_dma_err, + rte_memory_order_relaxed); if (!txq->tx_started) continue; @@ -774,6 +776,9 @@ int bnxt_stats_get_op(struct rte_eth_dev *eth_dev, bnxt_stats->oerrors += rte_atomic_load_explicit(&txq->tx_mbuf_drop, rte_memory_order_relaxed); + bnxt_stats->oerrors += + rte_atomic_load_explicit(&txq->tx_dma_err, + rte_memory_order_relaxed); } return rc; @@ -824,6 +829,7 @@ int bnxt_stats_reset_op(struct rte_eth_dev *eth_dev) struct bnxt_tx_queue *txq = bp->tx_queues[i]; txq->tx_mbuf_drop = 0; + txq->tx_dma_err = 0; } bnxt_clear_prev_stat(bp); @@ -927,6 +933,7 @@ int bnxt_dev_xstats_get_op(struct rte_eth_dev *eth_dev, RTE_DIM(bnxt_tx_stats_strings) + sz + RTE_DIM(bnxt_rx_ext_stats_strings) + RTE_DIM(bnxt_tx_ext_stats_strings) + + BNXT_NUM_SW_XSTATS + bnxt_flow_stats_cnt(bp); if (n < stat_count || xstats == NULL) @@ -1049,6 +1056,14 @@ int bnxt_dev_xstats_get_op(struct rte_eth_dev *eth_dev, count++; } + xstats[count].id = count; + xstats[count].value = 0; + for (i = 0; i < bp->tx_cp_nr_rings; i++) + xstats[count].value += + rte_atomic_load_explicit(&bp->tx_queues[i]->tx_dma_err, + rte_memory_order_relaxed); + count++; + if (bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_COUNTERS && bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_MGMT && BNXT_FLOW_XSTATS_EN(bp)) { @@ -1128,6 +1143,7 @@ int bnxt_dev_xstats_get_names_op(struct rte_eth_dev *eth_dev, sz + RTE_DIM(bnxt_rx_ext_stats_strings) + RTE_DIM(bnxt_tx_ext_stats_strings) + + BNXT_NUM_SW_XSTATS + bnxt_flow_stats_cnt(bp); if (xstats_names == NULL || size < stat_cnt) @@ -1181,6 +1197,10 @@ int bnxt_dev_xstats_get_names_op(struct rte_eth_dev *eth_dev, count++; } + strlcpy(xstats_names[count].name, "tx_dma_err_pkts", + sizeof(xstats_names[count].name)); + count++; + if (bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_COUNTERS && bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_MGMT && BNXT_FLOW_XSTATS_EN(bp)) { diff --git a/drivers/net/bnxt/bnxt_stats.h b/drivers/net/bnxt/bnxt_stats.h index c0508e773a..534b9af5e8 100644 --- a/drivers/net/bnxt/bnxt_stats.h +++ b/drivers/net/bnxt/bnxt_stats.h @@ -8,6 +8,9 @@ #include <ethdev_driver.h> +/* Number of software (non-HWRM) xstats appended after the FW-reported ones. */ +#define BNXT_NUM_SW_XSTATS 1 + void bnxt_free_stats(struct bnxt *bp); int bnxt_stats_get_op(struct rte_eth_dev *eth_dev, struct rte_eth_stats *bnxt_stats, struct eth_queue_stats *qstats); diff --git a/drivers/net/bnxt/bnxt_txq.h b/drivers/net/bnxt/bnxt_txq.h index ac8af91c57..525f841789 100644 --- a/drivers/net/bnxt/bnxt_txq.h +++ b/drivers/net/bnxt/bnxt_txq.h @@ -36,6 +36,7 @@ struct bnxt_tx_queue { struct rte_mbuf **free; uint64_t offloads; RTE_ATOMIC(uint64_t) tx_mbuf_drop; + RTE_ATOMIC(uint64_t) tx_dma_err; }; void bnxt_free_txq_stats(struct bnxt_tx_queue *txq); diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c index 3fae0824d1..edd99dc84a 100644 --- a/drivers/net/bnxt/bnxt_txr.c +++ b/drivers/net/bnxt/bnxt_txr.c @@ -782,6 +782,12 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq) if (!bnxt_cpr_cmp_valid(txcmp, raw_cons, ring_mask + 1)) break; + uint16_t errors_v = rte_le_to_cpu_16(txcmp->errors_v); + + if (unlikely(errors_v & TX_CMPL_ERRORS_DMA_ERROR)) + rte_atomic_fetch_add_explicit(&txq->tx_dma_err, 1, + rte_memory_order_relaxed); + if (CMP_TYPE(txcmp) == CMPL_BASE_TYPE_TX_L2_COAL) { struct tx_cmpl_coal *txcmp_c = (struct tx_cmpl_coal *)txcmp; -- 2.47.3

