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_rwq_ind_tbl(struct ib_uobject *uobject, 79 enum rdma_remove_reason why, 80 struct uverbs_attr_bundle *attrs) 81 { 82 struct ib_rwq_ind_table *rwq_ind_tbl = uobject->object; 83 struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl; 84 u32 table_size = (1 << rwq_ind_tbl->log_ind_tbl_size); 85 int ret, i; 86 87 if (atomic_read(&rwq_ind_tbl->usecnt)) 88 return -EBUSY; 89 90 ret = rwq_ind_tbl->device->ops.destroy_rwq_ind_table(rwq_ind_tbl); 91 if (ret) 92 return ret; 93 94 for (i = 0; i < table_size; i++) 95 atomic_dec(&ind_tbl[i]->usecnt); 96 97 kfree(rwq_ind_tbl); 98 kfree(ind_tbl); 99 return 0; 100 } 101 102 static int uverbs_free_xrcd(struct ib_uobject *uobject, 103 enum rdma_remove_reason why, 104 struct uverbs_attr_bundle *attrs) 105 { 106 struct ib_xrcd *xrcd = uobject->object; 107 struct ib_uxrcd_object *uxrcd = 108 container_of(uobject, struct ib_uxrcd_object, uobject); 109 int ret; 110 111 if (atomic_read(&uxrcd->refcnt)) 112 return -EBUSY; 113 114 mutex_lock(&attrs->ufile->device->xrcd_tree_mutex); 115 ret = ib_uverbs_dealloc_xrcd(uobject, xrcd, why, attrs); 116 mutex_unlock(&attrs->ufile->device->xrcd_tree_mutex); 117 118 return ret; 119 } 120 121 static int uverbs_free_pd(struct ib_uobject *uobject, 122 enum rdma_remove_reason why, 123 struct uverbs_attr_bundle *attrs) 124 { 125 struct ib_pd *pd = uobject->object; 126 127 if (atomic_read(&pd->usecnt)) 128 return -EBUSY; 129 130 return ib_dealloc_pd_user(pd, &attrs->driver_udata); 131 } 132 133 void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue) 134 { 135 struct ib_uverbs_event *entry, *tmp; 136 137 spin_lock_irq(&event_queue->lock); 138 /* 139 * The user must ensure that no new items are added to the event_list 140 * once is_closed is set. 141 */ 142 event_queue->is_closed = 1; 143 spin_unlock_irq(&event_queue->lock); 144 wake_up_interruptible(&event_queue->poll_wait); 145 kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN); 146 147 spin_lock_irq(&event_queue->lock); 148 list_for_each_entry_safe(entry, tmp, &event_queue->event_list, list) { 149 if (entry->counter) 150 list_del(&entry->obj_list); 151 list_del(&entry->list); 152 kfree(entry); 153 } 154 spin_unlock_irq(&event_queue->lock); 155 } 156 157 static void 158 uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj, 159 enum rdma_remove_reason why) 160 { 161 struct ib_uverbs_completion_event_file *file = 162 container_of(uobj, struct ib_uverbs_completion_event_file, 163 uobj); 164 165 ib_uverbs_free_event_queue(&file->ev_queue); 166 } 167 168 int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs) 169 { 170 return 0; 171 } 172 EXPORT_SYMBOL(uverbs_destroy_def_handler); 173 174 DECLARE_UVERBS_NAMED_OBJECT( 175 UVERBS_OBJECT_COMP_CHANNEL, 176 UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file), 177 uverbs_completion_event_file_destroy_uobj, 178 &uverbs_event_fops, 179 "[infinibandevent]", 180 O_RDONLY)); 181 182 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 183 UVERBS_METHOD_MW_DESTROY, 184 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_MW_HANDLE, 185 UVERBS_OBJECT_MW, 186 UVERBS_ACCESS_DESTROY, 187 UA_MANDATORY)); 188 189 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MW, 190 UVERBS_TYPE_ALLOC_IDR(uverbs_free_mw), 191 &UVERBS_METHOD(UVERBS_METHOD_MW_DESTROY)); 192 193 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 194 UVERBS_METHOD_AH_DESTROY, 195 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_AH_HANDLE, 196 UVERBS_OBJECT_AH, 197 UVERBS_ACCESS_DESTROY, 198 UA_MANDATORY)); 199 200 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_AH, 201 UVERBS_TYPE_ALLOC_IDR(uverbs_free_ah), 202 &UVERBS_METHOD(UVERBS_METHOD_AH_DESTROY)); 203 204 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 205 UVERBS_METHOD_FLOW_DESTROY, 206 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_HANDLE, 207 UVERBS_OBJECT_FLOW, 208 UVERBS_ACCESS_DESTROY, 209 UA_MANDATORY)); 210 211 DECLARE_UVERBS_NAMED_OBJECT( 212 UVERBS_OBJECT_FLOW, 213 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uflow_object), 214 uverbs_free_flow), 215 &UVERBS_METHOD(UVERBS_METHOD_FLOW_DESTROY)); 216 217 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 218 UVERBS_METHOD_RWQ_IND_TBL_DESTROY, 219 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_RWQ_IND_TBL_HANDLE, 220 UVERBS_OBJECT_RWQ_IND_TBL, 221 UVERBS_ACCESS_DESTROY, 222 UA_MANDATORY)); 223 224 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL, 225 UVERBS_TYPE_ALLOC_IDR(uverbs_free_rwq_ind_tbl), 226 &UVERBS_METHOD(UVERBS_METHOD_RWQ_IND_TBL_DESTROY)); 227 228 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 229 UVERBS_METHOD_XRCD_DESTROY, 230 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_XRCD_HANDLE, 231 UVERBS_OBJECT_XRCD, 232 UVERBS_ACCESS_DESTROY, 233 UA_MANDATORY)); 234 235 DECLARE_UVERBS_NAMED_OBJECT( 236 UVERBS_OBJECT_XRCD, 237 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object), 238 uverbs_free_xrcd), 239 &UVERBS_METHOD(UVERBS_METHOD_XRCD_DESTROY)); 240 241 DECLARE_UVERBS_NAMED_METHOD_DESTROY( 242 UVERBS_METHOD_PD_DESTROY, 243 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_PD_HANDLE, 244 UVERBS_OBJECT_PD, 245 UVERBS_ACCESS_DESTROY, 246 UA_MANDATORY)); 247 248 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD, 249 UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd), 250 &UVERBS_METHOD(UVERBS_METHOD_PD_DESTROY)); 251 252 const struct uapi_definition uverbs_def_obj_intf[] = { 253 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_PD, 254 UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)), 255 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_COMP_CHANNEL, 256 UAPI_DEF_OBJ_NEEDS_FN(dealloc_pd)), 257 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_AH, 258 UAPI_DEF_OBJ_NEEDS_FN(destroy_ah)), 259 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MW, 260 UAPI_DEF_OBJ_NEEDS_FN(dealloc_mw)), 261 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_FLOW, 262 UAPI_DEF_OBJ_NEEDS_FN(destroy_flow)), 263 UAPI_DEF_CHAIN_OBJ_TREE_NAMED( 264 UVERBS_OBJECT_RWQ_IND_TBL, 265 UAPI_DEF_OBJ_NEEDS_FN(destroy_rwq_ind_table)), 266 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_XRCD, 267 UAPI_DEF_OBJ_NEEDS_FN(dealloc_xrcd)), 268 {} 269 }; 270