1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright (c) 2020, Mellanox Technologies inc.  All rights reserved.
4  */
5 
6 #include <rdma/uverbs_std_types.h>
7 #include "rdma_core.h"
8 #include "uverbs.h"
9 
uverbs_free_srq(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)10 static int uverbs_free_srq(struct ib_uobject *uobject,
11 		    enum rdma_remove_reason why,
12 		    struct uverbs_attr_bundle *attrs)
13 {
14 	struct ib_srq *srq = uobject->object;
15 	struct ib_uevent_object *uevent =
16 		container_of(uobject, struct ib_uevent_object, uobject);
17 	enum ib_srq_type srq_type = srq->srq_type;
18 	int ret;
19 
20 	ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
21 	if (ret)
22 		return ret;
23 
24 	if (srq_type == IB_SRQT_XRC) {
25 		struct ib_usrq_object *us =
26 			container_of(uobject, struct ib_usrq_object,
27 				     uevent.uobject);
28 
29 		atomic_dec(&us->uxrcd->refcnt);
30 	}
31 
32 	ib_uverbs_release_uevent(uevent);
33 	return 0;
34 }
35 
UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)36 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)(
37 	struct uverbs_attr_bundle *attrs)
38 {
39 	struct ib_usrq_object *obj = container_of(
40 		uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE),
41 		typeof(*obj), uevent.uobject);
42 	struct ib_pd *pd =
43 		uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_SRQ_PD_HANDLE);
44 	struct ib_srq_init_attr attr = {};
45 	struct ib_uobject *xrcd_uobj;
46 	struct ib_srq *srq;
47 	u64 user_handle;
48 	int ret;
49 
50 	ret = uverbs_copy_from(&attr.attr.max_sge, attrs,
51 			       UVERBS_ATTR_CREATE_SRQ_MAX_SGE);
52 	if (!ret)
53 		ret = uverbs_copy_from(&attr.attr.max_wr, attrs,
54 				       UVERBS_ATTR_CREATE_SRQ_MAX_WR);
55 	if (!ret)
56 		ret = uverbs_copy_from(&attr.attr.srq_limit, attrs,
57 				       UVERBS_ATTR_CREATE_SRQ_LIMIT);
58 	if (!ret)
59 		ret = uverbs_copy_from(&user_handle, attrs,
60 				       UVERBS_ATTR_CREATE_SRQ_USER_HANDLE);
61 	if (!ret)
62 		ret = uverbs_get_const(&attr.srq_type, attrs,
63 				       UVERBS_ATTR_CREATE_SRQ_TYPE);
64 	if (ret)
65 		return ret;
66 
67 	if (ib_srq_has_cq(attr.srq_type)) {
68 		attr.ext.cq = uverbs_attr_get_obj(attrs,
69 					UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE);
70 		if (IS_ERR(attr.ext.cq))
71 			return PTR_ERR(attr.ext.cq);
72 	}
73 
74 	switch (attr.srq_type) {
75 	case IB_UVERBS_SRQT_XRC:
76 		xrcd_uobj = uverbs_attr_get_uobject(attrs,
77 					UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE);
78 		if (IS_ERR(xrcd_uobj))
79 			return PTR_ERR(xrcd_uobj);
80 
81 		attr.ext.xrc.xrcd = (struct ib_xrcd *)xrcd_uobj->object;
82 		if (!attr.ext.xrc.xrcd)
83 			return -EINVAL;
84 		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
85 					  uobject);
86 		atomic_inc(&obj->uxrcd->refcnt);
87 		break;
88 	case IB_UVERBS_SRQT_TM:
89 		ret = uverbs_copy_from(&attr.ext.tag_matching.max_num_tags,
90 				       attrs,
91 				       UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS);
92 		if (ret)
93 			return ret;
94 		break;
95 	case IB_UVERBS_SRQT_BASIC:
96 		break;
97 	default:
98 		return -EINVAL;
99 	}
100 
101 	obj->uevent.event_file = ib_uverbs_get_async_event(attrs,
102 					UVERBS_ATTR_CREATE_SRQ_EVENT_FD);
103 	INIT_LIST_HEAD(&obj->uevent.event_list);
104 	attr.event_handler = ib_uverbs_srq_event_handler;
105 	obj->uevent.uobject.user_handle = user_handle;
106 
107 	srq = ib_create_srq_user(pd, &attr, obj, &attrs->driver_udata);
108 	if (IS_ERR(srq)) {
109 		ret = PTR_ERR(srq);
110 		goto err;
111 	}
112 
113 	obj->uevent.uobject.object = srq;
114 	uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE);
115 
116 	ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
117 			     &attr.attr.max_wr,
118 			     sizeof(attr.attr.max_wr));
119 	if (ret)
120 		return ret;
121 
122 	ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
123 			     &attr.attr.max_sge,
124 			     sizeof(attr.attr.max_sge));
125 	if (ret)
126 		return ret;
127 
128 	if (attr.srq_type == IB_SRQT_XRC) {
129 		ret = uverbs_copy_to(attrs,
130 				     UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
131 				     &srq->ext.xrc.srq_num,
132 				     sizeof(srq->ext.xrc.srq_num));
133 		if (ret)
134 			return ret;
135 	}
136 
137 	return 0;
138 err:
139 	if (obj->uevent.event_file)
140 		uverbs_uobject_put(&obj->uevent.event_file->uobj);
141 	if (attr.srq_type == IB_SRQT_XRC)
142 		atomic_dec(&obj->uxrcd->refcnt);
143 	return ret;
144 };
145 
146 DECLARE_UVERBS_NAMED_METHOD(
147 	UVERBS_METHOD_SRQ_CREATE,
148 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_HANDLE,
149 			UVERBS_OBJECT_SRQ,
150 			UVERBS_ACCESS_NEW,
151 			UA_MANDATORY),
152 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_PD_HANDLE,
153 			UVERBS_OBJECT_PD,
154 			UVERBS_ACCESS_READ,
155 			UA_MANDATORY),
156 	UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_SRQ_TYPE,
157 			     enum ib_uverbs_srq_type,
158 			     UA_MANDATORY),
159 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_USER_HANDLE,
160 			   UVERBS_ATTR_TYPE(u64),
161 			   UA_MANDATORY),
162 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_WR,
163 			   UVERBS_ATTR_TYPE(u32),
164 			   UA_MANDATORY),
165 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_SGE,
166 			   UVERBS_ATTR_TYPE(u32),
167 			   UA_MANDATORY),
168 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_LIMIT,
169 			   UVERBS_ATTR_TYPE(u32),
170 			   UA_MANDATORY),
171 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE,
172 			UVERBS_OBJECT_XRCD,
173 			UVERBS_ACCESS_READ,
174 			UA_OPTIONAL),
175 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE,
176 			UVERBS_OBJECT_CQ,
177 			UVERBS_ACCESS_READ,
178 			UA_OPTIONAL),
179 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS,
180 			   UVERBS_ATTR_TYPE(u32),
181 			   UA_OPTIONAL),
182 	UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_SRQ_EVENT_FD,
183 		       UVERBS_OBJECT_ASYNC_EVENT,
184 		       UVERBS_ACCESS_READ,
185 		       UA_OPTIONAL),
186 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
187 			    UVERBS_ATTR_TYPE(u32),
188 			    UA_MANDATORY),
189 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
190 			    UVERBS_ATTR_TYPE(u32),
191 			    UA_MANDATORY),
192 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
193 			   UVERBS_ATTR_TYPE(u32),
194 			   UA_OPTIONAL),
195 	UVERBS_ATTR_UHW());
196 
UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)197 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)(
198 	struct uverbs_attr_bundle *attrs)
199 {
200 	struct ib_uobject *uobj =
201 		uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_SRQ_HANDLE);
202 	struct ib_usrq_object *obj =
203 		container_of(uobj, struct ib_usrq_object, uevent.uobject);
204 	struct ib_uverbs_destroy_srq_resp resp = {
205 		.events_reported = obj->uevent.events_reported
206 	};
207 
208 	return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_SRQ_RESP, &resp,
209 			      sizeof(resp));
210 }
211 
212 DECLARE_UVERBS_NAMED_METHOD(
213 	UVERBS_METHOD_SRQ_DESTROY,
214 	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_SRQ_HANDLE,
215 			UVERBS_OBJECT_SRQ,
216 			UVERBS_ACCESS_DESTROY,
217 			UA_MANDATORY),
218 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_SRQ_RESP,
219 			    UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_srq_resp),
220 			    UA_MANDATORY));
221 
222 DECLARE_UVERBS_NAMED_OBJECT(
223 	UVERBS_OBJECT_SRQ,
224 	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
225 				 uverbs_free_srq),
226 	&UVERBS_METHOD(UVERBS_METHOD_SRQ_CREATE),
227 	&UVERBS_METHOD(UVERBS_METHOD_SRQ_DESTROY)
228 );
229 
230 const struct uapi_definition uverbs_def_obj_srq[] = {
231 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ,
232 				      UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)),
233 	{}
234 };
235