-/**
- * Manage TX completions.
- *
- * When sending a burst, mlx5_tx_burst() posts several WRs.
- *
- * @param txq
- * Pointer to TX queue structure.
- */
-static inline void
-txq_complete(struct txq *txq)
-{
- const unsigned int elts_n = 1 << txq->elts_n;
- const unsigned int cqe_n = 1 << txq->cqe_n;
- const unsigned int cqe_cnt = cqe_n - 1;
- uint16_t elts_free = txq->elts_tail;
- uint16_t elts_tail;
- uint16_t cq_ci = txq->cq_ci;
- volatile struct mlx5_cqe *cqe = NULL;
- volatile struct mlx5_wqe_ctrl *ctrl;
-
- do {
- volatile struct mlx5_cqe *tmp;
-
- tmp = &(*txq->cqes)[cq_ci & cqe_cnt];
- if (check_cqe(tmp, cqe_n, cq_ci))
- break;
- cqe = tmp;
-#ifndef NDEBUG
- if (MLX5_CQE_FORMAT(cqe->op_own) == MLX5_COMPRESSED) {
- if (!check_cqe_seen(cqe))
- ERROR("unexpected compressed CQE, TX stopped");
- return;
- }
- if ((MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_RESP_ERR) ||
- (MLX5_CQE_OPCODE(cqe->op_own) == MLX5_CQE_REQ_ERR)) {
- if (!check_cqe_seen(cqe))
- ERROR("unexpected error CQE, TX stopped");
- return;
- }
-#endif /* NDEBUG */
- ++cq_ci;
- } while (1);
- if (unlikely(cqe == NULL))
- return;
- txq->wqe_pi = ntohs(cqe->wqe_counter);
- ctrl = (volatile struct mlx5_wqe_ctrl *)
- tx_mlx5_wqe(txq, txq->wqe_pi);
- elts_tail = ctrl->ctrl3;
- assert(elts_tail < (1 << txq->wqe_n));
- /* Free buffers. */
- while (elts_free != elts_tail) {
- struct rte_mbuf *elt = (*txq->elts)[elts_free];
- unsigned int elts_free_next =
- (elts_free + 1) & (elts_n - 1);
- struct rte_mbuf *elt_next = (*txq->elts)[elts_free_next];
-
-#ifndef NDEBUG
- /* Poisoning. */
- memset(&(*txq->elts)[elts_free],
- 0x66,
- sizeof((*txq->elts)[elts_free]));
-#endif
- RTE_MBUF_PREFETCH_TO_FREE(elt_next);
- /* Only one segment needs to be freed. */
- rte_pktmbuf_free_seg(elt);
- elts_free = elts_free_next;
- }
- txq->cq_ci = cq_ci;
- txq->elts_tail = elts_tail;
- /* Update the consumer index. */
- rte_wmb();
- *txq->cq_db = htonl(cq_ci);
-}
-
-/**
- * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which
- * the cloned mbuf is allocated is returned instead.
- *
- * @param buf
- * Pointer to mbuf.
- *
- * @return
- * Memory pool where data is located for given mbuf.
- */
-static struct rte_mempool *
-txq_mb2mp(struct rte_mbuf *buf)
-{
- if (unlikely(RTE_MBUF_INDIRECT(buf)))
- return rte_mbuf_from_indirect(buf)->pool;
- return buf->pool;
-}
-
-/**
- * Get Memory Region (MR) <-> Memory Pool (MP) association from txq->mp2mr[].
- * Add MP to txq->mp2mr[] if it's not registered yet. If mp2mr[] is full,
- * remove an entry first.
- *
- * @param txq
- * Pointer to TX queue structure.
- * @param[in] mp
- * Memory Pool for which a Memory Region lkey must be returned.
- *
- * @return
- * mr->lkey on success, (uint32_t)-1 on failure.
- */
-static inline uint32_t
-txq_mp2mr(struct txq *txq, struct rte_mempool *mp)
-{
- unsigned int i;
- uint32_t lkey = (uint32_t)-1;
-
- for (i = 0; (i != RTE_DIM(txq->mp2mr)); ++i) {
- if (unlikely(txq->mp2mr[i].mp == NULL)) {
- /* Unknown MP, add a new MR for it. */
- break;
- }
- if (txq->mp2mr[i].mp == mp) {
- assert(txq->mp2mr[i].lkey != (uint32_t)-1);
- assert(htonl(txq->mp2mr[i].mr->lkey) ==
- txq->mp2mr[i].lkey);
- lkey = txq->mp2mr[i].lkey;
- break;
- }
- }
- if (unlikely(lkey == (uint32_t)-1))
- lkey = txq_mp2mr_reg(txq, mp, i);
- return lkey;
-}
-
-/**
- * Ring TX queue doorbell.
- *
- * @param txq
- * Pointer to TX queue structure.
- * @param wqe
- * Pointer to the last WQE posted in the NIC.
- */
-static inline void
-mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
-{
- uint64_t *dst = (uint64_t *)((uintptr_t)txq->bf_reg);
- volatile uint64_t *src = ((volatile uint64_t *)wqe);
-
- rte_wmb();
- *txq->qp_db = htonl(txq->wqe_ci);
- /* Ensure ordering between DB record and BF copy. */
- rte_wmb();
- *dst = *src;
-}
-