in efawin/verbs.c [1773:1834]
static int efa_send_wr_complete(struct ibv_qp_ex *ibvqpx)
{
struct efa_qp *qp = to_efa_qp_ex(ibvqpx);
struct efa_sq *sq = &qp->sq;
uint32_t max_txbatch = sq->max_batch_wr;
uint32_t num_wqe_to_copy;
uint16_t local_idx = 0;
uint16_t curbatch = 0;
uint16_t sq_desc_idx;
uint16_t pc;
if (unlikely(qp->wr_session_err)) {
efa_sq_roll_back(sq);
goto out;
}
/*
* Copy local queue to device in chunks, handling wraparound and max
* doorbell batch.
*/
pc = sq->wq.pc - sq->num_wqe_pending;
sq_desc_idx = pc & sq->wq.desc_mask;
/* mmio_wc_start() comes from efa_send_wr_start() */
while (sq->num_wqe_pending) {
num_wqe_to_copy = min3(sq->num_wqe_pending,
sq->wq.wqe_cnt - sq_desc_idx,
max_txbatch - curbatch);
mmio_memcpy_x64((struct efa_io_tx_wqe *)sq->desc +
sq_desc_idx,
(struct efa_io_tx_wqe *)sq->local_queue +
local_idx,
num_wqe_to_copy * sizeof(struct efa_io_tx_wqe));
sq->num_wqe_pending -= num_wqe_to_copy;
local_idx += num_wqe_to_copy;
curbatch += num_wqe_to_copy;
pc += num_wqe_to_copy;
sq_desc_idx = (sq_desc_idx + num_wqe_to_copy) &
sq->wq.desc_mask;
if (curbatch == max_txbatch) {
mmio_flush_writes();
efa_sq_ring_doorbell(sq, pc);
curbatch = 0;
mmio_wc_start();
}
}
if (curbatch) {
mmio_flush_writes();
efa_sq_ring_doorbell(sq, sq->wq.pc);
}
out:
/*
* Not using mmio_wc_spinunlock as the doorbell write should be done
* inside the lock.
*/
pthread_spin_unlock(&sq->wq.wqlock);
return qp->wr_session_err;
}