From: Leon Romanovsky <[email protected]>

Separate the CQ creation logic into distinct kernel and user flows. The ionic
driver may allocate two umems per CQ, and the current layout prevents it from
supporting generic umem sources (VMA, dmabuf, memfd, and others).

Signed-off-by: Leon Romanovsky <[email protected]>
---
 drivers/infiniband/hw/ionic/ionic_controlpath.c | 88 +++++++++++++++++--------
 drivers/infiniband/hw/ionic/ionic_ibdev.c       |  1 +
 drivers/infiniband/hw/ionic/ionic_ibdev.h       |  2 +
 3 files changed, 64 insertions(+), 27 deletions(-)

diff --git a/drivers/infiniband/hw/ionic/ionic_controlpath.c 
b/drivers/infiniband/hw/ionic/ionic_controlpath.c
index ea12d9b8e125..5b8b6baaf5d4 100644
--- a/drivers/infiniband/hw/ionic/ionic_controlpath.c
+++ b/drivers/infiniband/hw/ionic/ionic_controlpath.c
@@ -89,7 +89,7 @@ int ionic_create_cq_common(struct ionic_vcq *vcq,
 
        cq->vcq = vcq;
 
-       if (attr->cqe < 1 || attr->cqe + IONIC_CQ_GRACE > 0xffff) {
+       if (attr->cqe > 0xffff - IONIC_CQ_GRACE) {
                rc = -EINVAL;
                goto err_args;
        }
@@ -1209,8 +1209,8 @@ static int ionic_destroy_cq_cmd(struct ionic_ibdev *dev, 
u32 cqid)
        return ionic_admin_wait(dev, &wr, IONIC_ADMIN_F_TEARDOWN);
 }
 
-int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
-                   struct uverbs_attr_bundle *attrs)
+int ionic_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr 
*attr,
+                        struct uverbs_attr_bundle *attrs)
 {
        struct ionic_ibdev *dev = to_ionic_ibdev(ibcq->device);
        struct ib_udata *udata = &attrs->driver_udata;
@@ -1222,21 +1222,18 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct 
ib_cq_init_attr *attr,
        struct ionic_cq_req req;
        int udma_idx = 0, rc;
 
-       if (udata) {
-               rc = ib_copy_from_udata(&req, udata, sizeof(req));
-               if (rc)
-                       return rc;
-       }
+       if (ibcq->umem)
+               return -EOPNOTSUPP;
 
-       vcq->udma_mask = BIT(dev->lif_cfg.udma_count) - 1;
+       rc = ib_copy_from_udata(&req, udata, sizeof(req));
+       if (rc)
+               return rc;
 
-       if (udata)
-               vcq->udma_mask &= req.udma_mask;
+       vcq->udma_mask = BIT(dev->lif_cfg.udma_count) - 1;
+       vcq->udma_mask &= req.udma_mask;
 
-       if (!vcq->udma_mask) {
-               rc = -EINVAL;
-               goto err_init;
-       }
+       if (!vcq->udma_mask)
+               return -EINVAL;
 
        for (; udma_idx < dev->lif_cfg.udma_count; ++udma_idx) {
                if (!(vcq->udma_mask & BIT(udma_idx)))
@@ -1247,24 +1244,25 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct 
ib_cq_init_attr *attr,
                                            &resp.cqid[udma_idx],
                                            udma_idx);
                if (rc)
-                       goto err_init;
+                       goto err_resp;
 
                rc = ionic_create_cq_cmd(dev, ctx, &vcq->cq[udma_idx], &buf);
-               if (rc)
-                       goto err_cmd;
+               if (rc) {
+                       ionic_pgtbl_unbuf(dev, &buf);
+                       ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]);
+                       goto err_resp;
+               }
 
                ionic_pgtbl_unbuf(dev, &buf);
        }
 
        vcq->ibcq.cqe = attr->cqe;
 
-       if (udata) {
-               resp.udma_mask = vcq->udma_mask;
+       resp.udma_mask = vcq->udma_mask;
 
-               rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
-               if (rc)
-                       goto err_resp;
-       }
+       rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
+       if (rc)
+               goto err_resp;
 
        return 0;
 
@@ -1274,11 +1272,47 @@ int ionic_create_cq(struct ib_cq *ibcq, const struct 
ib_cq_init_attr *attr,
                if (!(vcq->udma_mask & BIT(udma_idx)))
                        continue;
                ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid);
-err_cmd:
                ionic_pgtbl_unbuf(dev, &buf);
                ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]);
-err_init:
-               ;
+       }
+
+       return rc;
+}
+
+int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
+                   struct uverbs_attr_bundle *attrs)
+{
+       struct ionic_ibdev *dev = to_ionic_ibdev(ibcq->device);
+       struct ionic_vcq *vcq = to_ionic_vcq(ibcq);
+       struct ionic_tbl_buf buf = {};
+       int udma_idx = 0, rc;
+
+       vcq->udma_mask = BIT(dev->lif_cfg.udma_count) - 1;
+       for (; udma_idx < dev->lif_cfg.udma_count; ++udma_idx) {
+               rc = ionic_create_cq_common(vcq, &buf, attr, NULL, NULL, NULL,
+                                           NULL, udma_idx);
+               if (rc)
+                       goto err_resp;
+
+               rc = ionic_create_cq_cmd(dev, NULL, &vcq->cq[udma_idx], &buf);
+               if (rc) {
+                       ionic_pgtbl_unbuf(dev, &buf);
+                       ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]);
+                       goto err_resp;
+               }
+
+               ionic_pgtbl_unbuf(dev, &buf);
+       }
+
+       vcq->ibcq.cqe = attr->cqe;
+
+       return 0;
+
+err_resp:
+       while (udma_idx--) {
+               ionic_destroy_cq_cmd(dev, vcq->cq[udma_idx].cqid);
+               ionic_pgtbl_unbuf(dev, &buf);
+               ionic_destroy_cq_common(dev, &vcq->cq[udma_idx]);
        }
 
        return rc;
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c 
b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index 164046d00e5d..32321a8996d6 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -229,6 +229,7 @@ static const struct ib_device_ops ionic_dev_ops = {
        .alloc_mw = ionic_alloc_mw,
        .dealloc_mw = ionic_dealloc_mw,
        .create_cq = ionic_create_cq,
+       .create_user_cq = ionic_create_user_cq,
        .destroy_cq = ionic_destroy_cq,
        .create_qp = ionic_create_qp,
        .modify_qp = ionic_modify_qp,
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.h 
b/drivers/infiniband/hw/ionic/ionic_ibdev.h
index 63828240d659..0bcb8be6fb62 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.h
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.h
@@ -482,6 +482,8 @@ int ionic_alloc_mw(struct ib_mw *ibmw, struct ib_udata 
*udata);
 int ionic_dealloc_mw(struct ib_mw *ibmw);
 int ionic_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                    struct uverbs_attr_bundle *attrs);
+int ionic_create_user_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr 
*attr,
+                        struct uverbs_attr_bundle *attrs);
 int ionic_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
 int ionic_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
                    struct ib_udata *udata);

-- 
2.52.0


Reply via email to