]>
Commit | Line | Data |
---|---|---|
6be60aed MB |
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/bug.h> | |
37 | #include <linux/file.h> | |
38 | #include "rdma_core.h" | |
39 | #include "uverbs.h" | |
40 | ||
218271ad LR |
41 | static int uverbs_free_ah(struct ib_uobject *uobject, |
42 | enum rdma_remove_reason why) | |
6be60aed | 43 | { |
36523159 | 44 | return rdma_destroy_ah((struct ib_ah *)uobject->object); |
6be60aed MB |
45 | } |
46 | ||
218271ad LR |
47 | static int uverbs_free_flow(struct ib_uobject *uobject, |
48 | enum rdma_remove_reason why) | |
6be60aed MB |
49 | { |
50 | return ib_destroy_flow((struct ib_flow *)uobject->object); | |
51 | } | |
52 | ||
218271ad LR |
53 | static int uverbs_free_mw(struct ib_uobject *uobject, |
54 | enum rdma_remove_reason why) | |
6be60aed MB |
55 | { |
56 | return uverbs_dealloc_mw((struct ib_mw *)uobject->object); | |
57 | } | |
58 | ||
218271ad LR |
59 | static int uverbs_free_qp(struct ib_uobject *uobject, |
60 | enum rdma_remove_reason why) | |
6be60aed MB |
61 | { |
62 | struct ib_qp *qp = uobject->object; | |
63 | struct ib_uqp_object *uqp = | |
64 | container_of(uobject, struct ib_uqp_object, uevent.uobject); | |
65 | int ret; | |
66 | ||
67 | if (why == RDMA_REMOVE_DESTROY) { | |
68 | if (!list_empty(&uqp->mcast_list)) | |
69 | return -EBUSY; | |
70 | } else if (qp == qp->real_qp) { | |
71 | ib_uverbs_detach_umcast(qp, uqp); | |
72 | } | |
73 | ||
74 | ret = ib_destroy_qp(qp); | |
75 | if (ret && why == RDMA_REMOVE_DESTROY) | |
76 | return ret; | |
77 | ||
78 | if (uqp->uxrcd) | |
79 | atomic_dec(&uqp->uxrcd->refcnt); | |
80 | ||
81 | ib_uverbs_release_uevent(uobject->context->ufile, &uqp->uevent); | |
82 | return ret; | |
83 | } | |
84 | ||
218271ad LR |
85 | static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject, |
86 | enum rdma_remove_reason why) | |
6be60aed MB |
87 | { |
88 | struct ib_rwq_ind_table *rwq_ind_tbl = uobject->object; | |
89 | struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl; | |
90 | int ret; | |
91 | ||
92 | ret = ib_destroy_rwq_ind_table(rwq_ind_tbl); | |
93 | if (!ret || why != RDMA_REMOVE_DESTROY) | |
94 | kfree(ind_tbl); | |
95 | return ret; | |
96 | } | |
97 | ||
218271ad LR |
98 | static int uverbs_free_wq(struct ib_uobject *uobject, |
99 | enum rdma_remove_reason why) | |
6be60aed MB |
100 | { |
101 | struct ib_wq *wq = uobject->object; | |
102 | struct ib_uwq_object *uwq = | |
103 | container_of(uobject, struct ib_uwq_object, uevent.uobject); | |
104 | int ret; | |
105 | ||
106 | ret = ib_destroy_wq(wq); | |
107 | if (!ret || why != RDMA_REMOVE_DESTROY) | |
108 | ib_uverbs_release_uevent(uobject->context->ufile, &uwq->uevent); | |
109 | return ret; | |
110 | } | |
111 | ||
218271ad LR |
112 | static int uverbs_free_srq(struct ib_uobject *uobject, |
113 | enum rdma_remove_reason why) | |
6be60aed MB |
114 | { |
115 | struct ib_srq *srq = uobject->object; | |
116 | struct ib_uevent_object *uevent = | |
117 | container_of(uobject, struct ib_uevent_object, uobject); | |
118 | enum ib_srq_type srq_type = srq->srq_type; | |
119 | int ret; | |
120 | ||
121 | ret = ib_destroy_srq(srq); | |
122 | ||
123 | if (ret && why == RDMA_REMOVE_DESTROY) | |
124 | return ret; | |
125 | ||
126 | if (srq_type == IB_SRQT_XRC) { | |
127 | struct ib_usrq_object *us = | |
128 | container_of(uevent, struct ib_usrq_object, uevent); | |
129 | ||
130 | atomic_dec(&us->uxrcd->refcnt); | |
131 | } | |
132 | ||
133 | ib_uverbs_release_uevent(uobject->context->ufile, uevent); | |
134 | return ret; | |
135 | } | |
136 | ||
218271ad LR |
137 | static int uverbs_free_cq(struct ib_uobject *uobject, |
138 | enum rdma_remove_reason why) | |
6be60aed MB |
139 | { |
140 | struct ib_cq *cq = uobject->object; | |
db1b5ddd | 141 | struct ib_uverbs_event_queue *ev_queue = cq->cq_context; |
6be60aed MB |
142 | struct ib_ucq_object *ucq = |
143 | container_of(uobject, struct ib_ucq_object, uobject); | |
144 | int ret; | |
145 | ||
146 | ret = ib_destroy_cq(cq); | |
147 | if (!ret || why != RDMA_REMOVE_DESTROY) | |
db1b5ddd MB |
148 | ib_uverbs_release_ucq(uobject->context->ufile, ev_queue ? |
149 | container_of(ev_queue, | |
1e7710f3 | 150 | struct ib_uverbs_completion_event_file, |
db1b5ddd | 151 | ev_queue) : NULL, |
1e7710f3 | 152 | ucq); |
6be60aed MB |
153 | return ret; |
154 | } | |
155 | ||
218271ad LR |
156 | static int uverbs_free_mr(struct ib_uobject *uobject, |
157 | enum rdma_remove_reason why) | |
6be60aed MB |
158 | { |
159 | return ib_dereg_mr((struct ib_mr *)uobject->object); | |
160 | } | |
161 | ||
218271ad LR |
162 | static int uverbs_free_xrcd(struct ib_uobject *uobject, |
163 | enum rdma_remove_reason why) | |
6be60aed MB |
164 | { |
165 | struct ib_xrcd *xrcd = uobject->object; | |
166 | struct ib_uxrcd_object *uxrcd = | |
167 | container_of(uobject, struct ib_uxrcd_object, uobject); | |
168 | int ret; | |
169 | ||
170 | mutex_lock(&uobject->context->ufile->device->xrcd_tree_mutex); | |
171 | if (why == RDMA_REMOVE_DESTROY && atomic_read(&uxrcd->refcnt)) | |
172 | ret = -EBUSY; | |
173 | else | |
174 | ret = ib_uverbs_dealloc_xrcd(uobject->context->ufile->device, | |
175 | xrcd, why); | |
176 | mutex_unlock(&uobject->context->ufile->device->xrcd_tree_mutex); | |
177 | ||
178 | return ret; | |
179 | } | |
180 | ||
218271ad LR |
181 | static int uverbs_free_pd(struct ib_uobject *uobject, |
182 | enum rdma_remove_reason why) | |
6be60aed MB |
183 | { |
184 | struct ib_pd *pd = uobject->object; | |
185 | ||
186 | if (why == RDMA_REMOVE_DESTROY && atomic_read(&pd->usecnt)) | |
187 | return -EBUSY; | |
188 | ||
189 | ib_dealloc_pd((struct ib_pd *)uobject->object); | |
190 | return 0; | |
191 | } | |
192 | ||
218271ad LR |
193 | static int uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_file, |
194 | enum rdma_remove_reason why) | |
1e7710f3 MB |
195 | { |
196 | struct ib_uverbs_completion_event_file *comp_event_file = | |
197 | container_of(uobj_file, struct ib_uverbs_completion_event_file, | |
198 | uobj_file); | |
db1b5ddd | 199 | struct ib_uverbs_event_queue *event_queue = &comp_event_file->ev_queue; |
1e7710f3 | 200 | |
db1b5ddd MB |
201 | spin_lock_irq(&event_queue->lock); |
202 | event_queue->is_closed = 1; | |
203 | spin_unlock_irq(&event_queue->lock); | |
1e7710f3 MB |
204 | |
205 | if (why == RDMA_REMOVE_DRIVER_REMOVE) { | |
db1b5ddd MB |
206 | wake_up_interruptible(&event_queue->poll_wait); |
207 | kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN); | |
1e7710f3 MB |
208 | } |
209 | return 0; | |
210 | }; | |
211 | ||
212 | const struct uverbs_obj_fd_type uverbs_type_attrs_comp_channel = { | |
213 | .type = UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), 0), | |
214 | .context_closed = uverbs_hot_unplug_completion_event_file, | |
215 | .fops = &uverbs_event_fops, | |
216 | .name = "[infinibandevent]", | |
217 | .flags = O_RDONLY, | |
218 | }; | |
219 | ||
6be60aed MB |
220 | const struct uverbs_obj_idr_type uverbs_type_attrs_cq = { |
221 | .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), 0), | |
222 | .destroy_object = uverbs_free_cq, | |
223 | }; | |
224 | ||
225 | const struct uverbs_obj_idr_type uverbs_type_attrs_qp = { | |
226 | .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), 0), | |
227 | .destroy_object = uverbs_free_qp, | |
228 | }; | |
229 | ||
230 | const struct uverbs_obj_idr_type uverbs_type_attrs_mw = { | |
231 | .type = UVERBS_TYPE_ALLOC_IDR(0), | |
232 | .destroy_object = uverbs_free_mw, | |
233 | }; | |
234 | ||
235 | const struct uverbs_obj_idr_type uverbs_type_attrs_mr = { | |
236 | /* 1 is used in order to free the MR after all the MWs */ | |
237 | .type = UVERBS_TYPE_ALLOC_IDR(1), | |
238 | .destroy_object = uverbs_free_mr, | |
239 | }; | |
240 | ||
241 | const struct uverbs_obj_idr_type uverbs_type_attrs_srq = { | |
242 | .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object), 0), | |
243 | .destroy_object = uverbs_free_srq, | |
244 | }; | |
245 | ||
246 | const struct uverbs_obj_idr_type uverbs_type_attrs_ah = { | |
247 | .type = UVERBS_TYPE_ALLOC_IDR(0), | |
248 | .destroy_object = uverbs_free_ah, | |
249 | }; | |
250 | ||
251 | const struct uverbs_obj_idr_type uverbs_type_attrs_flow = { | |
252 | .type = UVERBS_TYPE_ALLOC_IDR(0), | |
253 | .destroy_object = uverbs_free_flow, | |
254 | }; | |
255 | ||
256 | const struct uverbs_obj_idr_type uverbs_type_attrs_wq = { | |
257 | .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), 0), | |
258 | .destroy_object = uverbs_free_wq, | |
259 | }; | |
260 | ||
261 | const struct uverbs_obj_idr_type uverbs_type_attrs_rwq_ind_table = { | |
262 | .type = UVERBS_TYPE_ALLOC_IDR(0), | |
263 | .destroy_object = uverbs_free_rwq_ind_tbl, | |
264 | }; | |
265 | ||
266 | const struct uverbs_obj_idr_type uverbs_type_attrs_xrcd = { | |
267 | .type = UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object), 0), | |
268 | .destroy_object = uverbs_free_xrcd, | |
269 | }; | |
270 | ||
271 | const struct uverbs_obj_idr_type uverbs_type_attrs_pd = { | |
272 | /* 2 is used in order to free the PD after MRs */ | |
273 | .type = UVERBS_TYPE_ALLOC_IDR(2), | |
274 | .destroy_object = uverbs_free_pd, | |
275 | }; |