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/restrack.h> 39 #include "rdma_core.h" 40 #include "uverbs.h" 41 42 static int uverbs_free_ah(struct ib_uobject *uobject, 43 enum rdma_remove_reason why, 44 struct uverbs_attr_bundle *attrs) 45 { 46 return rdma_destroy_ah_user((struct ib_ah *)uobject->object, 47 RDMA_DESTROY_AH_SLEEPABLE, 48 &attrs->driver_udata); 49 } 50 51 static int uverbs_free_flow(struct ib_uobject *uobject, 52 enum rdma_remove_reason why, 53 struct uverbs_attr_bundle *attrs) 54 { 55 struct ib_flow *flow = (struct ib_flow *)uobject->object; 56 struct ib_uflow_object *uflow = 57 container_of(uobject, struct ib_uflow_object, uobject); 58 struct ib_qp *qp = flow->qp; 59 int ret; 60 61 ret = flow->device->ops.destroy_flow(flow); 62 if (!ret) { 63 if (qp) 64 atomic_dec(&qp->usecnt); 65 ib_uverbs_flow_resources_free(uflow->resources); 66 } 67 68 return ret; 69 } 70 71 static int uverbs_free_mw(struct ib_uobject *uobject, 72 enum rdma_remove_reason why, 73 struct uverbs_attr_bundle *attrs) 74 { 75 return uverbs_dealloc_mw((struct ib_mw *)uobject->object); 76 } 77 78 static int uverbs_free_qp(struct ib_uobject *uobject, 79 enum rdma_remove_reason why, 80 struct uverbs_attr_bundle *attrs) 81 { 82 struct ib_qp *qp = uobject->object; 83 struct ib_uqp_object *uqp = 84 container_of(uobject, struct ib_uqp_object, uevent.uobject); 85 int ret; 86 87 /* 88 * If this is a user triggered destroy then do not allow destruction 89 * until the user cleans up all the mcast bindings. Unlike in other 90 * places we forcibly clean up the mcast attachments for !DESTROY 91 * because the mcast attaches are not ubojects and will not be 92 * destroyed by anything else during cleanup processing. 93 */ 94 if (why == RDMA_REMOVE_DESTROY) { 95 if (!list_empty(&uqp->mcast_list)) 96 return -EBUSY; 97 } else if (qp == qp->real_qp) { 98 ib_uverbs_detach_umcast(qp, uqp); 99 } 100 101 ret = ib_destroy_qp_user(qp, &attrs->driver_udata); 102 if (ib_is_destroy_retryable(ret, why, uobject)) 103 return ret; 104 105 if (uqp->uxrcd) 106 atomic_dec(&uqp->uxrcd->refcnt); 107 108 ib_uverbs_release_uevent(attrs->ufile, &uqp->uevent); 109 return ret; 110 } 111 112 static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject, 113 enum rdma_remove_reason why, 114 struct uverbs_attr_bundle *attrs) 115 { 116 struct ib_rwq_ind_table *rwq_ind_tbl = uobject->object; 117 struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl; 118 int ret; 119 120 ret = ib_destroy_rwq_ind_table(rwq_ind_tbl); 121 if (ib_is_destroy_retryable(ret, why, uobject)) 122 return ret; 123 124 kfree(ind_tbl); 125 return ret; 126 } 127 128 static int uverbs_free_wq(struct ib_uobject *uobject, 129 enum rdma_remove_reason why, 130 struct uverbs_attr_bundle *attrs) 131 { 132 struct ib_wq *wq = uobject->object; 133 struct ib_uwq_object *uwq = 134 container_of(uobject, struct ib_uwq_object, uevent.uobject); 135 int ret; 136 137 ret = ib_destroy_wq(wq, &attrs->driver_udata); 138 if (ib_is_destroy_retryable(ret, why, uobject)) 139 return ret; 140 141 ib_uverbs_release_uevent(attrs->ufile, &uwq->uevent); 142 return ret; 143 } 144 145 static int uverbs_free_srq(struct ib_uobject *uobject, 146 enum rdma_remove_reason why, 147 struct uverbs_attr_bundle *attrs) 148 { 149 struct ib_srq *srq = uobject->object; 150 struct ib_uevent_object *uevent = 151 container_of(uobject, struct ib_uevent_object, uobject); 152 enum ib_srq_type srq_type = srq->srq_type; 153 int ret; 154 155 ret = ib_destroy_srq_user(srq, &attrs->driver_udata); 156 if (ib_is_destroy_retryable(ret, why, uobject)) 157 return ret; 158 159 if (srq_type == IB_SRQT_XRC) { 160 struct ib_usrq_object *us = 161 container_of(uevent, struct ib_usrq_object, uevent); 162 163 atomic_dec(&us->uxrcd->refcnt); 164 } 165 166 ib_uverbs_release_uevent(attrs->ufile, uevent); 167 return ret; 168 } 169 170 static int uverbs_free_xrcd(struct ib_uobject *uobject, 171 enum rdma_remove_reason why, 172 struct uverbs_attr_bundle *attrs) 173 { 174 struct ib_xrcd *xrcd = uobject->object; 175 struct ib_uxrcd_object *uxrcd = 176 container_of(uobject, struct ib_uxrcd_object, uobject); 177 int ret; 178 179 ret = ib_destroy_usecnt(&uxrcd->refcnt, why, uobject); 180 if (ret) 181 return ret; 182 183 mutex_lock(&attrs->ufile->device->xrcd_tree_mutex); 184 ret = ib_uverbs_dealloc_xrcd(uobject, xrcd, why, attrs); 185 mutex_unlock(&attrs->ufile->device->xrcd_tree_mutex); 186 187 return ret; 188 } 189 190 static int uverbs_free_pd(struct ib_uobject *uobject, 191 enum rdma_remove_reason why, 192 struct uverbs_attr_bundle *attrs) 193 { 194 struct ib_pd *pd = uobject->object; 195 int ret; 196 197 ret = ib_destroy_usecnt(&pd->usecnt, why, uobject); 198 if (ret) 199 return ret; 200 201 ib_dealloc_pd_user(pd, &attrs->driver_udata); 202 return 0; 203 } 204 205 static int uverbs_hot_unplug_completion_event_file(struct ib_uobject *uobj, 206 enum rdma_remove_reason why) 207 { 208 struct ib_uverbs_completion_event_file *comp_event_file = 209 container_of(uobj, struct ib_uverbs_completion_event_file, 210 uobj); 211 struct ib_uverbs_event_queue *event_queue = &comp_event_file->ev_queue; 212 213 spin_lock_irq(&event_queue->lock); 214 event_queue->is_closed = 1; 215 spin_unlock_irq(&event_queue->lock); 216 217 if (why == RDMA_REMOVE_DRIVER_REMOVE) { 218 wake_up_interruptible(&event_queue->poll_wait); 219 kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN); 220 } 221 return 0; 222 }; 223 224 int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs) 225 { 226 return 0; 227 } 228 EXPORT_SYMBOL(uverbs_destroy_def_handler); 229 230 DECLARE_UVERBS_NAMED_OBJECT( 231 UVERBS_OBJECT_COMP_CHANNEL, 232 UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), 233 uverbs_hot_unplug_completion_event_file, 234 &uverbs_event_fops, 235 "[infinibandevent]", 236 O_RDONLY)); 237 238 DECLARE_UVERBS_NAMED_OBJECT( 239 UVERBS_OBJECT_QP, 240 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), uverbs_free_qp)); 241 242 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 243 UVERBS_METHOD_MW_DESTROY, 244 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_MW_HANDLE, 245 UVERBS_OBJECT_MW, 246 UVERBS_ACCESS_DESTROY, 247 UA_MANDATORY)); 248 249 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MW, 250 UVERBS_TYPE_ALLOC_IDR(uverbs_free_mw), 251 &UVERBS_METHOD(UVERBS_METHOD_MW_DESTROY)); 252 253 DECLARE_UVERBS_NAMED_OBJECT( 254 UVERBS_OBJECT_SRQ, 255 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object), 256 uverbs_free_srq)); 257 258 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 259 UVERBS_METHOD_AH_DESTROY, 260 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_AH_HANDLE, 261 UVERBS_OBJECT_AH, 262 UVERBS_ACCESS_DESTROY, 263 UA_MANDATORY)); 264 265 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_AH, 266 UVERBS_TYPE_ALLOC_IDR(uverbs_free_ah), 267 &UVERBS_METHOD(UVERBS_METHOD_AH_DESTROY)); 268 269 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 270 UVERBS_METHOD_FLOW_DESTROY, 271 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_HANDLE, 272 UVERBS_OBJECT_FLOW, 273 UVERBS_ACCESS_DESTROY, 274 UA_MANDATORY)); 275 276 DECLARE_UVERBS_NAMED_OBJECT( 277 UVERBS_OBJECT_FLOW, 278 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uflow_object), 279 uverbs_free_flow), 280 &UVERBS_METHOD(UVERBS_METHOD_FLOW_DESTROY)); 281 282 DECLARE_UVERBS_NAMED_OBJECT( 283 UVERBS_OBJECT_WQ, 284 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), uverbs_free_wq)); 285 286 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 287 UVERBS_METHOD_RWQ_IND_TBL_DESTROY, 288 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_RWQ_IND_TBL_HANDLE, 289 UVERBS_OBJECT_RWQ_IND_TBL, 290 UVERBS_ACCESS_DESTROY, 291 UA_MANDATORY)); 292 293 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL, 294 UVERBS_TYPE_ALLOC_IDR(uverbs_free_rwq_ind_tbl), 295 &UVERBS_METHOD(UVERBS_METHOD_RWQ_IND_TBL_DESTROY)); 296 297 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 298 UVERBS_METHOD_XRCD_DESTROY, 299 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_XRCD_HANDLE, 300 UVERBS_OBJECT_XRCD, 301 UVERBS_ACCESS_DESTROY, 302 UA_MANDATORY)); 303 304 DECLARE_UVERBS_NAMED_OBJECT( 305 UVERBS_OBJECT_XRCD, 306 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object), 307 uverbs_free_xrcd), 308 &UVERBS_METHOD(UVERBS_METHOD_XRCD_DESTROY)); 309 310 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 311 UVERBS_METHOD_PD_DESTROY, 312 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_PD_HANDLE, 313 UVERBS_OBJECT_PD, 314 UVERBS_ACCESS_DESTROY, 315 UA_MANDATORY)); 316 317 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD, 318 UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd), 319 &UVERBS_METHOD(UVERBS_METHOD_PD_DESTROY)); 320 321 const struct uapi_definition uverbs_def_obj_intf[] = { 322 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD, 323 UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)), 324 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL, 325 UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)), 326 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_QP, 327 UAPI_DEF_OBJ_NEEDS_FN(destroy_qp)), 328 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_AH, 329 UAPI_DEF_OBJ_NEEDS_FN(destroy_ah)), 330 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW, 331 UAPI_DEF_OBJ_NEEDS_FN(dealloc_mw)), 332 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ, 333 UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)), 334 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW, 335 UAPI_DEF_OBJ_NEEDS_FN(destroy_flow)), 336 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_WQ, 337 UAPI_DEF_OBJ_NEEDS_FN(destroy_wq)), 338 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 339 UVERBS_OBJECT_RWQ_IND_TBL, 340 UAPI_DEF_OBJ_NEEDS_FN(destroy_rwq_ind_table)), 341 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_XRCD, 342 UAPI_DEF_OBJ_NEEDS_FN(dealloc_xrcd)), 343 {} 344 }; 345