1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Cisco Systems. All rights reserved. 4 * Copyright (c) 2005 Mellanox Technologies. All rights reserved. 5 * Copyright (c) 2005 Voltaire, Inc. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 * $Id: uverbs_main.c 2733 2005-06-28 19:14:34Z roland $ 36 */ 37 38 #include <linux/module.h> 39 #include <linux/init.h> 40 #include <linux/device.h> 41 #include <linux/err.h> 42 #include <linux/fs.h> 43 #include <linux/poll.h> 44 #include <linux/file.h> 45 #include <linux/mount.h> 46 47 #include <asm/uaccess.h> 48 49 #include "uverbs.h" 50 51 MODULE_AUTHOR("Roland Dreier"); 52 MODULE_DESCRIPTION("InfiniBand userspace verbs access"); 53 MODULE_LICENSE("Dual BSD/GPL"); 54 55 #define INFINIBANDEVENTFS_MAGIC 0x49426576 /* "IBev" */ 56 57 enum { 58 IB_UVERBS_MAJOR = 231, 59 IB_UVERBS_BASE_MINOR = 192, 60 IB_UVERBS_MAX_DEVICES = 32 61 }; 62 63 #define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR) 64 65 DECLARE_MUTEX(ib_uverbs_idr_mutex); 66 DEFINE_IDR(ib_uverbs_pd_idr); 67 DEFINE_IDR(ib_uverbs_mr_idr); 68 DEFINE_IDR(ib_uverbs_mw_idr); 69 DEFINE_IDR(ib_uverbs_ah_idr); 70 DEFINE_IDR(ib_uverbs_cq_idr); 71 DEFINE_IDR(ib_uverbs_qp_idr); 72 DEFINE_IDR(ib_uverbs_srq_idr); 73 74 static spinlock_t map_lock; 75 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); 76 77 static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, 78 const char __user *buf, int in_len, 79 int out_len) = { 80 [IB_USER_VERBS_CMD_QUERY_PARAMS] = ib_uverbs_query_params, 81 [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context, 82 [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device, 83 [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port, 84 [IB_USER_VERBS_CMD_QUERY_GID] = ib_uverbs_query_gid, 85 [IB_USER_VERBS_CMD_QUERY_PKEY] = ib_uverbs_query_pkey, 86 [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd, 87 [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd, 88 [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr, 89 [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr, 90 [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq, 91 [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq, 92 [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp, 93 [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp, 94 [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp, 95 [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast, 96 [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast, 97 [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq, 98 [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq, 99 [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, 100 }; 101 102 static struct vfsmount *uverbs_event_mnt; 103 104 static void ib_uverbs_add_one(struct ib_device *device); 105 static void ib_uverbs_remove_one(struct ib_device *device); 106 107 static int ib_dealloc_ucontext(struct ib_ucontext *context) 108 { 109 struct ib_uobject *uobj, *tmp; 110 111 if (!context) 112 return 0; 113 114 down(&ib_uverbs_idr_mutex); 115 116 /* XXX Free AHs */ 117 118 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) { 119 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id); 120 idr_remove(&ib_uverbs_qp_idr, uobj->id); 121 ib_destroy_qp(qp); 122 list_del(&uobj->list); 123 kfree(uobj); 124 } 125 126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 127 struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id); 128 idr_remove(&ib_uverbs_cq_idr, uobj->id); 129 ib_destroy_cq(cq); 130 list_del(&uobj->list); 131 kfree(uobj); 132 } 133 134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 135 struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id); 136 idr_remove(&ib_uverbs_srq_idr, uobj->id); 137 ib_destroy_srq(srq); 138 list_del(&uobj->list); 139 kfree(uobj); 140 } 141 142 /* XXX Free MWs */ 143 144 list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) { 145 struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id); 146 struct ib_device *mrdev = mr->device; 147 struct ib_umem_object *memobj; 148 149 idr_remove(&ib_uverbs_mr_idr, uobj->id); 150 ib_dereg_mr(mr); 151 152 memobj = container_of(uobj, struct ib_umem_object, uobject); 153 ib_umem_release_on_close(mrdev, &memobj->umem); 154 155 list_del(&uobj->list); 156 kfree(memobj); 157 } 158 159 list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { 160 struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id); 161 idr_remove(&ib_uverbs_pd_idr, uobj->id); 162 ib_dealloc_pd(pd); 163 list_del(&uobj->list); 164 kfree(uobj); 165 } 166 167 up(&ib_uverbs_idr_mutex); 168 169 return context->device->dealloc_ucontext(context); 170 } 171 172 static void ib_uverbs_release_file(struct kref *ref) 173 { 174 struct ib_uverbs_file *file = 175 container_of(ref, struct ib_uverbs_file, ref); 176 177 module_put(file->device->ib_dev->owner); 178 kfree(file); 179 } 180 181 static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf, 182 size_t count, loff_t *pos) 183 { 184 struct ib_uverbs_event_file *file = filp->private_data; 185 void *event; 186 int eventsz; 187 int ret = 0; 188 189 spin_lock_irq(&file->lock); 190 191 while (list_empty(&file->event_list) && file->fd >= 0) { 192 spin_unlock_irq(&file->lock); 193 194 if (filp->f_flags & O_NONBLOCK) 195 return -EAGAIN; 196 197 if (wait_event_interruptible(file->poll_wait, 198 !list_empty(&file->event_list) || 199 file->fd < 0)) 200 return -ERESTARTSYS; 201 202 spin_lock_irq(&file->lock); 203 } 204 205 if (file->fd < 0) { 206 spin_unlock_irq(&file->lock); 207 return -ENODEV; 208 } 209 210 if (file->is_async) { 211 event = list_entry(file->event_list.next, 212 struct ib_uverbs_async_event, list); 213 eventsz = sizeof (struct ib_uverbs_async_event_desc); 214 } else { 215 event = list_entry(file->event_list.next, 216 struct ib_uverbs_comp_event, list); 217 eventsz = sizeof (struct ib_uverbs_comp_event_desc); 218 } 219 220 if (eventsz > count) { 221 ret = -EINVAL; 222 event = NULL; 223 } else 224 list_del(file->event_list.next); 225 226 spin_unlock_irq(&file->lock); 227 228 if (event) { 229 if (copy_to_user(buf, event, eventsz)) 230 ret = -EFAULT; 231 else 232 ret = eventsz; 233 } 234 235 kfree(event); 236 237 return ret; 238 } 239 240 static unsigned int ib_uverbs_event_poll(struct file *filp, 241 struct poll_table_struct *wait) 242 { 243 unsigned int pollflags = 0; 244 struct ib_uverbs_event_file *file = filp->private_data; 245 246 poll_wait(filp, &file->poll_wait, wait); 247 248 spin_lock_irq(&file->lock); 249 if (file->fd < 0) 250 pollflags = POLLERR; 251 else if (!list_empty(&file->event_list)) 252 pollflags = POLLIN | POLLRDNORM; 253 spin_unlock_irq(&file->lock); 254 255 return pollflags; 256 } 257 258 static void ib_uverbs_event_release(struct ib_uverbs_event_file *file) 259 { 260 struct list_head *entry, *tmp; 261 262 spin_lock_irq(&file->lock); 263 if (file->fd != -1) { 264 file->fd = -1; 265 list_for_each_safe(entry, tmp, &file->event_list) 266 if (file->is_async) 267 kfree(list_entry(entry, struct ib_uverbs_async_event, list)); 268 else 269 kfree(list_entry(entry, struct ib_uverbs_comp_event, list)); 270 } 271 spin_unlock_irq(&file->lock); 272 } 273 274 static int ib_uverbs_event_fasync(int fd, struct file *filp, int on) 275 { 276 struct ib_uverbs_event_file *file = filp->private_data; 277 278 return fasync_helper(fd, filp, on, &file->async_queue); 279 } 280 281 static int ib_uverbs_event_close(struct inode *inode, struct file *filp) 282 { 283 struct ib_uverbs_event_file *file = filp->private_data; 284 285 ib_uverbs_event_release(file); 286 ib_uverbs_event_fasync(-1, filp, 0); 287 kref_put(&file->uverbs_file->ref, ib_uverbs_release_file); 288 289 return 0; 290 } 291 292 static struct file_operations uverbs_event_fops = { 293 /* 294 * No .owner field since we artificially create event files, 295 * so there is no increment to the module reference count in 296 * the open path. All event files come from a uverbs command 297 * file, which already takes a module reference, so this is OK. 298 */ 299 .read = ib_uverbs_event_read, 300 .poll = ib_uverbs_event_poll, 301 .release = ib_uverbs_event_close, 302 .fasync = ib_uverbs_event_fasync 303 }; 304 305 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) 306 { 307 struct ib_uverbs_file *file = cq_context; 308 struct ib_uverbs_comp_event *entry; 309 unsigned long flags; 310 311 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 312 if (!entry) 313 return; 314 315 entry->desc.cq_handle = cq->uobject->user_handle; 316 317 spin_lock_irqsave(&file->comp_file[0].lock, flags); 318 list_add_tail(&entry->list, &file->comp_file[0].event_list); 319 spin_unlock_irqrestore(&file->comp_file[0].lock, flags); 320 321 wake_up_interruptible(&file->comp_file[0].poll_wait); 322 kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN); 323 } 324 325 static void ib_uverbs_async_handler(struct ib_uverbs_file *file, 326 __u64 element, __u64 event) 327 { 328 struct ib_uverbs_async_event *entry; 329 unsigned long flags; 330 331 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 332 if (!entry) 333 return; 334 335 entry->desc.element = element; 336 entry->desc.event_type = event; 337 338 spin_lock_irqsave(&file->async_file.lock, flags); 339 list_add_tail(&entry->list, &file->async_file.event_list); 340 spin_unlock_irqrestore(&file->async_file.lock, flags); 341 342 wake_up_interruptible(&file->async_file.poll_wait); 343 kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN); 344 } 345 346 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) 347 { 348 ib_uverbs_async_handler(context_ptr, 349 event->element.cq->uobject->user_handle, 350 event->event); 351 } 352 353 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) 354 { 355 ib_uverbs_async_handler(context_ptr, 356 event->element.qp->uobject->user_handle, 357 event->event); 358 } 359 360 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) 361 { 362 ib_uverbs_async_handler(context_ptr, 363 event->element.srq->uobject->user_handle, 364 event->event); 365 } 366 367 static void ib_uverbs_event_handler(struct ib_event_handler *handler, 368 struct ib_event *event) 369 { 370 struct ib_uverbs_file *file = 371 container_of(handler, struct ib_uverbs_file, event_handler); 372 373 ib_uverbs_async_handler(file, event->element.port_num, event->event); 374 } 375 376 static int ib_uverbs_event_init(struct ib_uverbs_event_file *file, 377 struct ib_uverbs_file *uverbs_file) 378 { 379 struct file *filp; 380 381 spin_lock_init(&file->lock); 382 INIT_LIST_HEAD(&file->event_list); 383 init_waitqueue_head(&file->poll_wait); 384 file->uverbs_file = uverbs_file; 385 file->async_queue = NULL; 386 387 file->fd = get_unused_fd(); 388 if (file->fd < 0) 389 return file->fd; 390 391 filp = get_empty_filp(); 392 if (!filp) { 393 put_unused_fd(file->fd); 394 return -ENFILE; 395 } 396 397 filp->f_op = &uverbs_event_fops; 398 filp->f_vfsmnt = mntget(uverbs_event_mnt); 399 filp->f_dentry = dget(uverbs_event_mnt->mnt_root); 400 filp->f_mapping = filp->f_dentry->d_inode->i_mapping; 401 filp->f_flags = O_RDONLY; 402 filp->f_mode = FMODE_READ; 403 filp->private_data = file; 404 405 fd_install(file->fd, filp); 406 407 return 0; 408 } 409 410 static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, 411 size_t count, loff_t *pos) 412 { 413 struct ib_uverbs_file *file = filp->private_data; 414 struct ib_uverbs_cmd_hdr hdr; 415 416 if (count < sizeof hdr) 417 return -EINVAL; 418 419 if (copy_from_user(&hdr, buf, sizeof hdr)) 420 return -EFAULT; 421 422 if (hdr.in_words * 4 != count) 423 return -EINVAL; 424 425 if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table)) 426 return -EINVAL; 427 428 if (!file->ucontext && 429 hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS && 430 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT) 431 return -EINVAL; 432 433 return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr, 434 hdr.in_words * 4, hdr.out_words * 4); 435 } 436 437 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) 438 { 439 struct ib_uverbs_file *file = filp->private_data; 440 441 if (!file->ucontext) 442 return -ENODEV; 443 else 444 return file->device->ib_dev->mmap(file->ucontext, vma); 445 } 446 447 static int ib_uverbs_open(struct inode *inode, struct file *filp) 448 { 449 struct ib_uverbs_device *dev = 450 container_of(inode->i_cdev, struct ib_uverbs_device, dev); 451 struct ib_uverbs_file *file; 452 int i = 0; 453 int ret; 454 455 if (!try_module_get(dev->ib_dev->owner)) 456 return -ENODEV; 457 458 file = kmalloc(sizeof *file + 459 (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file), 460 GFP_KERNEL); 461 if (!file) 462 return -ENOMEM; 463 464 file->device = dev; 465 kref_init(&file->ref); 466 467 file->ucontext = NULL; 468 469 ret = ib_uverbs_event_init(&file->async_file, file); 470 if (ret) 471 goto err; 472 473 file->async_file.is_async = 1; 474 475 kref_get(&file->ref); 476 477 for (i = 0; i < dev->num_comp; ++i) { 478 ret = ib_uverbs_event_init(&file->comp_file[i], file); 479 if (ret) 480 goto err_async; 481 kref_get(&file->ref); 482 file->comp_file[i].is_async = 0; 483 } 484 485 486 filp->private_data = file; 487 488 INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev, 489 ib_uverbs_event_handler); 490 if (ib_register_event_handler(&file->event_handler)) 491 goto err_async; 492 493 return 0; 494 495 err_async: 496 while (i--) 497 ib_uverbs_event_release(&file->comp_file[i]); 498 499 ib_uverbs_event_release(&file->async_file); 500 501 err: 502 kref_put(&file->ref, ib_uverbs_release_file); 503 504 return ret; 505 } 506 507 static int ib_uverbs_close(struct inode *inode, struct file *filp) 508 { 509 struct ib_uverbs_file *file = filp->private_data; 510 int i; 511 512 ib_unregister_event_handler(&file->event_handler); 513 ib_uverbs_event_release(&file->async_file); 514 ib_dealloc_ucontext(file->ucontext); 515 516 for (i = 0; i < file->device->num_comp; ++i) 517 ib_uverbs_event_release(&file->comp_file[i]); 518 519 kref_put(&file->ref, ib_uverbs_release_file); 520 521 return 0; 522 } 523 524 static struct file_operations uverbs_fops = { 525 .owner = THIS_MODULE, 526 .write = ib_uverbs_write, 527 .open = ib_uverbs_open, 528 .release = ib_uverbs_close 529 }; 530 531 static struct file_operations uverbs_mmap_fops = { 532 .owner = THIS_MODULE, 533 .write = ib_uverbs_write, 534 .mmap = ib_uverbs_mmap, 535 .open = ib_uverbs_open, 536 .release = ib_uverbs_close 537 }; 538 539 static struct ib_client uverbs_client = { 540 .name = "uverbs", 541 .add = ib_uverbs_add_one, 542 .remove = ib_uverbs_remove_one 543 }; 544 545 static ssize_t show_ibdev(struct class_device *class_dev, char *buf) 546 { 547 struct ib_uverbs_device *dev = 548 container_of(class_dev, struct ib_uverbs_device, class_dev); 549 550 return sprintf(buf, "%s\n", dev->ib_dev->name); 551 } 552 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); 553 554 static void ib_uverbs_release_class_dev(struct class_device *class_dev) 555 { 556 struct ib_uverbs_device *dev = 557 container_of(class_dev, struct ib_uverbs_device, class_dev); 558 559 cdev_del(&dev->dev); 560 clear_bit(dev->devnum, dev_map); 561 kfree(dev); 562 } 563 564 static struct class uverbs_class = { 565 .name = "infiniband_verbs", 566 .release = ib_uverbs_release_class_dev 567 }; 568 569 static ssize_t show_abi_version(struct class *class, char *buf) 570 { 571 return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION); 572 } 573 static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); 574 575 static void ib_uverbs_add_one(struct ib_device *device) 576 { 577 struct ib_uverbs_device *uverbs_dev; 578 579 if (!device->alloc_ucontext) 580 return; 581 582 uverbs_dev = kmalloc(sizeof *uverbs_dev, GFP_KERNEL); 583 if (!uverbs_dev) 584 return; 585 586 memset(uverbs_dev, 0, sizeof *uverbs_dev); 587 588 spin_lock(&map_lock); 589 uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); 590 if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) { 591 spin_unlock(&map_lock); 592 goto err; 593 } 594 set_bit(uverbs_dev->devnum, dev_map); 595 spin_unlock(&map_lock); 596 597 uverbs_dev->ib_dev = device; 598 uverbs_dev->num_comp = 1; 599 600 if (device->mmap) 601 cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops); 602 else 603 cdev_init(&uverbs_dev->dev, &uverbs_fops); 604 uverbs_dev->dev.owner = THIS_MODULE; 605 kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum); 606 if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1)) 607 goto err; 608 609 uverbs_dev->class_dev.class = &uverbs_class; 610 uverbs_dev->class_dev.dev = device->dma_device; 611 uverbs_dev->class_dev.devt = uverbs_dev->dev.dev; 612 snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum); 613 if (class_device_register(&uverbs_dev->class_dev)) 614 goto err_cdev; 615 616 if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev)) 617 goto err_class; 618 619 ib_set_client_data(device, &uverbs_client, uverbs_dev); 620 621 return; 622 623 err_class: 624 class_device_unregister(&uverbs_dev->class_dev); 625 626 err_cdev: 627 cdev_del(&uverbs_dev->dev); 628 clear_bit(uverbs_dev->devnum, dev_map); 629 630 err: 631 kfree(uverbs_dev); 632 return; 633 } 634 635 static void ib_uverbs_remove_one(struct ib_device *device) 636 { 637 struct ib_uverbs_device *uverbs_dev = ib_get_client_data(device, &uverbs_client); 638 639 if (!uverbs_dev) 640 return; 641 642 class_device_unregister(&uverbs_dev->class_dev); 643 } 644 645 static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags, 646 const char *dev_name, void *data) 647 { 648 return get_sb_pseudo(fs_type, "infinibandevent:", NULL, 649 INFINIBANDEVENTFS_MAGIC); 650 } 651 652 static struct file_system_type uverbs_event_fs = { 653 /* No owner field so module can be unloaded */ 654 .name = "infinibandeventfs", 655 .get_sb = uverbs_event_get_sb, 656 .kill_sb = kill_litter_super 657 }; 658 659 static int __init ib_uverbs_init(void) 660 { 661 int ret; 662 663 spin_lock_init(&map_lock); 664 665 ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES, 666 "infiniband_verbs"); 667 if (ret) { 668 printk(KERN_ERR "user_verbs: couldn't register device number\n"); 669 goto out; 670 } 671 672 ret = class_register(&uverbs_class); 673 if (ret) { 674 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n"); 675 goto out_chrdev; 676 } 677 678 ret = class_create_file(&uverbs_class, &class_attr_abi_version); 679 if (ret) { 680 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n"); 681 goto out_class; 682 } 683 684 ret = register_filesystem(&uverbs_event_fs); 685 if (ret) { 686 printk(KERN_ERR "user_verbs: couldn't register infinibandeventfs\n"); 687 goto out_class; 688 } 689 690 uverbs_event_mnt = kern_mount(&uverbs_event_fs); 691 if (IS_ERR(uverbs_event_mnt)) { 692 ret = PTR_ERR(uverbs_event_mnt); 693 printk(KERN_ERR "user_verbs: couldn't mount infinibandeventfs\n"); 694 goto out_fs; 695 } 696 697 ret = ib_register_client(&uverbs_client); 698 if (ret) { 699 printk(KERN_ERR "user_verbs: couldn't register client\n"); 700 goto out_mnt; 701 } 702 703 return 0; 704 705 out_mnt: 706 mntput(uverbs_event_mnt); 707 708 out_fs: 709 unregister_filesystem(&uverbs_event_fs); 710 711 out_class: 712 class_unregister(&uverbs_class); 713 714 out_chrdev: 715 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); 716 717 out: 718 return ret; 719 } 720 721 static void __exit ib_uverbs_cleanup(void) 722 { 723 ib_unregister_client(&uverbs_client); 724 mntput(uverbs_event_mnt); 725 unregister_filesystem(&uverbs_event_fs); 726 class_unregister(&uverbs_class); 727 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES); 728 } 729 730 module_init(ib_uverbs_init); 731 module_exit(ib_uverbs_cleanup); 732