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