in efawin/verbs.c [1883:1947]
int efa_post_recv(struct ibv_qp *ibvqp, struct ibv_recv_wr *wr,
struct ibv_recv_wr **bad)
{
struct efa_qp *qp = to_efa_qp(ibvqp);
struct efa_wq *wq = &qp->rq.wq;
struct efa_io_rx_desc rx_buf;
uint32_t rq_desc_offset;
uintptr_t addr;
int err = 0;
size_t i;
pthread_spin_lock(&wq->wqlock);
while (wr) {
err = efa_post_recv_validate(qp, wr);
if (err) {
*bad = wr;
goto ring_db;
}
memset(&rx_buf, 0, sizeof(rx_buf));
rx_buf.req_id = efa_wq_get_next_wrid_idx_locked(wq, wr->wr_id);
wq->wqe_posted++;
/* Default init of the rx buffer */
EFA_SET(&rx_buf.lkey_ctrl, EFA_IO_RX_DESC_FIRST, 1);
EFA_SET(&rx_buf.lkey_ctrl, EFA_IO_RX_DESC_LAST, 0);
for (i = 0; i < wr->num_sge; i++) {
/* Set last indication if need) */
if (i == wr->num_sge - 1)
EFA_SET(&rx_buf.lkey_ctrl, EFA_IO_RX_DESC_LAST,
1);
addr = wr->sg_list[i].addr;
/* Set RX buffer desc from SGE */
rx_buf.length = wr->sg_list[i].length;
EFA_SET(&rx_buf.lkey_ctrl, EFA_IO_RX_DESC_LKEY,
wr->sg_list[i].lkey);
rx_buf.buf_addr_lo = addr;
rx_buf.buf_addr_hi = (uint64_t)addr >> 32;
/* Copy descriptor to RX ring */
rq_desc_offset = (wq->pc & wq->desc_mask) *
sizeof(rx_buf);
memcpy(qp->rq.buf + rq_desc_offset, &rx_buf, sizeof(rx_buf));
/* Wrap rx descriptor index */
wq->pc++;
if (!(wq->pc & wq->desc_mask))
wq->phase++;
/* reset descriptor for next iov */
memset(&rx_buf, 0, sizeof(rx_buf));
}
wr = wr->next;
}
ring_db:
efa_rq_ring_doorbell(&qp->rq, wq->pc);
pthread_spin_unlock(&wq->wqlock);
return err;
}