*
* @param txq
* Pointer to Tx queue structure.
+ * @param elts_m
+ * Tx elements number mask.
+ * @param sq
+ * Pointer to the SQ structure.
*/
static void
-mlx4_txq_complete(struct txq *txq, const unsigned int elts_n,
- struct mlx4_sq *sq)
+mlx4_txq_complete(struct txq *txq, const unsigned int elts_m,
+ struct mlx4_sq *sq)
{
unsigned int elts_tail = txq->elts_tail;
struct mlx4_cq *cq = &txq->mcq;
if (unlikely(!completed))
return;
/* First stamping address is the end of the last one. */
- first_txbb = (&(*txq->elts)[elts_tail])->eocb;
+ first_txbb = (&(*txq->elts)[elts_tail & elts_m])->eocb;
elts_tail += completed;
- if (elts_tail >= elts_n)
- elts_tail -= elts_n;
/* The new tail element holds the end address. */
sq->remain_size += mlx4_txq_stamp_freed_wqe(sq, first_txbb,
- (&(*txq->elts)[elts_tail])->eocb);
+ (&(*txq->elts)[elts_tail & elts_m])->eocb);
/* Update CQ consumer index. */
cq->cons_index = cons_index;
*cq->set_ci_db = rte_cpu_to_be_32(cons_index & MLX4_CQ_DB_CI_MASK);
struct txq *txq = (struct txq *)dpdk_txq;
unsigned int elts_head = txq->elts_head;
const unsigned int elts_n = txq->elts_n;
+ const unsigned int elts_m = elts_n - 1;
unsigned int bytes_sent = 0;
unsigned int i;
unsigned int max;
assert(txq->elts_comp_cd != 0);
if (likely(txq->elts_comp != 0))
- mlx4_txq_complete(txq, elts_n, sq);
+ mlx4_txq_complete(txq, elts_m, sq);
max = (elts_n - (elts_head - txq->elts_tail));
- if (max > elts_n)
- max -= elts_n;
assert(max >= 1);
assert(max <= elts_n);
/* Always leave one free entry in the ring. */
--max;
if (max > pkts_n)
max = pkts_n;
- elt = &(*txq->elts)[elts_head];
+ elt = &(*txq->elts)[elts_head & elts_m];
/* First Tx burst element saves the next WQE control segment. */
ctrl = elt->wqe;
for (i = 0; (i != max); ++i) {
struct rte_mbuf *buf = pkts[i];
- unsigned int elts_head_next =
- (((elts_head + 1) == elts_n) ? 0 : elts_head + 1);
- struct txq_elt *elt_next = &(*txq->elts)[elts_head_next];
+ struct txq_elt *elt_next = &(*txq->elts)[++elts_head & elts_m];
uint32_t owner_opcode = sq->owner_opcode;
volatile struct mlx4_wqe_data_seg *dseg =
(volatile struct mlx4_wqe_data_seg *)(ctrl + 1);
ctrl->owner_opcode = rte_cpu_to_be_32(owner_opcode);
elt->buf = buf;
bytes_sent += buf->pkt_len;
- elts_head = elts_head_next;
ctrl = ctrl_next;
elt = elt_next;
}
rte_wmb();
/* Ring QP doorbell. */
rte_write32(txq->msq.doorbell_qpn, txq->msq.db);
- txq->elts_head = elts_head;
+ txq->elts_head += i;
txq->elts_comp += i;
return i;
}
unsigned int elts_head = txq->elts_head;
unsigned int elts_tail = txq->elts_tail;
struct txq_elt (*elts)[txq->elts_n] = txq->elts;
+ unsigned int elts_m = txq->elts_n - 1;
DEBUG("%p: freeing WRs", (void *)txq);
while (elts_tail != elts_head) {
- struct txq_elt *elt = &(*elts)[elts_tail];
+ struct txq_elt *elt = &(*elts)[elts_tail++ & elts_m];
assert(elt->buf != NULL);
rte_pktmbuf_free(elt->buf);
elt->buf = NULL;
elt->wqe = NULL;
- if (++elts_tail == RTE_DIM(*elts))
- elts_tail = 0;
}
txq->elts_tail = txq->elts_head;
}
struct mlx4dv_obj mlxdv;
struct mlx4dv_qp dv_qp;
struct mlx4dv_cq dv_cq;
- struct txq_elt (*elts)[desc];
+ struct txq_elt (*elts)[rte_align32pow2(desc)];
struct ibv_qp_init_attr qp_init_attr;
struct txq *txq;
uint8_t *bounce_buf;
ERROR("%p: invalid number of Tx descriptors", (void *)dev);
return -rte_errno;
}
+ if (desc != RTE_DIM(*elts)) {
+ desc = RTE_DIM(*elts);
+ WARN("%p: increased number of descriptors in Tx queue %u"
+ " to the next power of two (%u)",
+ (void *)dev, idx, desc);
+ }
/* Allocate and initialize Tx queue. */
mlx4_zmallocv_socket("TXQ", vec, RTE_DIM(vec), socket);
if (!txq) {