aboutsummaryrefslogtreecommitdiff
path: root/hw/rdma/vmw/pvrdma_cmd.c
diff options
context:
space:
mode:
authorKamal Heib <kamalheib1@gmail.com>2019-04-03 14:33:43 +0300
committerMarcel Apfelbaum <marcel.apfelbaum@gmail.com>2019-05-04 15:55:56 +0300
commit355b7cf356b7f506ca1b716647cc0cf19d312fd2 (patch)
treedeb3c03e8ae3fd4328b0082b9d9c29ec0fc10ba4 /hw/rdma/vmw/pvrdma_cmd.c
parent8b42cfab82f404389746dc71852dc88eacb40e8e (diff)
hw/pvrdma: Add support for SRQ
Implement the pvrdma device commands for supporting SRQ Signed-off-by: Kamal Heib <kamalheib1@gmail.com> Message-Id: <20190403113343.26384-5-kamalheib1@gmail.com> Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com> Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Diffstat (limited to 'hw/rdma/vmw/pvrdma_cmd.c')
-rw-r--r--hw/rdma/vmw/pvrdma_cmd.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/hw/rdma/vmw/pvrdma_cmd.c b/hw/rdma/vmw/pvrdma_cmd.c
index b931bb6dc9..8d70c0d23d 100644
--- a/hw/rdma/vmw/pvrdma_cmd.c
+++ b/hw/rdma/vmw/pvrdma_cmd.c
@@ -609,6 +609,149 @@ static int destroy_uc(PVRDMADev *dev, union pvrdma_cmd_req *req,
return 0;
}
+static int create_srq_ring(PCIDevice *pci_dev, PvrdmaRing **ring,
+ uint64_t pdir_dma, uint32_t max_wr,
+ uint32_t max_sge, uint32_t nchunks)
+{
+ uint64_t *dir = NULL, *tbl = NULL;
+ PvrdmaRing *r;
+ int rc = -EINVAL;
+ char ring_name[MAX_RING_NAME_SZ];
+ uint32_t wqe_sz;
+
+ if (!nchunks || nchunks > PVRDMA_MAX_FAST_REG_PAGES) {
+ rdma_error_report("Got invalid page count for SRQ ring: %d",
+ nchunks);
+ return rc;
+ }
+
+ dir = rdma_pci_dma_map(pci_dev, pdir_dma, TARGET_PAGE_SIZE);
+ if (!dir) {
+ rdma_error_report("Failed to map to SRQ page directory");
+ goto out;
+ }
+
+ tbl = rdma_pci_dma_map(pci_dev, dir[0], TARGET_PAGE_SIZE);
+ if (!tbl) {
+ rdma_error_report("Failed to map to SRQ page table");
+ goto out;
+ }
+
+ r = g_malloc(sizeof(*r));
+ *ring = r;
+
+ r->ring_state = (struct pvrdma_ring *)
+ rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
+ if (!r->ring_state) {
+ rdma_error_report("Failed to map tp SRQ ring state");
+ goto out_free_ring_mem;
+ }
+
+ wqe_sz = pow2ceil(sizeof(struct pvrdma_rq_wqe_hdr) +
+ sizeof(struct pvrdma_sge) * max_sge - 1);
+ sprintf(ring_name, "srq_ring_%" PRIx64, pdir_dma);
+ rc = pvrdma_ring_init(r, ring_name, pci_dev, &r->ring_state[1], max_wr,
+ wqe_sz, (dma_addr_t *)&tbl[1], nchunks - 1);
+ if (rc) {
+ goto out_unmap_ring_state;
+ }
+
+ goto out;
+
+out_unmap_ring_state:
+ rdma_pci_dma_unmap(pci_dev, r->ring_state, TARGET_PAGE_SIZE);
+
+out_free_ring_mem:
+ g_free(r);
+
+out:
+ rdma_pci_dma_unmap(pci_dev, tbl, TARGET_PAGE_SIZE);
+ rdma_pci_dma_unmap(pci_dev, dir, TARGET_PAGE_SIZE);
+
+ return rc;
+}
+
+static void destroy_srq_ring(PvrdmaRing *ring)
+{
+ pvrdma_ring_free(ring);
+ rdma_pci_dma_unmap(ring->dev, ring->ring_state, TARGET_PAGE_SIZE);
+ g_free(ring);
+}
+
+static int create_srq(PVRDMADev *dev, union pvrdma_cmd_req *req,
+ union pvrdma_cmd_resp *rsp)
+{
+ struct pvrdma_cmd_create_srq *cmd = &req->create_srq;
+ struct pvrdma_cmd_create_srq_resp *resp = &rsp->create_srq_resp;
+ PvrdmaRing *ring = NULL;
+ int rc;
+
+ memset(resp, 0, sizeof(*resp));
+
+ rc = create_srq_ring(PCI_DEVICE(dev), &ring, cmd->pdir_dma,
+ cmd->attrs.max_wr, cmd->attrs.max_sge,
+ cmd->nchunks);
+ if (rc) {
+ return rc;
+ }
+
+ rc = rdma_rm_alloc_srq(&dev->rdma_dev_res, cmd->pd_handle,
+ cmd->attrs.max_wr, cmd->attrs.max_sge,
+ cmd->attrs.srq_limit, &resp->srqn, ring);
+ if (rc) {
+ destroy_srq_ring(ring);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int query_srq(PVRDMADev *dev, union pvrdma_cmd_req *req,
+ union pvrdma_cmd_resp *rsp)
+{
+ struct pvrdma_cmd_query_srq *cmd = &req->query_srq;
+ struct pvrdma_cmd_query_srq_resp *resp = &rsp->query_srq_resp;
+
+ memset(resp, 0, sizeof(*resp));
+
+ return rdma_rm_query_srq(&dev->rdma_dev_res, cmd->srq_handle,
+ (struct ibv_srq_attr *)&resp->attrs);
+}
+
+static int modify_srq(PVRDMADev *dev, union pvrdma_cmd_req *req,
+ union pvrdma_cmd_resp *rsp)
+{
+ struct pvrdma_cmd_modify_srq *cmd = &req->modify_srq;
+
+ /* Only support SRQ limit */
+ if (!(cmd->attr_mask & IBV_SRQ_LIMIT) ||
+ (cmd->attr_mask & IBV_SRQ_MAX_WR))
+ return -EINVAL;
+
+ return rdma_rm_modify_srq(&dev->rdma_dev_res, cmd->srq_handle,
+ (struct ibv_srq_attr *)&cmd->attrs,
+ cmd->attr_mask);
+}
+
+static int destroy_srq(PVRDMADev *dev, union pvrdma_cmd_req *req,
+ union pvrdma_cmd_resp *rsp)
+{
+ struct pvrdma_cmd_destroy_srq *cmd = &req->destroy_srq;
+ RdmaRmSRQ *srq;
+ PvrdmaRing *ring;
+
+ srq = rdma_rm_get_srq(&dev->rdma_dev_res, cmd->srq_handle);
+ if (!srq) {
+ return -EINVAL;
+ }
+
+ ring = (PvrdmaRing *)srq->opaque;
+ destroy_srq_ring(ring);
+ rdma_rm_dealloc_srq(&dev->rdma_dev_res, cmd->srq_handle);
+
+ return 0;
+}
+
struct cmd_handler {
uint32_t cmd;
uint32_t ack;
@@ -634,6 +777,10 @@ static struct cmd_handler cmd_handlers[] = {
{PVRDMA_CMD_DESTROY_UC, PVRDMA_CMD_DESTROY_UC_RESP_NOOP, destroy_uc},
{PVRDMA_CMD_CREATE_BIND, PVRDMA_CMD_CREATE_BIND_RESP_NOOP, create_bind},
{PVRDMA_CMD_DESTROY_BIND, PVRDMA_CMD_DESTROY_BIND_RESP_NOOP, destroy_bind},
+ {PVRDMA_CMD_CREATE_SRQ, PVRDMA_CMD_CREATE_SRQ_RESP, create_srq},
+ {PVRDMA_CMD_QUERY_SRQ, PVRDMA_CMD_QUERY_SRQ_RESP, query_srq},
+ {PVRDMA_CMD_MODIFY_SRQ, PVRDMA_CMD_MODIFY_SRQ_RESP, modify_srq},
+ {PVRDMA_CMD_DESTROY_SRQ, PVRDMA_CMD_DESTROY_SRQ_RESP, destroy_srq},
};
int pvrdma_exec_cmd(PVRDMADev *dev)