aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/rdma_core.c5
-rw-r--r--drivers/infiniband/core/uverbs_ioctl.c28
-rw-r--r--drivers/infiniband/core/uverbs_std_types_cq.c21
3 files changed, 32 insertions, 22 deletions
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index a63844ba8414..9e84ded6d3be 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -924,10 +924,7 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
rdma_lookup_put_uobject(uobj, true);
break;
case UVERBS_ACCESS_DESTROY:
- if (commit)
- ret = rdma_remove_commit_uobject(uobj);
- else
- rdma_lookup_put_uobject(uobj, true);
+ rdma_lookup_put_uobject(uobj, true);
break;
case UVERBS_ACCESS_NEW:
if (commit)
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 23a1777f26e2..404acfcdbeb2 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -51,6 +51,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
u16 attr_id,
const struct uverbs_attr_spec_hash *attr_spec_bucket,
struct uverbs_attr_bundle_hash *attr_bundle_h,
+ struct uverbs_obj_attr **destroy_attr,
struct ib_uverbs_attr __user *uattr_ptr)
{
const struct uverbs_attr_spec *spec;
@@ -148,6 +149,12 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
if (!object)
return -EINVAL;
+ /* specs are allowed to have only one destroy attribute */
+ WARN_ON(spec->u.obj.access == UVERBS_ACCESS_DESTROY &&
+ *destroy_attr);
+ if (spec->u.obj.access == UVERBS_ACCESS_DESTROY)
+ *destroy_attr = o_attr;
+
/*
* The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and
* s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64
@@ -235,6 +242,7 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
size_t num_uattrs,
const struct uverbs_method_spec *method,
struct uverbs_attr_bundle *attr_bundle,
+ struct uverbs_obj_attr **destroy_attr,
struct ib_uverbs_attr __user *uattr_ptr)
{
size_t i;
@@ -268,7 +276,8 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
attr_spec_bucket = method->attr_buckets[ret];
ret = uverbs_process_attr(ufile, uattr, attr_id,
attr_spec_bucket,
- &attr_bundle->hash[ret], uattr_ptr++);
+ &attr_bundle->hash[ret], destroy_attr,
+ uattr_ptr++);
if (ret) {
uverbs_finalize_attrs(attr_bundle,
method->attr_buckets,
@@ -322,9 +331,11 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
int ret;
int finalize_ret;
int num_given_buckets;
+ struct uverbs_obj_attr *destroy_attr = NULL;
- num_given_buckets = uverbs_uattrs_process(
- ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr);
+ num_given_buckets =
+ uverbs_uattrs_process(ufile, uattrs, num_uattrs, method_spec,
+ attr_bundle, &destroy_attr, uattr_ptr);
if (num_given_buckets <= 0)
return -EINVAL;
@@ -333,7 +344,18 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
if (ret)
goto cleanup;
+ /*
+ * We destroy the HW object before invoking the handler, handlers do
+ * not get to manipulate the HW objects.
+ */
+ if (destroy_attr) {
+ ret = rdma_explicit_destroy(destroy_attr->uobject);
+ if (ret)
+ goto cleanup;
+ }
+
ret = method_spec->handler(ibdev, ufile, attr_bundle);
+
cleanup:
finalize_ret = uverbs_finalize_attrs(attr_bundle,
method_spec->attr_buckets,
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index 3179203a2dd7..68c86e6e932e 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -179,21 +179,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_DESTROY)(struct ib_device *ib_dev,
{
struct ib_uobject *uobj =
uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_CQ_HANDLE);
- struct ib_uverbs_destroy_cq_resp resp;
- struct ib_ucq_object *obj;
- int ret;
-
- if (IS_ERR(uobj))
- return PTR_ERR(uobj);
-
- obj = container_of(uobj, struct ib_ucq_object, uobject);
-
- ret = rdma_explicit_destroy(uobj);
- if (ret)
- return ret;
-
- resp.comp_events_reported = obj->comp_events_reported;
- resp.async_events_reported = obj->async_events_reported;
+ struct ib_ucq_object *obj =
+ container_of(uobj, struct ib_ucq_object, uobject);
+ struct ib_uverbs_destroy_cq_resp resp = {
+ .comp_events_reported = obj->comp_events_reported,
+ .async_events_reported = obj->async_events_reported
+ };
return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_CQ_RESP, &resp,
sizeof(resp));