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
)
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
)) {
72 memset(cqe1
, 0, sizeof(*cqe1
));
73 cqe1
->wr_id
= cqe
->wr_id
;
75 cqe1
->opcode
= cqe
->opcode
;
76 cqe1
->status
= cqe
->status
;
77 cqe1
->vendor_err
= cqe
->vendor_err
;
79 pvrdma_ring_write_inc(ring
);
81 /* Step #2: Put CQ number on dsr completion ring */
82 pr_dbg("Writing CQNE\n");
83 cqne
= pvrdma_ring_next_elem_write(&dev
->dsr_info
.cq
);
84 if (unlikely(!cqne
)) {
88 cqne
->info
= cq_handle
;
89 pvrdma_ring_write_inc(&dev
->dsr_info
.cq
);
91 pr_dbg("cq->notify=%d\n", cq
->notify
);
94 post_interrupt(dev
, INTR_VEC_CMD_COMPLETION_Q
);
100 static void pvrdma_qp_ops_comp_handler(int status
, unsigned int vendor_err
,
103 CompHandlerCtx
*comp_ctx
= (CompHandlerCtx
*)ctx
;
105 pr_dbg("cq_handle=%d\n", comp_ctx
->cq_handle
);
106 pr_dbg("wr_id=%" PRIx64
"\n", comp_ctx
->cqe
.wr_id
);
107 pr_dbg("status=%d\n", status
);
108 pr_dbg("vendor_err=0x%x\n", vendor_err
);
109 comp_ctx
->cqe
.status
= status
;
110 comp_ctx
->cqe
.vendor_err
= vendor_err
;
111 pvrdma_post_cqe(comp_ctx
->dev
, comp_ctx
->cq_handle
, &comp_ctx
->cqe
);
115 void pvrdma_qp_ops_fini(void)
117 rdma_backend_unregister_comp_handler();
120 int pvrdma_qp_ops_init(void)
122 rdma_backend_register_comp_handler(pvrdma_qp_ops_comp_handler
);
127 int pvrdma_qp_send(PVRDMADev
*dev
, uint32_t qp_handle
)
133 pr_dbg("qp_handle=0x%x\n", qp_handle
);
135 qp
= rdma_rm_get_qp(&dev
->rdma_dev_res
, qp_handle
);
140 ring
= (PvrdmaRing
*)qp
->opaque
;
141 pr_dbg("sring=%p\n", ring
);
143 wqe
= (struct PvrdmaSqWqe
*)pvrdma_ring_next_elem_read(ring
);
145 CompHandlerCtx
*comp_ctx
;
147 pr_dbg("wr_id=%" PRIx64
"\n", wqe
->hdr
.wr_id
);
150 comp_ctx
= g_malloc(sizeof(CompHandlerCtx
));
152 comp_ctx
->cq_handle
= qp
->send_cq_handle
;
153 comp_ctx
->cqe
.wr_id
= wqe
->hdr
.wr_id
;
154 comp_ctx
->cqe
.qp
= qp_handle
;
155 comp_ctx
->cqe
.opcode
= wqe
->hdr
.opcode
;
157 rdma_backend_post_send(&dev
->backend_dev
, &qp
->backend_qp
, qp
->qp_type
,
158 (struct ibv_sge
*)&wqe
->sge
[0], wqe
->hdr
.num_sge
,
159 (union ibv_gid
*)wqe
->hdr
.wr
.ud
.av
.dgid
,
160 wqe
->hdr
.wr
.ud
.remote_qpn
,
161 wqe
->hdr
.wr
.ud
.remote_qkey
, comp_ctx
);
163 pvrdma_ring_read_inc(ring
);
165 wqe
= pvrdma_ring_next_elem_read(ring
);
171 int pvrdma_qp_recv(PVRDMADev
*dev
, uint32_t qp_handle
)
177 pr_dbg("qp_handle=0x%x\n", qp_handle
);
179 qp
= rdma_rm_get_qp(&dev
->rdma_dev_res
, qp_handle
);
184 ring
= &((PvrdmaRing
*)qp
->opaque
)[1];
185 pr_dbg("rring=%p\n", ring
);
187 wqe
= (struct PvrdmaRqWqe
*)pvrdma_ring_next_elem_read(ring
);
189 CompHandlerCtx
*comp_ctx
;
191 pr_dbg("wr_id=%" PRIx64
"\n", wqe
->hdr
.wr_id
);
194 comp_ctx
= g_malloc(sizeof(CompHandlerCtx
));
196 comp_ctx
->cq_handle
= qp
->recv_cq_handle
;
197 comp_ctx
->cqe
.qp
= qp_handle
;
198 comp_ctx
->cqe
.wr_id
= wqe
->hdr
.wr_id
;
200 rdma_backend_post_recv(&dev
->backend_dev
, &dev
->rdma_dev_res
,
201 &qp
->backend_qp
, qp
->qp_type
,
202 (struct ibv_sge
*)&wqe
->sge
[0], wqe
->hdr
.num_sge
,
205 pvrdma_ring_read_inc(ring
);
207 wqe
= pvrdma_ring_next_elem_read(ring
);
213 void pvrdma_cq_poll(RdmaDeviceResources
*dev_res
, uint32_t cq_handle
)
217 cq
= rdma_rm_get_cq(dev_res
, cq_handle
);
219 pr_dbg("Invalid CQ# %d\n", cq_handle
);
223 rdma_backend_poll_cq(dev_res
, &cq
->backend_cq
);