Vector PMD returns buffers to the application without setting the pointers in the Rx queue to null nor allocating them. When the PMD cleanup the ring it needs to take a special care to those pointers to not free the mbufs before the application have used them nor if the application have already freed them.
Signed-off-by: Nelio Laranjeiro <nelio.laranje...@6wind.com> Acked-by: Yongseok Koh <ys...@mellanox.com> --- drivers/net/mlx5/mlx5_rxq.c | 71 +++++++++++++------------------------------- drivers/net/mlx5/mlx5_rxtx.h | 3 +- 2 files changed, 21 insertions(+), 53 deletions(-) diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c index c90ec81..68dce04 100644 --- a/drivers/net/mlx5/mlx5_rxq.c +++ b/drivers/net/mlx5/mlx5_rxq.c @@ -634,41 +634,6 @@ priv_rehash_flows(struct priv *priv) } /** - * Unlike regular Rx function, vPMD Rx doesn't replace mbufs immediately when - * receiving packets. Instead it replaces later in bulk. In rxq->elts[], entries - * from rq_pi to rq_ci are owned by device but the rest is already delivered to - * application. In order not to reuse those mbufs by rxq_alloc_elts(), this - * function must be called to replace used mbufs. - * - * @param rxq - * Pointer to RX queue structure. - * - * @return - * 0 on success, errno value on failure. - */ -static int -rxq_trim_elts(struct rxq *rxq) -{ - const uint16_t q_n = (1 << rxq->elts_n); - const uint16_t q_mask = q_n - 1; - uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi); - uint16_t i; - - if (!rxq->trim_elts) - return 0; - for (i = 0; i < used; ++i) { - struct rte_mbuf *buf; - buf = rte_pktmbuf_alloc(rxq->mp); - if (!buf) - return ENOMEM; - (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = buf; - } - rxq->rq_pi = rxq->rq_ci; - rxq->trim_elts = 0; - return 0; -} - -/** * Allocate RX queue elements. * * @param rxq_ctrl @@ -739,7 +704,6 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) /* Padding with a fake mbuf for vectorized Rx. */ for (i = 0; i < MLX5_VPMD_DESCS_PER_LOOP; ++i) (*rxq->elts)[elts_n + i] = &rxq->fake_mbuf; - rxq->trim_elts = 1; } DEBUG("%p: allocated and configured %u segments (max %u packets)", (void *)rxq_ctrl, elts_n, elts_n / (1 << rxq_ctrl->rxq.sges_n)); @@ -766,16 +730,28 @@ rxq_alloc_elts(struct rxq_ctrl *rxq_ctrl, unsigned int elts_n) static void rxq_free_elts(struct rxq_ctrl *rxq_ctrl) { - unsigned int i; + struct rxq *rxq = &rxq_ctrl->rxq; + const uint16_t q_n = (1 << rxq->elts_n); + const uint16_t q_mask = q_n - 1; + uint16_t used = q_n - (rxq->rq_ci - rxq->rq_pi); + uint16_t i; DEBUG("%p: freeing WRs", (void *)rxq_ctrl); - if (rxq_ctrl->rxq.elts == NULL) + if (rxq->elts == NULL) return; - - for (i = 0; (i != (1u << rxq_ctrl->rxq.elts_n)); ++i) { - if ((*rxq_ctrl->rxq.elts)[i] != NULL) - rte_pktmbuf_free_seg((*rxq_ctrl->rxq.elts)[i]); - (*rxq_ctrl->rxq.elts)[i] = NULL; + /** + * Some mbuf in the Ring belongs to the application. They cannot be + * freed. + */ + if (rxq_check_vec_support(rxq) > 0) { + for (i = 0; i < used; ++i) + (*rxq->elts)[(rxq->rq_ci + i) & q_mask] = NULL; + rxq->rq_pi = rxq->rq_ci; + } + for (i = 0; (i != (1u << rxq->elts_n)); ++i) { + if ((*rxq->elts)[i] != NULL) + rte_pktmbuf_free_seg((*rxq->elts)[i]); + (*rxq->elts)[i] = NULL; } } @@ -1087,14 +1063,7 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl, (void *)dev, strerror(ret)); goto error; } - if (rxq_ctrl->rxq.elts_n) { - assert(1 << rxq_ctrl->rxq.elts_n == desc); - assert(rxq_ctrl->rxq.elts != tmpl.rxq.elts); - ret = rxq_trim_elts(&rxq_ctrl->rxq); - if (!ret) - ret = rxq_alloc_elts(&tmpl, desc); - } else - ret = rxq_alloc_elts(&tmpl, desc); + ret = rxq_alloc_elts(&tmpl, desc); if (ret) { ERROR("%p: RXQ allocation failed: %s", (void *)dev, strerror(ret)); diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h index 690b308..300d097 100644 --- a/drivers/net/mlx5/mlx5_rxtx.h +++ b/drivers/net/mlx5/mlx5_rxtx.h @@ -116,8 +116,7 @@ struct rxq { unsigned int rss_hash:1; /* RSS hash result is enabled. */ unsigned int mark:1; /* Marked flow available on the queue. */ unsigned int pending_err:1; /* CQE error needs to be handled. */ - unsigned int trim_elts:1; /* Whether elts needs clean-up. */ - unsigned int :6; /* Remaining bits. */ + unsigned int :7; /* Remaining bits. */ volatile uint32_t *rq_db; volatile uint32_t *cq_db; uint16_t rq_ci; -- 2.1.4