From: Leon Romanovsky <[email protected]>
Separate the CQ creation logic into distinct kernel and user flows.
Signed-off-by: Leon Romanovsky <[email protected]>
---
drivers/infiniband/sw/siw/siw_main.c | 1 +
drivers/infiniband/sw/siw/siw_verbs.c | 111 +++++++++++++++++++++++-----------
drivers/infiniband/sw/siw/siw_verbs.h | 2 +
3 files changed, 80 insertions(+), 34 deletions(-)
diff --git a/drivers/infiniband/sw/siw/siw_main.c
b/drivers/infiniband/sw/siw/siw_main.c
index 5168307229a9..75dcf3578eac 100644
--- a/drivers/infiniband/sw/siw/siw_main.c
+++ b/drivers/infiniband/sw/siw/siw_main.c
@@ -232,6 +232,7 @@ static const struct ib_device_ops siw_device_ops = {
.alloc_pd = siw_alloc_pd,
.alloc_ucontext = siw_alloc_ucontext,
.create_cq = siw_create_cq,
+ .create_user_cq = siw_create_user_cq,
.create_qp = siw_create_qp,
.create_srq = siw_create_srq,
.dealloc_driver = siw_device_cleanup,
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c
b/drivers/infiniband/sw/siw/siw_verbs.c
index efa2f097b582..92b25b389b69 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -1139,15 +1139,15 @@ int siw_destroy_cq(struct ib_cq *base_cq, struct
ib_udata *udata)
* @attrs: uverbs bundle
*/
-int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
- struct uverbs_attr_bundle *attrs)
+int siw_create_user_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr
*attr,
+ struct uverbs_attr_bundle *attrs)
{
struct ib_udata *udata = &attrs->driver_udata;
struct siw_device *sdev = to_siw_dev(base_cq->device);
struct siw_cq *cq = to_siw_cq(base_cq);
int rv, size = attr->cqe;
- if (attr->flags)
+ if (attr->flags || base_cq->umem)
return -EOPNOTSUPP;
if (atomic_inc_return(&sdev->num_cq) > SIW_MAX_CQ) {
@@ -1155,7 +1155,7 @@ int siw_create_cq(struct ib_cq *base_cq, const struct
ib_cq_init_attr *attr,
rv = -ENOMEM;
goto err_out;
}
- if (size < 1 || size > sdev->attrs.max_cqe) {
+ if (attr->cqe > sdev->attrs.max_cqe) {
siw_dbg(base_cq->device, "CQ size error: %d\n", size);
rv = -EINVAL;
goto err_out;
@@ -1164,13 +1164,8 @@ int siw_create_cq(struct ib_cq *base_cq, const struct
ib_cq_init_attr *attr,
cq->base_cq.cqe = size;
cq->num_cqe = size;
- if (udata)
- cq->queue = vmalloc_user(size * sizeof(struct siw_cqe) +
- sizeof(struct siw_cq_ctrl));
- else
- cq->queue = vzalloc(size * sizeof(struct siw_cqe) +
- sizeof(struct siw_cq_ctrl));
-
+ cq->queue = vmalloc_user(size * sizeof(struct siw_cqe) +
+ sizeof(struct siw_cq_ctrl));
if (cq->queue == NULL) {
rv = -ENOMEM;
goto err_out;
@@ -1182,33 +1177,32 @@ int siw_create_cq(struct ib_cq *base_cq, const struct
ib_cq_init_attr *attr,
cq->notify = (struct siw_cq_ctrl *)&cq->queue[size];
- if (udata) {
- struct siw_uresp_create_cq uresp = {};
- struct siw_ucontext *ctx =
- rdma_udata_to_drv_context(udata, struct siw_ucontext,
- base_ucontext);
- size_t length = size * sizeof(struct siw_cqe) +
- sizeof(struct siw_cq_ctrl);
+ struct siw_uresp_create_cq uresp = {};
+ struct siw_ucontext *ctx =
+ rdma_udata_to_drv_context(udata, struct siw_ucontext,
+ base_ucontext);
+ size_t length = size * sizeof(struct siw_cqe) +
+ sizeof(struct siw_cq_ctrl);
- cq->cq_entry =
- siw_mmap_entry_insert(ctx, cq->queue,
- length, &uresp.cq_key);
- if (!cq->cq_entry) {
- rv = -ENOMEM;
- goto err_out;
- }
+ cq->cq_entry =
+ siw_mmap_entry_insert(ctx, cq->queue,
+ length, &uresp.cq_key);
+ if (!cq->cq_entry) {
+ rv = -ENOMEM;
+ goto err_out;
+ }
- uresp.cq_id = cq->id;
- uresp.num_cqe = size;
+ uresp.cq_id = cq->id;
+ uresp.num_cqe = size;
- if (udata->outlen < sizeof(uresp)) {
- rv = -EINVAL;
- goto err_out;
- }
- rv = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
- if (rv)
- goto err_out;
+ if (udata->outlen < sizeof(uresp)) {
+ rv = -EINVAL;
+ goto err_out;
}
+ rv = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+ if (rv)
+ goto err_out;
+
return 0;
err_out:
@@ -1227,6 +1221,55 @@ int siw_create_cq(struct ib_cq *base_cq, const struct
ib_cq_init_attr *attr,
return rv;
}
+int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
+ struct uverbs_attr_bundle *attrs)
+{
+ struct siw_device *sdev = to_siw_dev(base_cq->device);
+ struct siw_cq *cq = to_siw_cq(base_cq);
+ int rv, size = attr->cqe;
+
+ if (attr->flags)
+ return -EOPNOTSUPP;
+
+ if (atomic_inc_return(&sdev->num_cq) > SIW_MAX_CQ) {
+ siw_dbg(base_cq->device, "too many CQ's\n");
+ rv = -ENOMEM;
+ goto err_out;
+ }
+ if (size < 1 || size > sdev->attrs.max_cqe) {
+ siw_dbg(base_cq->device, "CQ size error: %d\n", size);
+ rv = -EINVAL;
+ goto err_out;
+ }
+ size = roundup_pow_of_two(size);
+ cq->base_cq.cqe = size;
+ cq->num_cqe = size;
+
+ cq->queue = vzalloc(size * sizeof(struct siw_cqe) +
+ sizeof(struct siw_cq_ctrl));
+ if (cq->queue == NULL) {
+ rv = -ENOMEM;
+ goto err_out;
+ }
+ get_random_bytes(&cq->id, 4);
+ siw_dbg(base_cq->device, "new CQ [%u]\n", cq->id);
+
+ spin_lock_init(&cq->lock);
+
+ cq->notify = (struct siw_cq_ctrl *)&cq->queue[size];
+
+ return 0;
+
+err_out:
+ siw_dbg(base_cq->device, "CQ creation failed: %d", rv);
+
+ if (cq->queue)
+ vfree(cq->queue);
+ atomic_dec(&sdev->num_cq);
+
+ return rv;
+}
+
/*
* siw_poll_cq()
*
diff --git a/drivers/infiniband/sw/siw/siw_verbs.h
b/drivers/infiniband/sw/siw/siw_verbs.h
index e9f4463aecdc..527c356b55af 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.h
+++ b/drivers/infiniband/sw/siw/siw_verbs.h
@@ -44,6 +44,8 @@ int siw_query_device(struct ib_device *base_dev, struct
ib_device_attr *attr,
struct ib_udata *udata);
int siw_create_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr *attr,
struct uverbs_attr_bundle *attrs);
+int siw_create_user_cq(struct ib_cq *base_cq, const struct ib_cq_init_attr
*attr,
+ struct uverbs_attr_bundle *attrs);
int siw_query_port(struct ib_device *base_dev, u32 port,
struct ib_port_attr *attr);
int siw_query_gid(struct ib_device *base_dev, u32 port, int idx,