[PATCH rdma-next 10/10] RDMA/uverbs: Check for NULL driver methods for every write call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jason Gunthorpe <jgg@xxxxxxxxxxxx>

Add annotations to the uverbs_api structure indicating which driver
methods are called by the implementation. If the required method
is NULL the write API will be not be callable.

This effectively duplicates the cmd_mask system, however it does it by
expressing invariants required by the core code, not by delegating
decision making to the driver. This is another step toward eliminating
cmd_mask.

Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
---
 drivers/infiniband/core/uverbs_cmd.c  | 216 +++++++++++++++-----------
 drivers/infiniband/core/uverbs_uapi.c |  47 +++++-
 include/rdma/uverbs_ioctl.h           |  16 ++
 3 files changed, 178 insertions(+), 101 deletions(-)

diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 7c7ec1575511..e2fcaf398a4d 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -991,11 +991,6 @@ static struct ib_ucq_object *create_cq(struct ib_uverbs_file *file,
 	if (IS_ERR(obj))
 		return obj;
 
-	if (!ib_dev->create_cq) {
-		ret = -EOPNOTSUPP;
-		goto err;
-	}
-
 	if (cmd->comp_channel >= 0) {
 		ev_file = ib_uverbs_lookup_comp_file(cmd->comp_channel, file);
 		if (IS_ERR(ev_file)) {
@@ -2541,8 +2536,7 @@ static ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
 		goto out;
 
 	resp.bad_wr = 0;
-	ret = srq->device->post_srq_recv ?
-		srq->device->post_srq_recv(srq, wr, &bad_wr) : -EOPNOTSUPP;
+	ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
 
 	uobj_put_obj_read(srq);
 
@@ -3144,10 +3138,6 @@ static int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
 	obj->uevent.events_reported = 0;
 	INIT_LIST_HEAD(&obj->uevent.event_list);
 
-	if (!pd->device->create_wq) {
-		err = -EOPNOTSUPP;
-		goto err_put_cq;
-	}
 	wq = pd->device->create_wq(pd, &wq_init_attr, uhw);
 	if (IS_ERR(wq)) {
 		err = PTR_ERR(wq);
@@ -3277,12 +3267,7 @@ static int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file,
 		wq_attr.flags = cmd.flags;
 		wq_attr.flags_mask = cmd.flags_mask;
 	}
-	if (!wq->device->modify_wq) {
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
 	ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw);
-out:
 	uobj_put_obj_read(wq);
 	return ret;
 }
@@ -3380,10 +3365,6 @@ static int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
 	init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size;
 	init_attr.ind_tbl = wqs;
 
-	if (!ib_dev->create_rwq_ind_table) {
-		err = -EOPNOTSUPP;
-		goto err_uobj;
-	}
 	rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw);
 
 	if (IS_ERR(rwq_ind_tbl)) {
@@ -3548,11 +3529,6 @@ static int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
 		goto err_put;
 	}
 
-	if (!qp->device->create_flow) {
-		err = -EOPNOTSUPP;
-		goto err_put;
-	}
-
 	flow_attr = kzalloc(struct_size(flow_attr, flows,
 				cmd.flow_attr.num_of_specs), GFP_KERNEL);
 	if (!flow_attr) {
@@ -3971,9 +3947,6 @@ static int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
 		return PTR_ERR(ucontext);
 	ib_dev = ucontext->device;
 
-	if (!ib_dev->query_device)
-		return -EOPNOTSUPP;
-
 	if (ucore->inlen < sizeof(cmd))
 		return -EINVAL;
 
@@ -4123,11 +4096,14 @@ static int ib_uverbs_ex_modify_cq(struct ib_uverbs_file *file,
 }
 
 const struct uapi_definition uverbs_def_write_intf[] = {
-	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_AH,
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH,
-						   ib_uverbs_create_ah),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH,
-						   ib_uverbs_destroy_ah)),
+	DECLARE_UVERBS_OBJECT(
+		UVERBS_OBJECT_AH,
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_AH,
+				     ib_uverbs_create_ah,
+				     UAPI_DEF_METHOD_NEEDS_FN(create_ah)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_AH,
+				     ib_uverbs_destroy_ah,
+				     UAPI_DEF_METHOD_NEEDS_FN(destroy_ah))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_COMP_CHANNEL,
@@ -4137,19 +4113,26 @@ const struct uapi_definition uverbs_def_write_intf[] = {
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_CQ,
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_CQ,
-				     ib_uverbs_create_cq),
+				     ib_uverbs_create_cq,
+				     UAPI_DEF_METHOD_NEEDS_FN(create_cq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_CQ,
-				     ib_uverbs_destroy_cq),
+				     ib_uverbs_destroy_cq,
+				     UAPI_DEF_METHOD_NEEDS_FN(destroy_cq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POLL_CQ,
-				     ib_uverbs_poll_cq),
+				     ib_uverbs_poll_cq,
+				     UAPI_DEF_METHOD_NEEDS_FN(poll_cq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
-				     ib_uverbs_req_notify_cq),
+				     ib_uverbs_req_notify_cq,
+				     UAPI_DEF_METHOD_NEEDS_FN(req_notify_cq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_RESIZE_CQ,
-				     ib_uverbs_resize_cq),
+				     ib_uverbs_resize_cq,
+				     UAPI_DEF_METHOD_NEEDS_FN(resize_cq)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_CQ,
-					ib_uverbs_ex_create_cq),
+					ib_uverbs_ex_create_cq,
+					UAPI_DEF_METHOD_NEEDS_FN(create_cq)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_CQ,
-					ib_uverbs_ex_modify_cq)),
+					ib_uverbs_ex_modify_cq,
+					UAPI_DEF_METHOD_NEEDS_FN(create_cq))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_DEVICE,
@@ -4158,98 +4141,141 @@ const struct uapi_definition uverbs_def_write_intf[] = {
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_DEVICE,
 				     ib_uverbs_query_device),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_PORT,
-				     ib_uverbs_query_port),
+				     ib_uverbs_query_port,
+				     UAPI_DEF_METHOD_NEEDS_FN(query_port)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_QUERY_DEVICE,
-					ib_uverbs_ex_query_device)),
+					ib_uverbs_ex_query_device,
+					UAPI_DEF_METHOD_NEEDS_FN(query_device)),
+		UAPI_DEF_OBJ_NEEDS_FN(alloc_ucontext),
+		UAPI_DEF_OBJ_NEEDS_FN(dealloc_ucontext)),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_FLOW,
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_FLOW,
-					ib_uverbs_ex_create_flow),
+					ib_uverbs_ex_create_flow,
+					UAPI_DEF_METHOD_NEEDS_FN(create_flow)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
-					ib_uverbs_ex_destroy_flow)),
-
-	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MR,
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR,
-						   ib_uverbs_dereg_mr),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR,
-						   ib_uverbs_reg_mr),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR,
-						   ib_uverbs_rereg_mr)),
-
-	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_MW,
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW,
-						   ib_uverbs_alloc_mw),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW,
-						   ib_uverbs_dealloc_mw)),
-
-	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_PD,
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD,
-						   ib_uverbs_alloc_pd),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD,
-						   ib_uverbs_dealloc_pd)),
+					ib_uverbs_ex_destroy_flow,
+					UAPI_DEF_METHOD_NEEDS_FN(destroy_flow))),
+
+	DECLARE_UVERBS_OBJECT(
+		UVERBS_OBJECT_MR,
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEREG_MR,
+				     ib_uverbs_dereg_mr,
+				     UAPI_DEF_METHOD_NEEDS_FN(dereg_mr)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REG_MR,
+				     ib_uverbs_reg_mr,
+				     UAPI_DEF_METHOD_NEEDS_FN(reg_user_mr)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_REREG_MR,
+				     ib_uverbs_rereg_mr,
+				     UAPI_DEF_METHOD_NEEDS_FN(rereg_user_mr))),
+
+	DECLARE_UVERBS_OBJECT(
+		UVERBS_OBJECT_MW,
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_MW,
+				     ib_uverbs_alloc_mw,
+				     UAPI_DEF_METHOD_NEEDS_FN(alloc_mw)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_MW,
+				     ib_uverbs_dealloc_mw,
+				     UAPI_DEF_METHOD_NEEDS_FN(dealloc_mw))),
+
+	DECLARE_UVERBS_OBJECT(
+		UVERBS_OBJECT_PD,
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ALLOC_PD,
+				     ib_uverbs_alloc_pd,
+				     UAPI_DEF_METHOD_NEEDS_FN(alloc_pd)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DEALLOC_PD,
+				     ib_uverbs_dealloc_pd,
+				     UAPI_DEF_METHOD_NEEDS_FN(dealloc_pd))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_QP,
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_ATTACH_MCAST,
-				     ib_uverbs_attach_mcast),
+				     ib_uverbs_attach_mcast,
+				     UAPI_DEF_METHOD_NEEDS_FN(attach_mcast),
+				     UAPI_DEF_METHOD_NEEDS_FN(detach_mcast)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_QP,
-				     ib_uverbs_create_qp),
+				     ib_uverbs_create_qp,
+				     UAPI_DEF_METHOD_NEEDS_FN(create_qp)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_QP,
-				     ib_uverbs_destroy_qp),
+				     ib_uverbs_destroy_qp,
+				     UAPI_DEF_METHOD_NEEDS_FN(destroy_qp)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DETACH_MCAST,
-				     ib_uverbs_detach_mcast),
+				     ib_uverbs_detach_mcast,
+				     UAPI_DEF_METHOD_NEEDS_FN(detach_mcast)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_QP,
-				     ib_uverbs_modify_qp),
+				     ib_uverbs_modify_qp,
+				     UAPI_DEF_METHOD_NEEDS_FN(modify_qp)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_RECV,
-				     ib_uverbs_post_recv),
+				     ib_uverbs_post_recv,
+				     UAPI_DEF_METHOD_NEEDS_FN(post_recv)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SEND,
-				     ib_uverbs_post_send),
+				     ib_uverbs_post_send,
+				     UAPI_DEF_METHOD_NEEDS_FN(post_send)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_QP,
-				     ib_uverbs_query_qp),
+				     ib_uverbs_query_qp,
+				     UAPI_DEF_METHOD_NEEDS_FN(query_qp)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_QP,
-					ib_uverbs_ex_create_qp),
+					ib_uverbs_ex_create_qp,
+					UAPI_DEF_METHOD_NEEDS_FN(create_qp)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_QP,
-					ib_uverbs_ex_modify_qp)),
+					ib_uverbs_ex_modify_qp,
+					UAPI_DEF_METHOD_NEEDS_FN(modify_qp))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_RWQ_IND_TBL,
-		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
-					ib_uverbs_ex_create_rwq_ind_table),
-		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
-					ib_uverbs_ex_destroy_rwq_ind_table)),
+		DECLARE_UVERBS_WRITE_EX(
+			IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
+			ib_uverbs_ex_create_rwq_ind_table,
+			UAPI_DEF_METHOD_NEEDS_FN(create_rwq_ind_table)),
+		DECLARE_UVERBS_WRITE_EX(
+			IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL,
+			ib_uverbs_ex_destroy_rwq_ind_table,
+			UAPI_DEF_METHOD_NEEDS_FN(destroy_rwq_ind_table))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_WQ,
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_CREATE_WQ,
-					ib_uverbs_ex_create_wq),
+					ib_uverbs_ex_create_wq,
+					UAPI_DEF_METHOD_NEEDS_FN(create_wq)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_DESTROY_WQ,
-					ib_uverbs_ex_destroy_wq),
+					ib_uverbs_ex_destroy_wq,
+					UAPI_DEF_METHOD_NEEDS_FN(destroy_wq)),
 		DECLARE_UVERBS_WRITE_EX(IB_USER_VERBS_EX_CMD_MODIFY_WQ,
-					ib_uverbs_ex_modify_wq)),
+					ib_uverbs_ex_modify_wq,
+					UAPI_DEF_METHOD_NEEDS_FN(modify_wq))),
 
 	DECLARE_UVERBS_OBJECT(
 		UVERBS_OBJECT_SRQ,
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_SRQ,
-				     ib_uverbs_create_srq),
+				     ib_uverbs_create_srq,
+				     UAPI_DEF_METHOD_NEEDS_FN(create_srq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CREATE_XSRQ,
-				     ib_uverbs_create_xsrq),
+				     ib_uverbs_create_xsrq,
+				     UAPI_DEF_METHOD_NEEDS_FN(create_srq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_DESTROY_SRQ,
-				     ib_uverbs_destroy_srq),
+				     ib_uverbs_destroy_srq,
+				     UAPI_DEF_METHOD_NEEDS_FN(destroy_srq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_MODIFY_SRQ,
-				     ib_uverbs_modify_srq),
+				     ib_uverbs_modify_srq,
+				     UAPI_DEF_METHOD_NEEDS_FN(modify_srq)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_POST_SRQ_RECV,
-				     ib_uverbs_post_srq_recv),
+				     ib_uverbs_post_srq_recv,
+				     UAPI_DEF_METHOD_NEEDS_FN(post_srq_recv)),
 		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_QUERY_SRQ,
-				     ib_uverbs_query_srq)),
-
-	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT_XRCD,
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD,
-						   ib_uverbs_close_xrcd),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP,
-						   ib_uverbs_open_qp),
-			      DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD,
-						   ib_uverbs_open_xrcd)),
+				     ib_uverbs_query_srq,
+				     UAPI_DEF_METHOD_NEEDS_FN(query_srq))),
+
+	DECLARE_UVERBS_OBJECT(
+		UVERBS_OBJECT_XRCD,
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_CLOSE_XRCD,
+				     ib_uverbs_close_xrcd,
+				     UAPI_DEF_METHOD_NEEDS_FN(dealloc_xrcd)),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP,
+				     ib_uverbs_open_qp),
+		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_XRCD,
+				     ib_uverbs_open_xrcd,
+				     UAPI_DEF_METHOD_NEEDS_FN(alloc_xrcd))),
 
 	{},
 };
diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c
index fe1bef1c2966..1de1a6575278 100644
--- a/drivers/infiniband/core/uverbs_uapi.c
+++ b/drivers/infiniband/core/uverbs_uapi.c
@@ -60,8 +60,11 @@ static void *uapi_add_get_elm(struct uverbs_api *uapi, u32 key,
 	return elm;
 }
 
-static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev,
-			     const struct uapi_definition *def, u32 obj_key)
+static int uapi_create_write(struct uverbs_api *uapi,
+			     struct ib_device *ibdev,
+			     const struct uapi_definition *def,
+			     u32 obj_key,
+			     u32 *cur_method_key)
 {
 	struct uverbs_api_write_method *method_elm;
 	u32 method_key = obj_key;
@@ -93,6 +96,8 @@ static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev,
 		method_elm->disabled = !(ibdev->uverbs_cmd_mask &
 					 BIT_ULL(def->write.command_num));
 	}
+
+	*cur_method_key = method_key;
 	return 0;
 }
 
@@ -218,7 +223,8 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi,
 
 static int uapi_disable_elm(struct uverbs_api *uapi,
 			    const struct uapi_definition *def,
-			    u32 obj_key)
+			    u32 obj_key,
+			    u32 method_key)
 {
 	bool exists;
 
@@ -233,6 +239,31 @@ static int uapi_disable_elm(struct uverbs_api *uapi,
 		return 0;
 	}
 
+	if (def->scope == UAPI_SCOPE_METHOD &&
+	    uapi_key_is_ioctl_method(method_key)) {
+		struct uverbs_api_ioctl_method *method_elm;
+
+		method_elm = uapi_add_get_elm(uapi, method_key,
+					      sizeof(*method_elm), &exists);
+		if (IS_ERR(method_elm))
+			return PTR_ERR(method_elm);
+		method_elm->disabled = 1;
+		return 0;
+	}
+
+	if (def->scope == UAPI_SCOPE_METHOD &&
+	    (uapi_key_is_write_method(method_key) ||
+	     uapi_key_is_write_ex_method(method_key))) {
+		struct uverbs_api_write_method *write_elm;
+
+		write_elm = uapi_add_get_elm(uapi, method_key,
+					     sizeof(*write_elm), &exists);
+		if (IS_ERR(write_elm))
+			return PTR_ERR(write_elm);
+		write_elm->disabled = 1;
+		return 0;
+	}
+
 	WARN_ON(true);
 	return -EINVAL;
 }
@@ -243,6 +274,7 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
 {
 	const struct uapi_definition *def = def_list;
 	u32 cur_obj_key = UVERBS_API_KEY_ERR;
+	u32 cur_method_key = UVERBS_API_KEY_ERR;
 	bool exists;
 	int rc;
 
@@ -277,7 +309,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
 
 			if (*ibdev_fn)
 				continue;
-			rc = uapi_disable_elm(uapi, def, cur_obj_key);
+			rc = uapi_disable_elm(
+				uapi, def, cur_obj_key, cur_method_key);
 			if (rc)
 				return rc;
 			continue;
@@ -286,7 +319,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
 		case UAPI_DEF_IS_SUPPORTED_FUNC:
 			if (def->func_is_supported(ibdev))
 				continue;
-			rc = uapi_disable_elm(uapi, def, cur_obj_key);
+			rc = uapi_disable_elm(
+				uapi, def, cur_obj_key, cur_method_key);
 			if (rc)
 				return rc;
 			continue;
@@ -303,7 +337,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
 		}
 
 		case UAPI_DEF_WRITE:
-			rc = uapi_create_write(uapi, ibdev, def, cur_obj_key);
+			rc = uapi_create_write(
+				uapi, ibdev, def, cur_obj_key, &cur_method_key);
 			if (rc)
 				return rc;
 			continue;
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index 5df8ed79ba6c..963dd6b70cde 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -350,6 +350,7 @@ enum uapi_definition_kind {
 
 enum uapi_definition_scope {
 	UAPI_SCOPE_OBJECT = 1,
+	UAPI_SCOPE_METHOD = 2,
 };
 
 struct uapi_definition {
@@ -422,6 +423,21 @@ struct uapi_definition {
 				sizeof(void *)),                               \
 	}
 
+/*
+ * Method is only supported if the function pointer named ibdev_fn in struct
+ * ib_device is not NULL.
+ */
+#define UAPI_DEF_METHOD_NEEDS_FN(ibdev_fn)                                     \
+	{                                                                      \
+		.kind = UAPI_DEF_IS_SUPPORTED_DEV_FN,                          \
+		.scope = UAPI_SCOPE_METHOD,                                    \
+		.needs_fn_offset =                                             \
+			offsetof(struct ib_device, ibdev_fn) +                 \
+			BUILD_BUG_ON_ZERO(                                     \
+				sizeof(((struct ib_device *)0)->ibdev_fn) !=   \
+				sizeof(void *)),                               \
+	}
+
 /* Call a function to determine if the entire object is supported or not */
 #define UAPI_DEF_IS_OBJ_SUPPORTED(_func)                                       \
 	{                                                                      \
-- 
2.19.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux