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 #include "core_priv.h"
10 
uverbs_free_qp(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)11 static int uverbs_free_qp(struct ib_uobject *uobject,
12 			  enum rdma_remove_reason why,
13 			  struct uverbs_attr_bundle *attrs)
14 {
15 	struct ib_qp *qp = uobject->object;
16 	struct ib_uqp_object *uqp =
17 		container_of(uobject, struct ib_uqp_object, uevent.uobject);
18 	int ret;
19 
20 	/*
21 	 * If this is a user triggered destroy then do not allow destruction
22 	 * until the user cleans up all the mcast bindings. Unlike in other
23 	 * places we forcibly clean up the mcast attachments for !DESTROY
24 	 * because the mcast attaches are not ubojects and will not be
25 	 * destroyed by anything else during cleanup processing.
26 	 */
27 	if (why == RDMA_REMOVE_DESTROY) {
28 		if (!list_empty(&uqp->mcast_list))
29 			return -EBUSY;
30 	} else if (qp == qp->real_qp) {
31 		ib_uverbs_detach_umcast(qp, uqp);
32 	}
33 
34 	ret = ib_destroy_qp_user(qp, &attrs->driver_udata);
35 	if (ret)
36 		return ret;
37 
38 	if (uqp->uxrcd)
39 		atomic_dec(&uqp->uxrcd->refcnt);
40 
41 	ib_uverbs_release_uevent(&uqp->uevent);
42 	return 0;
43 }
44 
check_creation_flags(enum ib_qp_type qp_type,u32 create_flags)45 static int check_creation_flags(enum ib_qp_type qp_type,
46 				u32 create_flags)
47 {
48 	create_flags &= ~IB_UVERBS_QP_CREATE_SQ_SIG_ALL;
49 
50 	if (!create_flags || qp_type == IB_QPT_DRIVER)
51 		return 0;
52 
53 	if (qp_type != IB_QPT_RAW_PACKET && qp_type != IB_QPT_UD)
54 		return -EINVAL;
55 
56 	if ((create_flags & IB_UVERBS_QP_CREATE_SCATTER_FCS ||
57 	     create_flags & IB_UVERBS_QP_CREATE_CVLAN_STRIPPING) &&
58 	     qp_type != IB_QPT_RAW_PACKET)
59 		return -EINVAL;
60 
61 	return 0;
62 }
63 
set_caps(struct ib_qp_init_attr * attr,struct ib_uverbs_qp_cap * cap,bool req)64 static void set_caps(struct ib_qp_init_attr *attr,
65 		     struct ib_uverbs_qp_cap *cap, bool req)
66 {
67 	if (req) {
68 		attr->cap.max_send_wr = cap->max_send_wr;
69 		attr->cap.max_recv_wr = cap->max_recv_wr;
70 		attr->cap.max_send_sge = cap->max_send_sge;
71 		attr->cap.max_recv_sge = cap->max_recv_sge;
72 		attr->cap.max_inline_data = cap->max_inline_data;
73 	} else {
74 		cap->max_send_wr = attr->cap.max_send_wr;
75 		cap->max_recv_wr = attr->cap.max_recv_wr;
76 		cap->max_send_sge = attr->cap.max_send_sge;
77 		cap->max_recv_sge = attr->cap.max_recv_sge;
78 		cap->max_inline_data = attr->cap.max_inline_data;
79 	}
80 }
81 
UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)82 static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(
83 	struct uverbs_attr_bundle *attrs)
84 {
85 	struct ib_uqp_object *obj = container_of(
86 		uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_QP_HANDLE),
87 		typeof(*obj), uevent.uobject);
88 	struct ib_qp_init_attr attr = {};
89 	struct ib_uverbs_qp_cap cap = {};
90 	struct ib_rwq_ind_table *rwq_ind_tbl = NULL;
91 	struct ib_qp *qp;
92 	struct ib_pd *pd = NULL;
93 	struct ib_srq *srq = NULL;
94 	struct ib_cq *recv_cq = NULL;
95 	struct ib_cq *send_cq = NULL;
96 	struct ib_xrcd *xrcd = NULL;
97 	struct ib_uobject *xrcd_uobj = NULL;
98 	struct ib_device *device;
99 	u64 user_handle;
100 	int ret;
101 
102 	ret = uverbs_copy_from_or_zero(&cap, attrs,
103 			       UVERBS_ATTR_CREATE_QP_CAP);
104 	if (!ret)
105 		ret = uverbs_copy_from(&user_handle, attrs,
106 				       UVERBS_ATTR_CREATE_QP_USER_HANDLE);
107 	if (!ret)
108 		ret = uverbs_get_const(&attr.qp_type, attrs,
109 				       UVERBS_ATTR_CREATE_QP_TYPE);
110 	if (ret)
111 		return ret;
112 
113 	switch (attr.qp_type) {
114 	case IB_QPT_XRC_TGT:
115 		if (uverbs_attr_is_valid(attrs,
116 				UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE) ||
117 		    uverbs_attr_is_valid(attrs,
118 				UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE) ||
119 		    uverbs_attr_is_valid(attrs,
120 				UVERBS_ATTR_CREATE_QP_PD_HANDLE) ||
121 		    uverbs_attr_is_valid(attrs,
122 				UVERBS_ATTR_CREATE_QP_IND_TABLE_HANDLE))
123 			return -EINVAL;
124 
125 		xrcd_uobj = uverbs_attr_get_uobject(attrs,
126 					UVERBS_ATTR_CREATE_QP_XRCD_HANDLE);
127 		if (IS_ERR(xrcd_uobj))
128 			return PTR_ERR(xrcd_uobj);
129 
130 		xrcd = (struct ib_xrcd *)xrcd_uobj->object;
131 		if (!xrcd)
132 			return -EINVAL;
133 		device = xrcd->device;
134 		break;
135 	case IB_UVERBS_QPT_RAW_PACKET:
136 		if (!capable(CAP_NET_RAW))
137 			return -EPERM;
138 		fallthrough;
139 	case IB_UVERBS_QPT_RC:
140 	case IB_UVERBS_QPT_UC:
141 	case IB_UVERBS_QPT_UD:
142 	case IB_UVERBS_QPT_XRC_INI:
143 	case IB_UVERBS_QPT_DRIVER:
144 		if (uverbs_attr_is_valid(attrs,
145 					 UVERBS_ATTR_CREATE_QP_XRCD_HANDLE) ||
146 		   (uverbs_attr_is_valid(attrs,
147 					 UVERBS_ATTR_CREATE_QP_SRQ_HANDLE) &&
148 			attr.qp_type == IB_QPT_XRC_INI))
149 			return -EINVAL;
150 
151 		pd = uverbs_attr_get_obj(attrs,
152 					 UVERBS_ATTR_CREATE_QP_PD_HANDLE);
153 		if (IS_ERR(pd))
154 			return PTR_ERR(pd);
155 
156 		rwq_ind_tbl = uverbs_attr_get_obj(attrs,
157 			UVERBS_ATTR_CREATE_QP_IND_TABLE_HANDLE);
158 		if (!IS_ERR(rwq_ind_tbl)) {
159 			if (cap.max_recv_wr || cap.max_recv_sge ||
160 			    uverbs_attr_is_valid(attrs,
161 				UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE) ||
162 			    uverbs_attr_is_valid(attrs,
163 					UVERBS_ATTR_CREATE_QP_SRQ_HANDLE))
164 				return -EINVAL;
165 
166 			/* send_cq is optinal */
167 			if (cap.max_send_wr) {
168 				send_cq = uverbs_attr_get_obj(attrs,
169 					UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE);
170 				if (IS_ERR(send_cq))
171 					return PTR_ERR(send_cq);
172 			}
173 			attr.rwq_ind_tbl = rwq_ind_tbl;
174 		} else {
175 			send_cq = uverbs_attr_get_obj(attrs,
176 					UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE);
177 			if (IS_ERR(send_cq))
178 				return PTR_ERR(send_cq);
179 
180 			if (attr.qp_type != IB_QPT_XRC_INI) {
181 				recv_cq = uverbs_attr_get_obj(attrs,
182 					UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE);
183 				if (IS_ERR(recv_cq))
184 					return PTR_ERR(recv_cq);
185 			}
186 		}
187 
188 		device = pd->device;
189 		break;
190 	default:
191 		return -EINVAL;
192 	}
193 
194 	ret = uverbs_get_flags32(&attr.create_flags, attrs,
195 			 UVERBS_ATTR_CREATE_QP_FLAGS,
196 			 IB_UVERBS_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
197 			 IB_UVERBS_QP_CREATE_SCATTER_FCS |
198 			 IB_UVERBS_QP_CREATE_CVLAN_STRIPPING |
199 			 IB_UVERBS_QP_CREATE_PCI_WRITE_END_PADDING |
200 			 IB_UVERBS_QP_CREATE_SQ_SIG_ALL);
201 	if (ret)
202 		return ret;
203 
204 	ret = check_creation_flags(attr.qp_type, attr.create_flags);
205 	if (ret)
206 		return ret;
207 
208 	if (uverbs_attr_is_valid(attrs,
209 			UVERBS_ATTR_CREATE_QP_SOURCE_QPN)) {
210 		ret = uverbs_copy_from(&attr.source_qpn, attrs,
211 				       UVERBS_ATTR_CREATE_QP_SOURCE_QPN);
212 		if (ret)
213 			return ret;
214 		attr.create_flags |= IB_QP_CREATE_SOURCE_QPN;
215 	}
216 
217 	srq = uverbs_attr_get_obj(attrs,
218 				  UVERBS_ATTR_CREATE_QP_SRQ_HANDLE);
219 	if (!IS_ERR(srq)) {
220 		if ((srq->srq_type == IB_SRQT_XRC &&
221 			attr.qp_type != IB_QPT_XRC_TGT) ||
222 		    (srq->srq_type != IB_SRQT_XRC &&
223 			attr.qp_type == IB_QPT_XRC_TGT))
224 			return -EINVAL;
225 		attr.srq = srq;
226 	}
227 
228 	obj->uevent.event_file = ib_uverbs_get_async_event(attrs,
229 					UVERBS_ATTR_CREATE_QP_EVENT_FD);
230 	INIT_LIST_HEAD(&obj->uevent.event_list);
231 	INIT_LIST_HEAD(&obj->mcast_list);
232 	obj->uevent.uobject.user_handle = user_handle;
233 	attr.event_handler = ib_uverbs_qp_event_handler;
234 	attr.send_cq = send_cq;
235 	attr.recv_cq = recv_cq;
236 	attr.xrcd = xrcd;
237 	if (attr.create_flags & IB_UVERBS_QP_CREATE_SQ_SIG_ALL) {
238 		/* This creation bit is uverbs one, need to mask before
239 		 * calling drivers. It was added to prevent an extra user attr
240 		 * only for that when using ioctl.
241 		 */
242 		attr.create_flags &= ~IB_UVERBS_QP_CREATE_SQ_SIG_ALL;
243 		attr.sq_sig_type = IB_SIGNAL_ALL_WR;
244 	} else {
245 		attr.sq_sig_type = IB_SIGNAL_REQ_WR;
246 	}
247 
248 	set_caps(&attr, &cap, true);
249 	mutex_init(&obj->mcast_lock);
250 
251 	qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
252 			       KBUILD_MODNAME);
253 	if (IS_ERR(qp)) {
254 		ret = PTR_ERR(qp);
255 		goto err_put;
256 	}
257 	ib_qp_usecnt_inc(qp);
258 
259 	if (attr.qp_type == IB_QPT_XRC_TGT) {
260 		obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
261 					  uobject);
262 		atomic_inc(&obj->uxrcd->refcnt);
263 	}
264 
265 	obj->uevent.uobject.object = qp;
266 	uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_QP_HANDLE);
267 
268 	set_caps(&attr, &cap, false);
269 	ret = uverbs_copy_to_struct_or_zero(attrs,
270 					UVERBS_ATTR_CREATE_QP_RESP_CAP, &cap,
271 					sizeof(cap));
272 	if (ret)
273 		return ret;
274 
275 	ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_QP_RESP_QP_NUM,
276 			     &qp->qp_num,
277 			     sizeof(qp->qp_num));
278 
279 	return ret;
280 err_put:
281 	if (obj->uevent.event_file)
282 		uverbs_uobject_put(&obj->uevent.event_file->uobj);
283 	return ret;
284 };
285 
286 DECLARE_UVERBS_NAMED_METHOD(
287 	UVERBS_METHOD_QP_CREATE,
288 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_HANDLE,
289 			UVERBS_OBJECT_QP,
290 			UVERBS_ACCESS_NEW,
291 			UA_MANDATORY),
292 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_XRCD_HANDLE,
293 			UVERBS_OBJECT_XRCD,
294 			UVERBS_ACCESS_READ,
295 			UA_OPTIONAL),
296 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_PD_HANDLE,
297 			UVERBS_OBJECT_PD,
298 			UVERBS_ACCESS_READ,
299 			UA_OPTIONAL),
300 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_SRQ_HANDLE,
301 			UVERBS_OBJECT_SRQ,
302 			UVERBS_ACCESS_READ,
303 			UA_OPTIONAL),
304 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE,
305 			UVERBS_OBJECT_CQ,
306 			UVERBS_ACCESS_READ,
307 			UA_OPTIONAL),
308 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE,
309 			UVERBS_OBJECT_CQ,
310 			UVERBS_ACCESS_READ,
311 			UA_OPTIONAL),
312 	UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_QP_IND_TABLE_HANDLE,
313 			UVERBS_OBJECT_RWQ_IND_TBL,
314 			UVERBS_ACCESS_READ,
315 			UA_OPTIONAL),
316 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_QP_USER_HANDLE,
317 			   UVERBS_ATTR_TYPE(u64),
318 			   UA_MANDATORY),
319 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_QP_CAP,
320 			   UVERBS_ATTR_STRUCT(struct ib_uverbs_qp_cap,
321 					      max_inline_data),
322 			   UA_MANDATORY),
323 	UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_QP_TYPE,
324 			     enum ib_uverbs_qp_type,
325 			     UA_MANDATORY),
326 	UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_CREATE_QP_FLAGS,
327 			     enum ib_uverbs_qp_create_flags,
328 			     UA_OPTIONAL),
329 	UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_QP_SOURCE_QPN,
330 			   UVERBS_ATTR_TYPE(u32),
331 			   UA_OPTIONAL),
332 	UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_QP_EVENT_FD,
333 		       UVERBS_OBJECT_ASYNC_EVENT,
334 		       UVERBS_ACCESS_READ,
335 		       UA_OPTIONAL),
336 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_QP_RESP_CAP,
337 			    UVERBS_ATTR_STRUCT(struct ib_uverbs_qp_cap,
338 					       max_inline_data),
339 			   UA_MANDATORY),
340 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_QP_RESP_QP_NUM,
341 			   UVERBS_ATTR_TYPE(u32),
342 			   UA_MANDATORY),
343 	UVERBS_ATTR_UHW());
344 
UVERBS_HANDLER(UVERBS_METHOD_QP_DESTROY)345 static int UVERBS_HANDLER(UVERBS_METHOD_QP_DESTROY)(
346 	struct uverbs_attr_bundle *attrs)
347 {
348 	struct ib_uobject *uobj =
349 		uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_QP_HANDLE);
350 	struct ib_uqp_object *obj =
351 		container_of(uobj, struct ib_uqp_object, uevent.uobject);
352 	struct ib_uverbs_destroy_qp_resp resp = {
353 		.events_reported = obj->uevent.events_reported
354 	};
355 
356 	return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_QP_RESP, &resp,
357 			      sizeof(resp));
358 }
359 
360 DECLARE_UVERBS_NAMED_METHOD(
361 	UVERBS_METHOD_QP_DESTROY,
362 	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_QP_HANDLE,
363 			UVERBS_OBJECT_QP,
364 			UVERBS_ACCESS_DESTROY,
365 			UA_MANDATORY),
366 	UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_QP_RESP,
367 			    UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_qp_resp),
368 			    UA_MANDATORY));
369 
370 DECLARE_UVERBS_NAMED_OBJECT(
371 	UVERBS_OBJECT_QP,
372 	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), uverbs_free_qp),
373 	&UVERBS_METHOD(UVERBS_METHOD_QP_CREATE),
374 	&UVERBS_METHOD(UVERBS_METHOD_QP_DESTROY));
375 
376 const struct uapi_definition uverbs_def_obj_qp[] = {
377 	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_QP,
378 				      UAPI_DEF_OBJ_NEEDS_FN(destroy_qp)),
379 	{}
380 };
381