This makes async events aligned with completion events as both are full uobjects of FD type and use the same uobject lifecycle. A bunch of duplicate code is consolidated and the general flow between the two FDs is now very similar.
Unified · Split
| @@ -35,6 +35,7 @@ ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \ · 34 unmodified lines | ||
| 35 | 35 | uverbs_std_types_cq.o \ |
| 36 | 36 | uverbs_std_types_flow_action.o uverbs_std_types_dm.o \ |
| 37 | 37 | uverbs_std_types_mr.o uverbs_std_types_counters.o \ |
| 38 | − uverbs_uapi.o uverbs_std_types_device.o | |
| 38 | + uverbs_uapi.o uverbs_std_types_device.o \ | |
| 39 | + uverbs_std_types_async_fd.o | |
| 39 | 40 | ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o |
| 40 | 41 | ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o |
| @@ -151,6 +151,7 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm, · 150 unmodified lines | ||
| 151 | 151 | unsigned int num_attrs); |
| 152 | 152 | void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile); |
| 153 | 153 | |
| 154 | +extern const struct uapi_definition uverbs_def_obj_async_fd[]; | |
| 154 | 155 | extern const struct uapi_definition uverbs_def_obj_counters[]; |
| 155 | 156 | extern const struct uapi_definition uverbs_def_obj_cq[]; |
| 156 | 157 | extern const struct uapi_definition uverbs_def_obj_device[]; |
| @@ -111,7 +111,6 @@ struct ib_uverbs_device { · 110 unmodified lines | ||
| 111 | 111 | struct srcu_struct disassociate_srcu; |
| 112 | 112 | struct mutex lists_mutex; /* protect lists */ |
| 113 | 113 | struct list_head uverbs_file_list; |
| 114 | − struct list_head uverbs_events_file_list; | |
| 115 | 114 | struct uverbs_api *uapi; |
| 116 | 115 | }; |
| 117 | 116 | |
| @@ -124,10 +123,9 @@ struct ib_uverbs_event_queue { · 6 unmodified lines | ||
| 124 | 123 | }; |
| 125 | 124 | |
| 126 | 125 | struct ib_uverbs_async_event_file { |
| 126 | + struct ib_uobject uobj; | |
| 127 | 127 | struct ib_uverbs_event_queue ev_queue; |
| 128 | − struct ib_uverbs_file *uverbs_file; | |
| 129 | − struct kref ref; | |
| 130 | − struct list_head list; | |
| 128 | + struct ib_event_handler event_handler; | |
| 131 | 129 | }; |
| 132 | 130 | |
| 133 | 131 | struct ib_uverbs_completion_event_file { |
| @@ -144,8 +142,7 @@ struct ib_uverbs_file { · 10 unmodified lines | ||
| 144 | 142 | * ucontext_lock held |
| 145 | 143 | */ |
| 146 | 144 | struct ib_ucontext *ucontext; |
| 147 | − struct ib_event_handler event_handler; | |
| 148 | − struct ib_uverbs_async_event_file *async_file; | |
| 145 | + struct ib_uverbs_async_event_file *async_file; | |
| 149 | 146 | struct list_head list; |
| 150 | 147 | |
| 151 | 148 | /* |
| @@ -217,10 +214,10 @@ struct ib_ucq_object { · 65 unmodified lines | ||
| 217 | 214 | }; |
| 218 | 215 | |
| 219 | 216 | extern const struct file_operations uverbs_event_fops; |
| 217 | +extern const struct file_operations uverbs_async_event_fops; | |
| 220 | 218 | void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue); |
| 221 | −struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file, | |
| 222 | − struct ib_device *ib_dev); | |
| 223 | −void ib_uverbs_free_async_event_file(struct ib_uverbs_file *uverbs_file); | |
| 219 | +void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file); | |
| 220 | +void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue); | |
| 224 | 221 | void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res); |
| 225 | 222 | |
| 226 | 223 | void ib_uverbs_release_ucq(struct ib_uverbs_file *file, |
| @@ -209,9 +209,9 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs) · 208 unmodified lines | ||
| 209 | 209 | struct ib_uverbs_get_context cmd; |
| 210 | 210 | struct ib_uverbs_get_context_resp resp; |
| 211 | 211 | struct ib_ucontext *ucontext; |
| 212 | − struct file *filp; | |
| 213 | 212 | struct ib_rdmacg_object cg_obj; |
| 214 | 213 | struct ib_device *ib_dev; |
| 214 | + struct ib_uobject *uobj; | |
| 215 | 215 | int ret; |
| 216 | 216 | |
| 217 | 217 | ret = uverbs_request(attrs, &cmd, sizeof(cmd)); |
| @@ -254,30 +254,28 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs) · 36 unmodified lines | ||
| 254 | 254 | |
| 255 | 255 | xa_init_flags(&ucontext->mmap_xa, XA_FLAGS_ALLOC); |
| 256 | 256 | |
| 257 | − ret = get_unused_fd_flags(O_CLOEXEC); | |
| 258 | − if (ret < 0) | |
| 257 | + uobj = uobj_alloc(UVERBS_OBJECT_ASYNC_EVENT, attrs, &ib_dev); | |
| 258 | + if (IS_ERR(uobj)) { | |
| 259 | + ret = PTR_ERR(uobj); | |
| 259 | 260 | goto err_free; |
| 260 | − resp.async_fd = ret; | |
| 261 | − | |
| 262 | − filp = ib_uverbs_alloc_async_event_file(file, ib_dev); | |
| 263 | − if (IS_ERR(filp)) { | |
| 264 | − ret = PTR_ERR(filp); | |
| 265 | − goto err_fd; | |
| 266 | 261 | } |
| 267 | 262 | |
| 263 | + resp.async_fd = uobj->id; | |
| 268 | 264 | resp.num_comp_vectors = file->device->num_comp_vectors; |
| 269 | 265 | |
| 270 | 266 | ret = uverbs_response(attrs, &resp, sizeof(resp)); |
| 271 | 267 | if (ret) |
| 272 | − goto err_file; | |
| 268 | + goto err_uobj; | |
| 273 | 269 | |
| 274 | 270 | ret = ib_dev->ops.alloc_ucontext(ucontext, &attrs->driver_udata); |
| 275 | 271 | if (ret) |
| 276 | − goto err_file; | |
| 272 | + goto err_uobj; | |
| 277 | 273 | |
| 278 | 274 | rdma_restrack_uadd(&ucontext->res); |
| 279 | 275 | |
| 280 | − fd_install(resp.async_fd, filp); | |
| 276 | + ib_uverbs_init_async_event_file( | |
| 277 | + container_of(uobj, struct ib_uverbs_async_event_file, uobj)); | |
| 278 | + rdma_alloc_commit_uobject(uobj, attrs); | |
| 281 | 279 | |
| 282 | 280 | /* |
| 283 | 281 | * Make sure that ib_uverbs_get_ucontext() sees the pointer update |
| @@ -289,12 +287,8 @@ static int ib_uverbs_get_context(struct uverbs_attr_bundle *attrs) · 5 unmodified lines | ||
| 289 | 287 | |
| 290 | 288 | return 0; |
| 291 | 289 | |
| 292 | −err_file: | |
| 293 | − ib_uverbs_free_async_event_file(file); | |
| 294 | − fput(filp); | |
| 295 | − | |
| 296 | −err_fd: | |
| 297 | − put_unused_fd(resp.async_fd); | |
| 290 | +err_uobj: | |
| 291 | + rdma_alloc_abort_uobject(uobj, attrs); | |
| 298 | 292 | |
| 299 | 293 | err_free: |
| 300 | 294 | kfree(ucontext); |
| @@ -125,14 +125,6 @@ static void ib_uverbs_release_dev(struct device *device) · 124 unmodified lines | ||
| 125 | 125 | kfree(dev); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | −static void ib_uverbs_release_async_event_file(struct kref *ref) | |
| 129 | −{ | |
| 130 | − struct ib_uverbs_async_event_file *file = | |
| 131 | − container_of(ref, struct ib_uverbs_async_event_file, ref); | |
| 132 | − | |
| 133 | − kfree(file); | |
| 134 | −} | |
| 135 | − | |
| 136 | 128 | void ib_uverbs_release_ucq(struct ib_uverbs_file *file, |
| 137 | 129 | struct ib_uverbs_completion_event_file *ev_file, |
| 138 | 130 | struct ib_ucq_object *uobj) |
| @@ -203,8 +195,7 @@ void ib_uverbs_release_file(struct kref *ref) · 64 unmodified lines | ||
| 203 | 195 | ib_uverbs_comp_dev(file->device); |
| 204 | 196 | |
| 205 | 197 | if (file->async_file) |
| 206 | − kref_put(&file->async_file->ref, | |
| 207 | − ib_uverbs_release_async_event_file); | |
| 198 | + uverbs_uobject_put(&file->async_file->uobj); | |
| 208 | 199 | put_device(&file->device->dev); |
| 209 | 200 | |
| 210 | 201 | if (file->disassociate_page) |
| @@ -339,35 +330,6 @@ static int ib_uverbs_comp_event_fasync(int fd, struct file *filp, int on) · 128 unmodified lines | ||
| 339 | 330 | return fasync_helper(fd, filp, on, &comp_ev_file->ev_queue.async_queue); |
| 340 | 331 | } |
| 341 | 332 | |
| 342 | −static int ib_uverbs_async_event_close(struct inode *inode, struct file *filp) | |
| 343 | −{ | |
| 344 | − struct ib_uverbs_async_event_file *file = filp->private_data; | |
| 345 | − struct ib_uverbs_file *uverbs_file = file->uverbs_file; | |
| 346 | − struct ib_uverbs_event *entry, *tmp; | |
| 347 | − int closed_already = 0; | |
| 348 | − | |
| 349 | − mutex_lock(&uverbs_file->device->lists_mutex); | |
| 350 | − spin_lock_irq(&file->ev_queue.lock); | |
| 351 | − closed_already = file->ev_queue.is_closed; | |
| 352 | − file->ev_queue.is_closed = 1; | |
| 353 | − list_for_each_entry_safe(entry, tmp, &file->ev_queue.event_list, list) { | |
| 354 | − if (entry->counter) | |
| 355 | − list_del(&entry->obj_list); | |
| 356 | − kfree(entry); | |
| 357 | − } | |
| 358 | − spin_unlock_irq(&file->ev_queue.lock); | |
| 359 | − if (!closed_already) { | |
| 360 | − list_del(&file->list); | |
| 361 | − ib_unregister_event_handler(&uverbs_file->event_handler); | |
| 362 | − } | |
| 363 | − mutex_unlock(&uverbs_file->device->lists_mutex); | |
| 364 | − | |
| 365 | − kref_put(&uverbs_file->ref, ib_uverbs_release_file); | |
| 366 | − kref_put(&file->ref, ib_uverbs_release_async_event_file); | |
| 367 | − | |
| 368 | − return 0; | |
| 369 | −} | |
| 370 | − | |
| 371 | 333 | const struct file_operations uverbs_event_fops = { |
| 372 | 334 | .owner = THIS_MODULE, |
| 373 | 335 | .read = ib_uverbs_comp_event_read, |
| @@ -377,11 +339,11 @@ const struct file_operations uverbs_event_fops = { · 3 unmodified lines | ||
| 377 | 339 | .llseek = no_llseek, |
| 378 | 340 | }; |
| 379 | 341 | |
| 380 | −static const struct file_operations uverbs_async_event_fops = { | |
| 342 | +const struct file_operations uverbs_async_event_fops = { | |
| 381 | 343 | .owner = THIS_MODULE, |
| 382 | 344 | .read = ib_uverbs_async_event_read, |
| 383 | 345 | .poll = ib_uverbs_async_event_poll, |
| 384 | − .release = ib_uverbs_async_event_close, | |
| 346 | + .release = uverbs_uobject_fd_release, | |
| 385 | 347 | .fasync = ib_uverbs_async_event_fasync, |
| 386 | 348 | .llseek = no_llseek, |
| 387 | 349 | }; |
| @@ -491,17 +453,11 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler, · 103 unmodified lines | ||
| 491 | 453 | struct ib_event *event) |
| 492 | 454 | { |
| 493 | 455 | ib_uverbs_async_handler( |
| 494 | − container_of(handler, struct ib_uverbs_file, event_handler) | |
| 495 | − ->async_file, | |
| 456 | + container_of(handler, struct ib_uverbs_async_event_file, | |
| 457 | + event_handler), | |
| 496 | 458 | event->element.port_num, event->event, NULL, NULL); |
| 497 | 459 | } |
| 498 | 460 | |
| 499 | −void ib_uverbs_free_async_event_file(struct ib_uverbs_file *file) | |
| 500 | −{ | |
| 501 | − kref_put(&file->async_file->ref, ib_uverbs_release_async_event_file); | |
| 502 | − file->async_file = NULL; | |
| 503 | −} | |
| 504 | − | |
| 505 | 461 | void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue) |
| 506 | 462 | { |
| 507 | 463 | spin_lock_init(&ev_queue->lock); |
| @@ -511,45 +467,23 @@ void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue) · 3 unmodified lines | ||
| 511 | 467 | ev_queue->async_queue = NULL; |
| 512 | 468 | } |
| 513 | 469 | |
| 514 | −struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file, | |
| 515 | − struct ib_device *ib_dev) | |
| 470 | +void ib_uverbs_init_async_event_file( | |
| 471 | + struct ib_uverbs_async_event_file *async_file) | |
| 516 | 472 | { |
| 517 | − struct ib_uverbs_async_event_file *ev_file; | |
| 518 | − struct file *filp; | |
| 519 | − | |
| 520 | − ev_file = kzalloc(sizeof(*ev_file), GFP_KERNEL); | |
| 521 | − if (!ev_file) | |
| 522 | − return ERR_PTR(-ENOMEM); | |
| 523 | − | |
| 524 | − ib_uverbs_init_event_queue(&ev_file->ev_queue); | |
| 525 | − ev_file->uverbs_file = uverbs_file; | |
| 526 | − kref_get(&ev_file->uverbs_file->ref); | |
| 527 | − kref_init(&ev_file->ref); | |
| 528 | − filp = anon_inode_getfile("[infinibandevent]", &uverbs_async_event_fops, | |
| 529 | − ev_file, O_RDONLY); | |
| 530 | − if (IS_ERR(filp)) | |
| 531 | − goto err_put_refs; | |
| 532 | − | |
| 533 | − mutex_lock(&uverbs_file->device->lists_mutex); | |
| 534 | − list_add_tail(&ev_file->list, | |
| 535 | − &uverbs_file->device->uverbs_events_file_list); | |
| 536 | − mutex_unlock(&uverbs_file->device->lists_mutex); | |
| 537 | − | |
| 538 | − WARN_ON(uverbs_file->async_file); | |
| 539 | − uverbs_file->async_file = ev_file; | |
| 540 | − kref_get(&uverbs_file->async_file->ref); | |
| 541 | − INIT_IB_EVENT_HANDLER(&uverbs_file->event_handler, | |
| 542 | − ib_dev, | |
| 543 | − ib_uverbs_event_handler); | |
| 544 | − ib_register_event_handler(&uverbs_file->event_handler); | |
| 545 | − /* At that point async file stuff was fully set */ | |
| 473 | + struct ib_uverbs_file *uverbs_file = async_file->uobj.ufile; | |
| 474 | + struct ib_device *ib_dev = async_file->uobj.context->device; | |
| 546 | 475 | |
| 547 | − return filp; | |
| 476 | + ib_uverbs_init_event_queue(&async_file->ev_queue); | |
| 548 | 477 | |
| 549 | −err_put_refs: | |
| 550 | − kref_put(&ev_file->uverbs_file->ref, ib_uverbs_release_file); | |
| 551 | − kref_put(&ev_file->ref, ib_uverbs_release_async_event_file); | |
| 552 | − return filp; | |
| 478 | + if (!WARN_ON(uverbs_file->async_file)) { | |
| 479 | + uverbs_file->async_file = async_file; | |
| 480 | + /* Pairs with the put in ib_uverbs_release_file */ | |
| 481 | + uverbs_uobject_get(&async_file->uobj); | |
| 482 | + } | |
| 483 | + | |
| 484 | + INIT_IB_EVENT_HANDLER(&async_file->event_handler, ib_dev, | |
| 485 | + ib_uverbs_event_handler); | |
| 486 | + ib_register_event_handler(&async_file->event_handler); | |
| 553 | 487 | } |
| 554 | 488 | |
| 555 | 489 | static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr, |
| @@ -1178,7 +1112,6 @@ static void ib_uverbs_add_one(struct ib_device *device) · 622 unmodified lines | ||
| 1178 | 1112 | mutex_init(&uverbs_dev->xrcd_tree_mutex); |
| 1179 | 1113 | mutex_init(&uverbs_dev->lists_mutex); |
| 1180 | 1114 | INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); |
| 1181 | − INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); | |
| 1182 | 1115 | rcu_assign_pointer(uverbs_dev->ib_dev, device); |
| 1183 | 1116 | uverbs_dev->num_comp_vectors = device->num_comp_vectors; |
| 1184 | 1117 | |
| @@ -1223,7 +1156,6 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev, · 38 unmodified lines | ||
| 1223 | 1156 | struct ib_device *ib_dev) |
| 1224 | 1157 | { |
| 1225 | 1158 | struct ib_uverbs_file *file; |
| 1226 | − struct ib_uverbs_async_event_file *event_file; | |
| 1227 | 1159 | struct ib_event event; |
| 1228 | 1160 | |
| 1229 | 1161 | /* Pending running commands to terminate */ |
| @@ -1246,31 +1178,15 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev, · 16 unmodified lines | ||
| 1246 | 1178 | */ |
| 1247 | 1179 | mutex_unlock(&uverbs_dev->lists_mutex); |
| 1248 | 1180 | |
| 1249 | − ib_uverbs_event_handler(&file->event_handler, &event); | |
| 1181 | + if (file->async_file) | |
| 1182 | + ib_uverbs_event_handler( | |
| 1183 | + &file->async_file->event_handler, &event); | |
| 1184 | + | |
| 1250 | 1185 | uverbs_destroy_ufile_hw(file, RDMA_REMOVE_DRIVER_REMOVE); |
| 1251 | 1186 | kref_put(&file->ref, ib_uverbs_release_file); |
| 1252 | 1187 | |
| 1253 | 1188 | mutex_lock(&uverbs_dev->lists_mutex); |
| 1254 | 1189 | } |
| 1255 | − | |
| 1256 | − while (!list_empty(&uverbs_dev->uverbs_events_file_list)) { | |
| 1257 | − event_file = list_first_entry(&uverbs_dev-> | |
| 1258 | − uverbs_events_file_list, | |
| 1259 | − struct ib_uverbs_async_event_file, | |
| 1260 | − list); | |
| 1261 | − spin_lock_irq(&event_file->ev_queue.lock); | |
| 1262 | − event_file->ev_queue.is_closed = 1; | |
| 1263 | − spin_unlock_irq(&event_file->ev_queue.lock); | |
| 1264 | − | |
| 1265 | − list_del(&event_file->list); | |
| 1266 | − ib_unregister_event_handler( | |
| 1267 | − &event_file->uverbs_file->event_handler); | |
| 1268 | − event_file->uverbs_file->event_handler.device = | |
| 1269 | − NULL; | |
| 1270 | − | |
| 1271 | − wake_up_interruptible(&event_file->ev_queue.poll_wait); | |
| 1272 | − kill_fasync(&event_file->ev_queue.async_queue, SIGIO, POLL_IN); | |
| 1273 | − } | |
| 1274 | 1190 | mutex_unlock(&uverbs_dev->lists_mutex); |
| 1275 | 1191 | |
| 1276 | 1192 | uverbs_disassociate_api(uverbs_dev->uapi); |
| @@ -202,17 +202,15 @@ static int uverbs_free_pd(struct ib_uobject *uobject, · 201 unmodified lines | ||
| 202 | 202 | return 0; |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | −static int | |
| 206 | −uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj, | |
| 207 | − enum rdma_remove_reason why) | |
| 205 | +void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue) | |
| 208 | 206 | { |
| 209 | − struct ib_uverbs_completion_event_file *file = | |
| 210 | − container_of(uobj, struct ib_uverbs_completion_event_file, | |
| 211 | − uobj); | |
| 212 | − struct ib_uverbs_event_queue *event_queue = &file->ev_queue; | |
| 213 | 207 | struct ib_uverbs_event *entry, *tmp; |
| 214 | 208 | |
| 215 | 209 | spin_lock_irq(&event_queue->lock); |
| 210 | + /* | |
| 211 | + * The user must ensure that no new items are added to the event_list | |
| 212 | + * once is_closed is set. | |
| 213 | + */ | |
| 216 | 214 | event_queue->is_closed = 1; |
| 217 | 215 | spin_unlock_irq(&event_queue->lock); |
| 218 | 216 | wake_up_interruptible(&event_queue->poll_wait); |
| @@ -225,8 +223,19 @@ uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj, · 6 unmodified lines | ||
| 225 | 223 | kfree(entry); |
| 226 | 224 | } |
| 227 | 225 | spin_unlock_irq(&event_queue->lock); |
| 226 | +} | |
| 227 | + | |
| 228 | +static int | |
| 229 | +uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj, | |
| 230 | + enum rdma_remove_reason why) | |
| 231 | +{ | |
| 232 | + struct ib_uverbs_completion_event_file *file = | |
| 233 | + container_of(uobj, struct ib_uverbs_completion_event_file, | |
| 234 | + uobj); | |
| 235 | + | |
| 236 | + ib_uverbs_free_event_queue(&file->ev_queue); | |
| 228 | 237 | return 0; |
| 229 | −}; | |
| 238 | +} | |
| 230 | 239 | |
| 231 | 240 | int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs) |
| 232 | 241 | { |
| @@ -0,0 +1,33 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB | |
| 2 | +/* | |
| 3 | + * Copyright (c) 2019, Mellanox Technologies inc. All rights reserved. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +#include <rdma/uverbs_std_types.h> | |
| 7 | +#include <rdma/uverbs_ioctl.h> | |
| 8 | +#include "rdma_core.h" | |
| 9 | +#include "uverbs.h" | |
| 10 | + | |
| 11 | +static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, | |
| 12 | + enum rdma_remove_reason why) | |
| 13 | +{ | |
| 14 | + struct ib_uverbs_async_event_file *event_file = | |
| 15 | + container_of(uobj, struct ib_uverbs_async_event_file, uobj); | |
| 16 | + | |
| 17 | + ib_unregister_event_handler(&event_file->event_handler); | |
| 18 | + ib_uverbs_free_event_queue(&event_file->ev_queue); | |
| 19 | + return 0; | |
| 20 | +} | |
| 21 | + | |
| 22 | +DECLARE_UVERBS_NAMED_OBJECT( | |
| 23 | + UVERBS_OBJECT_ASYNC_EVENT, | |
| 24 | + UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_async_event_file), | |
| 25 | + uverbs_async_event_destroy_uobj, | |
| 26 | + &uverbs_async_event_fops, | |
| 27 | + "[infinibandevent]", | |
| 28 | + O_RDONLY)); | |
| 29 | + | |
| 30 | +const struct uapi_definition uverbs_def_obj_async_fd[] = { | |
| 31 | + UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_ASYNC_EVENT), | |
| 32 | + {} | |
| 33 | +}; | |
| @@ -626,6 +626,7 @@ void uverbs_destroy_api(struct uverbs_api *uapi) · 625 unmodified lines | ||
| 626 | 626 | } |
| 627 | 627 | |
| 628 | 628 | static const struct uapi_definition uverbs_core_api[] = { |
| 629 | + UAPI_DEF_CHAIN(uverbs_def_obj_async_fd), | |
| 629 | 630 | UAPI_DEF_CHAIN(uverbs_def_obj_counters), |
| 630 | 631 | UAPI_DEF_CHAIN(uverbs_def_obj_cq), |
| 631 | 632 | UAPI_DEF_CHAIN(uverbs_def_obj_device), |
| @@ -56,6 +56,7 @@ enum uverbs_default_objects { · 55 unmodified lines | ||
| 56 | 56 | UVERBS_OBJECT_FLOW_ACTION, |
| 57 | 57 | UVERBS_OBJECT_DM, |
| 58 | 58 | UVERBS_OBJECT_COUNTERS, |
| 59 | + UVERBS_OBJECT_ASYNC_EVENT, | |
| 59 | 60 | }; |
| 60 | 61 | |
| 61 | 62 | enum { |