1/*
2 * Copyright (c) 2017, Mellanox Technologies inc.  All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses.  You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 *     Redistribution and use in source and binary forms, with or
11 *     without modification, are permitted provided that the following
12 *     conditions are met:
13 *
14 *      - Redistributions of source code must retain the above
15 *        copyright notice, this list of conditions and the following
16 *        disclaimer.
17 *
18 *      - Redistributions in binary form must reproduce the above
19 *        copyright notice, this list of conditions and the following
20 *        disclaimer in the documentation and/or other materials
21 *        provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
33#include <rdma/uverbs_std_types.h>
34#include <rdma/ib_user_verbs.h>
35#include <rdma/ib_verbs.h>
36#include <linux/file.h>
37#include "rdma_core.h"
38#include "uverbs.h"
39
40static int uverbs_free_ah(struct ib_uobject *uobject,
41			  enum rdma_remove_reason why,
42			  struct uverbs_attr_bundle *attrs)
43{
44	return ib_destroy_ah_user((struct ib_ah *)uobject->object,
45				  RDMA_DESTROY_AH_SLEEPABLE,
46				  &attrs->driver_udata);
47}
48
49static int uverbs_free_flow(struct ib_uobject *uobject,
50			    enum rdma_remove_reason why,
51			    struct uverbs_attr_bundle *attrs)
52{
53	struct ib_flow *flow = (struct ib_flow *)uobject->object;
54	struct ib_uflow_object *uflow =
55		container_of(uobject, struct ib_uflow_object, uobject);
56	struct ib_qp *qp = flow->qp;
57	int ret;
58
59	ret = flow->device->destroy_flow(flow);
60	if (!ret) {
61		if (qp)
62			atomic_dec(&qp->usecnt);
63		ib_uverbs_flow_resources_free(uflow->resources);
64	}
65
66	return ret;
67}
68
69static int uverbs_free_mw(struct ib_uobject *uobject,
70			  enum rdma_remove_reason why,
71			  struct uverbs_attr_bundle *attrs)
72{
73	return uverbs_dealloc_mw((struct ib_mw *)uobject->object);
74}
75
76static int uverbs_free_qp(struct ib_uobject *uobject,
77			  enum rdma_remove_reason why,
78			  struct uverbs_attr_bundle *attrs)
79{
80	struct ib_qp *qp = uobject->object;
81	struct ib_uqp_object *uqp =
82		container_of(uobject, struct ib_uqp_object, uevent.uobject);
83	int ret;
84
85	/*
86	 * If this is a user triggered destroy then do not allow destruction
87	 * until the user cleans up all the mcast bindings. Unlike in other
88	 * places we forcibly clean up the mcast attachments for !DESTROY
89	 * because the mcast attaches are not ubojects and will not be
90	 * destroyed by anything else during cleanup processing.
91	 */
92	if (why == RDMA_REMOVE_DESTROY) {
93		if (!list_empty(&uqp->mcast_list))
94			return -EBUSY;
95	} else if (qp == qp->real_qp) {
96		ib_uverbs_detach_umcast(qp, uqp);
97	}
98
99	ret = ib_destroy_qp_user(qp, &attrs->driver_udata);
100	if (ib_is_destroy_retryable(ret, why, uobject))
101		return ret;
102
103	if (uqp->uxrcd)
104		atomic_dec(&uqp->uxrcd->refcnt);
105
106	ib_uverbs_release_uevent(&uqp->uevent);
107	return ret;
108}
109
110static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,
111				   enum rdma_remove_reason why,
112				   struct uverbs_attr_bundle *attrs)
113{
114	struct ib_rwq_ind_table *rwq_ind_tbl = uobject->object;
115	struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl;
116	int ret;
117
118	ret = ib_destroy_rwq_ind_table(rwq_ind_tbl);
119	if (ib_is_destroy_retryable(ret, why, uobject))
120		return ret;
121
122	kfree(ind_tbl);
123	return ret;
124}
125
126static int uverbs_free_wq(struct ib_uobject *uobject,
127			  enum rdma_remove_reason why,
128			  struct uverbs_attr_bundle *attrs)
129{
130	struct ib_wq *wq = uobject->object;
131	struct ib_uwq_object *uwq =
132		container_of(uobject, struct ib_uwq_object, uevent.uobject);
133	int ret;
134
135	ret = ib_destroy_wq(wq, &attrs->driver_udata);
136	if (ib_is_destroy_retryable(ret, why, uobject))
137		return ret;
138
139	ib_uverbs_release_uevent(&uwq->uevent);
140	return ret;
141}
142
143static int uverbs_free_srq(struct ib_uobject *uobject,
144			   enum rdma_remove_reason why,
145			   struct uverbs_attr_bundle *attrs)
146{
147	struct ib_srq *srq = uobject->object;
148	struct ib_uevent_object *uevent =
149		container_of(uobject, struct ib_uevent_object, uobject);
150	enum ib_srq_type  srq_type = srq->srq_type;
151	int ret;
152
153	ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
154	if (ib_is_destroy_retryable(ret, why, uobject))
155		return ret;
156
157	if (srq_type == IB_SRQT_XRC) {
158		struct ib_usrq_object *us =
159			container_of(uevent, struct ib_usrq_object, uevent);
160
161		atomic_dec(&us->uxrcd->refcnt);
162	}
163
164	ib_uverbs_release_uevent(uevent);
165	return ret;
166}
167
168static int uverbs_free_xrcd(struct ib_uobject *uobject,
169			    enum rdma_remove_reason why,
170			    struct uverbs_attr_bundle *attrs)
171{
172	struct ib_xrcd *xrcd = uobject->object;
173	struct ib_uxrcd_object *uxrcd =
174		container_of(uobject, struct ib_uxrcd_object, uobject);
175	int ret;
176
177	ret = ib_destroy_usecnt(&uxrcd->refcnt, why, uobject);
178	if (ret)
179		return ret;
180
181	mutex_lock(&attrs->ufile->device->xrcd_tree_mutex);
182	ret = ib_uverbs_dealloc_xrcd(uobject, xrcd, why, attrs);
183	mutex_unlock(&attrs->ufile->device->xrcd_tree_mutex);
184
185	return ret;
186}
187
188static int uverbs_free_pd(struct ib_uobject *uobject,
189			  enum rdma_remove_reason why,
190			  struct uverbs_attr_bundle *attrs)
191{
192	struct ib_pd *pd = uobject->object;
193	int ret;
194
195	ret = ib_destroy_usecnt(&pd->usecnt, why, uobject);
196	if (ret)
197		return ret;
198
199	ib_dealloc_pd_user(pd, &attrs->driver_udata);
200	return 0;
201}
202
203void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue)
204{
205	struct ib_uverbs_event *entry, *tmp;
206
207	spin_lock_irq(&event_queue->lock);
208	/*
209	 * The user must ensure that no new items are added to the event_list
210	 * once is_closed is set.
211	 */
212	event_queue->is_closed = 1;
213	spin_unlock_irq(&event_queue->lock);
214	wake_up_interruptible(&event_queue->poll_wait);
215	kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN);
216
217	spin_lock_irq(&event_queue->lock);
218	list_for_each_entry_safe(entry, tmp, &event_queue->event_list, list) {
219		if (entry->counter)
220			list_del(&entry->obj_list);
221		list_del(&entry->list);
222		kfree(entry);
223	}
224	spin_unlock_irq(&event_queue->lock);
225}
226
227static int
228uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,
229					  enum rdma_remove_reason why)
230{
231	struct ib_uverbs_completion_event_file *file =
232		container_of(uobj, struct ib_uverbs_completion_event_file,
233			     uobj);
234
235	ib_uverbs_free_event_queue(&file->ev_queue);
236	return 0;
237}
238
239int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs)
240{
241	return 0;
242}
243EXPORT_SYMBOL(uverbs_destroy_def_handler);
244
245DECLARE_UVERBS_NAMED_OBJECT(
246	UVERBS_OBJECT_COMP_CHANNEL,
247	UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file),
248			     uverbs_completion_event_file_destroy_uobj,
249			     &uverbs_event_fops,
250			     "[infinibandevent]",
251			     FMODE_READ));
252
253DECLARE_UVERBS_NAMED_OBJECT(
254	UVERBS_OBJECT_QP,
255	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), uverbs_free_qp));
256
257DECLARE_UVERBS_NAMED_METHOD_DESTROY(
258	UVERBS_METHOD_MW_DESTROY,
259	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_MW_HANDLE,
260			UVERBS_OBJECT_MW,
261			UVERBS_ACCESS_DESTROY,
262			UA_MANDATORY));
263
264DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MW,
265			    UVERBS_TYPE_ALLOC_IDR(uverbs_free_mw),
266			    &UVERBS_METHOD(UVERBS_METHOD_MW_DESTROY));
267
268DECLARE_UVERBS_NAMED_OBJECT(
269	UVERBS_OBJECT_SRQ,
270	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
271				 uverbs_free_srq));
272
273DECLARE_UVERBS_NAMED_METHOD_DESTROY(
274	UVERBS_METHOD_AH_DESTROY,
275	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_AH_HANDLE,
276			UVERBS_OBJECT_AH,
277			UVERBS_ACCESS_DESTROY,
278			UA_MANDATORY));
279
280DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_AH,
281			    UVERBS_TYPE_ALLOC_IDR(uverbs_free_ah),
282			    &UVERBS_METHOD(UVERBS_METHOD_AH_DESTROY));
283
284DECLARE_UVERBS_NAMED_METHOD_DESTROY(
285	UVERBS_METHOD_FLOW_DESTROY,
286	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_HANDLE,
287			UVERBS_OBJECT_FLOW,
288			UVERBS_ACCESS_DESTROY,
289			UA_MANDATORY));
290
291DECLARE_UVERBS_NAMED_OBJECT(
292	UVERBS_OBJECT_FLOW,
293	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uflow_object),
294				 uverbs_free_flow),
295			    &UVERBS_METHOD(UVERBS_METHOD_FLOW_DESTROY));
296
297DECLARE_UVERBS_NAMED_OBJECT(
298	UVERBS_OBJECT_WQ,
299	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), uverbs_free_wq));
300
301DECLARE_UVERBS_NAMED_METHOD_DESTROY(
302	UVERBS_METHOD_RWQ_IND_TBL_DESTROY,
303	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_RWQ_IND_TBL_HANDLE,
304			UVERBS_OBJECT_RWQ_IND_TBL,
305			UVERBS_ACCESS_DESTROY,
306			UA_MANDATORY));
307
308DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL,
309			    UVERBS_TYPE_ALLOC_IDR(uverbs_free_rwq_ind_tbl),
310			    &UVERBS_METHOD(UVERBS_METHOD_RWQ_IND_TBL_DESTROY));
311
312DECLARE_UVERBS_NAMED_METHOD_DESTROY(
313	UVERBS_METHOD_XRCD_DESTROY,
314	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_XRCD_HANDLE,
315			UVERBS_OBJECT_XRCD,
316			UVERBS_ACCESS_DESTROY,
317			UA_MANDATORY));
318
319DECLARE_UVERBS_NAMED_OBJECT(
320	UVERBS_OBJECT_XRCD,
321	UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object),
322				 uverbs_free_xrcd),
323			    &UVERBS_METHOD(UVERBS_METHOD_XRCD_DESTROY));
324
325DECLARE_UVERBS_NAMED_METHOD_DESTROY(
326	UVERBS_METHOD_PD_DESTROY,
327	UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_PD_HANDLE,
328			UVERBS_OBJECT_PD,
329			UVERBS_ACCESS_DESTROY,
330			UA_MANDATORY));
331
332DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,
333			    UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd),
334			    &UVERBS_METHOD(UVERBS_METHOD_PD_DESTROY));
335
336const struct uapi_definition uverbs_def_obj_intf[] = {
337	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD,
338				      UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)),
339	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL,
340				      UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)),
341	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_QP,
342				      UAPI_DEF_OBJ_NEEDS_FN(destroy_qp)),
343	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_AH,
344				      UAPI_DEF_OBJ_NEEDS_FN(destroy_ah)),
345	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW,
346				      UAPI_DEF_OBJ_NEEDS_FN(dealloc_mw)),
347	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ,
348				      UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)),
349	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW,
350				      UAPI_DEF_OBJ_NEEDS_FN(destroy_flow)),
351	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ,
352				      UAPI_DEF_OBJ_NEEDS_FN(destroy_wq)),
353	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
354		UVERBS_OBJECT_RWQ_IND_TBL,
355		UAPI_DEF_OBJ_NEEDS_FN(destroy_rwq_ind_table)),
356	UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_XRCD,
357				      UAPI_DEF_OBJ_NEEDS_FN(dealloc_xrcd)),
358	{}
359};
360