2 * QEMU paravirtual RDMA - QP implementation
4 * Copyright (C) 2018 Oracle
5 * Copyright (C) 2018 Red Hat Inc
8 * Yuval Shaia <yuval.shaia@oracle.com>
9 * Marcel Apfelbaum <marcel@redhat.com>
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
16 #include "qemu/osdep.h"
18 #include "../rdma_utils.h"
19 #include "../rdma_rm.h"
20 #include "../rdma_backend.h"
23 #include "standard-headers/rdma/vmw_pvrdma-abi.h"
24 #include "pvrdma_qp_ops.h"
26 typedef struct CompHandlerCtx
{
29 struct pvrdma_cqe cqe
;
33 typedef struct PvrdmaSqWqe
{
34 struct pvrdma_sq_wqe_hdr hdr
;
35 struct pvrdma_sge sge
[0];
39 typedef struct PvrdmaRqWqe
{
40 struct pvrdma_rq_wqe_hdr hdr
;
41 struct pvrdma_sge sge
[0];
45 * 1. Put CQE on send CQ ring
46 * 2. Put CQ number on dsr completion ring
49 static int pvrdma_post_cqe(PVRDMADev
*dev
, uint32_t cq_handle
,
50 struct pvrdma_cqe
*cqe
, struct ibv_wc
*wc
)
52 struct pvrdma_cqe
*cqe1
;
53 struct pvrdma_cqne
*cqne
;
55 RdmaRmCQ
*cq
= rdma_rm_get_cq(&dev
->rdma_dev_res
, cq_handle
);
58 pr_dbg("Invalid cqn %d\n", cq_handle
);
62 ring
= (PvrdmaRing
*)cq
->opaque
;
63 pr_dbg("ring=%p\n", ring
);
65 /* Step #1: Put CQE on CQ ring */
66 pr_dbg("Writing CQE\n");
67 cqe1
= pvrdma_ring_next_elem_write(ring
);
68 if (unlikely(!cqe1
)) {
69 pr_dbg("No CQEs in ring\n");
73 memset(cqe1
, 0, sizeof(*cqe1
));
74 cqe1
->wr_id
= cqe
->wr_id
;
76 cqe1
->opcode
= cqe
->opcode
;
77 cqe1
->status
= wc
->status
;
78 cqe1
->byte_len
= wc
->byte_len
;
79 cqe1
->src_qp
= wc
->src_qp
;
80 cqe1
->wc_flags
= wc
->wc_flags
;
81 cqe1
->vendor_err
= wc
->vendor_err
;
83 pr_dbg("wr_id=%" PRIx64
"\n", cqe1
->wr_id
);
84 pr_dbg("qp=0x%lx\n", cqe1
->qp
);
85 pr_dbg("opcode=%d\n", cqe1
->opcode
);
86 pr_dbg("status=%d\n", cqe1
->status
);
87 pr_dbg("byte_len=%d\n", cqe1
->byte_len
);
88 pr_dbg("src_qp=%d\n", cqe1
->src_qp
);
89 pr_dbg("wc_flags=%d\n", cqe1
->wc_flags
);
90 pr_dbg("vendor_err=%d\n", cqe1
->vendor_err
);
92 pvrdma_ring_write_inc(ring
);
94 /* Step #2: Put CQ number on dsr completion ring */
95 pr_dbg("Writing CQNE\n");
96 cqne
= pvrdma_ring_next_elem_write(&dev
->dsr_info
.cq
);
97 if (unlikely(!cqne
)) {
101 cqne
->info
= cq_handle
;
102 pvrdma_ring_write_inc(&dev
->dsr_info
.cq
);
104 pr_dbg("cq->notify=%d\n", cq
->notify
);
105 if (cq
->notify
!= CNT_CLEAR
) {
106 if (cq
->notify
== CNT_ARM
) {
107 cq
->notify
= CNT_CLEAR
;
109 post_interrupt(dev
, INTR_VEC_CMD_COMPLETION_Q
);
115 static void pvrdma_qp_ops_comp_handler(void *ctx
, struct ibv_wc
*wc
)
117 CompHandlerCtx
*comp_ctx
= (CompHandlerCtx
*)ctx
;
119 pvrdma_post_cqe(comp_ctx
->dev
, comp_ctx
->cq_handle
, &comp_ctx
->cqe
, wc
);
124 void pvrdma_qp_ops_fini(void)
126 rdma_backend_unregister_comp_handler();
129 int pvrdma_qp_ops_init(void)
131 rdma_backend_register_comp_handler(pvrdma_qp_ops_comp_handler
);
136 int pvrdma_qp_send(PVRDMADev
*dev
, uint32_t qp_handle
)
144 pr_dbg("qp_handle=0x%x\n", qp_handle
);
146 qp
= rdma_rm_get_qp(&dev
->rdma_dev_res
, qp_handle
);
151 ring
= (PvrdmaRing
*)qp
->opaque
;
152 pr_dbg("sring=%p\n", ring
);
154 wqe
= (struct PvrdmaSqWqe
*)pvrdma_ring_next_elem_read(ring
);
156 CompHandlerCtx
*comp_ctx
;
158 pr_dbg("wr_id=%" PRIx64
"\n", wqe
->hdr
.wr_id
);
161 comp_ctx
= g_malloc(sizeof(CompHandlerCtx
));
163 comp_ctx
->cq_handle
= qp
->send_cq_handle
;
164 comp_ctx
->cqe
.wr_id
= wqe
->hdr
.wr_id
;
165 comp_ctx
->cqe
.qp
= qp_handle
;
166 comp_ctx
->cqe
.opcode
= IBV_WC_SEND
;
168 sgid
= rdma_rm_get_gid(&dev
->rdma_dev_res
, wqe
->hdr
.wr
.ud
.av
.gid_index
);
170 pr_dbg("Fail to get gid for idx %d\n", wqe
->hdr
.wr
.ud
.av
.gid_index
);
173 pr_dbg("sgid_id=%d, sgid=0x%llx\n", wqe
->hdr
.wr
.ud
.av
.gid_index
,
174 sgid
->global
.interface_id
);
176 sgid_idx
= rdma_rm_get_backend_gid_index(&dev
->rdma_dev_res
,
178 wqe
->hdr
.wr
.ud
.av
.gid_index
);
180 pr_dbg("Fail to get bk sgid_idx for sgid_idx %d\n",
181 wqe
->hdr
.wr
.ud
.av
.gid_index
);
185 rdma_backend_post_send(&dev
->backend_dev
, &qp
->backend_qp
, qp
->qp_type
,
186 (struct ibv_sge
*)&wqe
->sge
[0], wqe
->hdr
.num_sge
,
188 (union ibv_gid
*)wqe
->hdr
.wr
.ud
.av
.dgid
,
189 wqe
->hdr
.wr
.ud
.remote_qpn
,
190 wqe
->hdr
.wr
.ud
.remote_qkey
, comp_ctx
);
192 pvrdma_ring_read_inc(ring
);
194 wqe
= pvrdma_ring_next_elem_read(ring
);
200 int pvrdma_qp_recv(PVRDMADev
*dev
, uint32_t qp_handle
)
206 pr_dbg("qp_handle=0x%x\n", qp_handle
);
208 qp
= rdma_rm_get_qp(&dev
->rdma_dev_res
, qp_handle
);
213 ring
= &((PvrdmaRing
*)qp
->opaque
)[1];
214 pr_dbg("rring=%p\n", ring
);
216 wqe
= (struct PvrdmaRqWqe
*)pvrdma_ring_next_elem_read(ring
);
218 CompHandlerCtx
*comp_ctx
;
220 pr_dbg("wr_id=%" PRIx64
"\n", wqe
->hdr
.wr_id
);
223 comp_ctx
= g_malloc(sizeof(CompHandlerCtx
));
225 comp_ctx
->cq_handle
= qp
->recv_cq_handle
;
226 comp_ctx
->cqe
.wr_id
= wqe
->hdr
.wr_id
;
227 comp_ctx
->cqe
.qp
= qp_handle
;
228 comp_ctx
->cqe
.opcode
= IBV_WC_RECV
;
230 rdma_backend_post_recv(&dev
->backend_dev
, &dev
->rdma_dev_res
,
231 &qp
->backend_qp
, qp
->qp_type
,
232 (struct ibv_sge
*)&wqe
->sge
[0], wqe
->hdr
.num_sge
,
235 pvrdma_ring_read_inc(ring
);
237 wqe
= pvrdma_ring_next_elem_read(ring
);
243 void pvrdma_cq_poll(RdmaDeviceResources
*dev_res
, uint32_t cq_handle
)
247 cq
= rdma_rm_get_cq(dev_res
, cq_handle
);
249 pr_dbg("Invalid CQ# %d\n", cq_handle
);
253 rdma_backend_poll_cq(dev_res
, &cq
->backend_cq
);