1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved. 4 * Copyright (c) 2005 PathScale, Inc. All rights reserved. 5 * Copyright (c) 2006 Mellanox Technologies. 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 36 #include <linux/file.h> 37 #include <linux/fs.h> 38 #include <linux/slab.h> 39 40 #include <asm/uaccess.h> 41 42 #include "uverbs.h" 43 44 struct uverbs_lock_class { 45 struct lock_class_key key; 46 char name[16]; 47 }; 48 49 static struct uverbs_lock_class pd_lock_class = { .name = "PD-uobj" }; 50 static struct uverbs_lock_class mr_lock_class = { .name = "MR-uobj" }; 51 static struct uverbs_lock_class mw_lock_class = { .name = "MW-uobj" }; 52 static struct uverbs_lock_class cq_lock_class = { .name = "CQ-uobj" }; 53 static struct uverbs_lock_class qp_lock_class = { .name = "QP-uobj" }; 54 static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" }; 55 static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" }; 56 static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" }; 57 58 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ 59 do { \ 60 (udata)->inbuf = (void __user *) (ibuf); \ 61 (udata)->outbuf = (void __user *) (obuf); \ 62 (udata)->inlen = (ilen); \ 63 (udata)->outlen = (olen); \ 64 } while (0) 65 66 /* 67 * The ib_uobject locking scheme is as follows: 68 * 69 * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it 70 * needs to be held during all idr operations. When an object is 71 * looked up, a reference must be taken on the object's kref before 72 * dropping this lock. 73 * 74 * - Each object also has an rwsem. This rwsem must be held for 75 * reading while an operation that uses the object is performed. 76 * For example, while registering an MR, the associated PD's 77 * uobject.mutex must be held for reading. The rwsem must be held 78 * for writing while initializing or destroying an object. 79 * 80 * - In addition, each object has a "live" flag. If this flag is not 81 * set, then lookups of the object will fail even if it is found in 82 * the idr. This handles a reader that blocks and does not acquire 83 * the rwsem until after the object is destroyed. The destroy 84 * operation will set the live flag to 0 and then drop the rwsem; 85 * this will allow the reader to acquire the rwsem, see that the 86 * live flag is 0, and then drop the rwsem and its reference to 87 * object. The underlying storage will not be freed until the last 88 * reference to the object is dropped. 89 */ 90 91 static void init_uobj(struct ib_uobject *uobj, u64 user_handle, 92 struct ib_ucontext *context, struct uverbs_lock_class *c) 93 { 94 uobj->user_handle = user_handle; 95 uobj->context = context; 96 kref_init(&uobj->ref); 97 init_rwsem(&uobj->mutex); 98 lockdep_set_class_and_name(&uobj->mutex, &c->key, c->name); 99 uobj->live = 0; 100 } 101 102 static void release_uobj(struct kref *kref) 103 { 104 kfree(container_of(kref, struct ib_uobject, ref)); 105 } 106 107 static void put_uobj(struct ib_uobject *uobj) 108 { 109 kref_put(&uobj->ref, release_uobj); 110 } 111 112 static void put_uobj_read(struct ib_uobject *uobj) 113 { 114 up_read(&uobj->mutex); 115 put_uobj(uobj); 116 } 117 118 static void put_uobj_write(struct ib_uobject *uobj) 119 { 120 up_write(&uobj->mutex); 121 put_uobj(uobj); 122 } 123 124 static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj) 125 { 126 int ret; 127 128 idr_preload(GFP_KERNEL); 129 spin_lock(&ib_uverbs_idr_lock); 130 131 ret = idr_alloc(idr, uobj, 0, 0, GFP_NOWAIT); 132 if (ret >= 0) 133 uobj->id = ret; 134 135 spin_unlock(&ib_uverbs_idr_lock); 136 idr_preload_end(); 137 138 return ret < 0 ? ret : 0; 139 } 140 141 void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj) 142 { 143 spin_lock(&ib_uverbs_idr_lock); 144 idr_remove(idr, uobj->id); 145 spin_unlock(&ib_uverbs_idr_lock); 146 } 147 148 static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id, 149 struct ib_ucontext *context) 150 { 151 struct ib_uobject *uobj; 152 153 spin_lock(&ib_uverbs_idr_lock); 154 uobj = idr_find(idr, id); 155 if (uobj) { 156 if (uobj->context == context) 157 kref_get(&uobj->ref); 158 else 159 uobj = NULL; 160 } 161 spin_unlock(&ib_uverbs_idr_lock); 162 163 return uobj; 164 } 165 166 static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, 167 struct ib_ucontext *context, int nested) 168 { 169 struct ib_uobject *uobj; 170 171 uobj = __idr_get_uobj(idr, id, context); 172 if (!uobj) 173 return NULL; 174 175 if (nested) 176 down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING); 177 else 178 down_read(&uobj->mutex); 179 if (!uobj->live) { 180 put_uobj_read(uobj); 181 return NULL; 182 } 183 184 return uobj; 185 } 186 187 static struct ib_uobject *idr_write_uobj(struct idr *idr, int id, 188 struct ib_ucontext *context) 189 { 190 struct ib_uobject *uobj; 191 192 uobj = __idr_get_uobj(idr, id, context); 193 if (!uobj) 194 return NULL; 195 196 down_write(&uobj->mutex); 197 if (!uobj->live) { 198 put_uobj_write(uobj); 199 return NULL; 200 } 201 202 return uobj; 203 } 204 205 static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context, 206 int nested) 207 { 208 struct ib_uobject *uobj; 209 210 uobj = idr_read_uobj(idr, id, context, nested); 211 return uobj ? uobj->object : NULL; 212 } 213 214 static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) 215 { 216 return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0); 217 } 218 219 static void put_pd_read(struct ib_pd *pd) 220 { 221 put_uobj_read(pd->uobject); 222 } 223 224 static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested) 225 { 226 return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested); 227 } 228 229 static void put_cq_read(struct ib_cq *cq) 230 { 231 put_uobj_read(cq->uobject); 232 } 233 234 static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) 235 { 236 return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0); 237 } 238 239 static void put_ah_read(struct ib_ah *ah) 240 { 241 put_uobj_read(ah->uobject); 242 } 243 244 static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) 245 { 246 return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); 247 } 248 249 static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) 250 { 251 struct ib_uobject *uobj; 252 253 uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context); 254 return uobj ? uobj->object : NULL; 255 } 256 257 static void put_qp_read(struct ib_qp *qp) 258 { 259 put_uobj_read(qp->uobject); 260 } 261 262 static void put_qp_write(struct ib_qp *qp) 263 { 264 put_uobj_write(qp->uobject); 265 } 266 267 static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) 268 { 269 return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0); 270 } 271 272 static void put_srq_read(struct ib_srq *srq) 273 { 274 put_uobj_read(srq->uobject); 275 } 276 277 static struct ib_xrcd *idr_read_xrcd(int xrcd_handle, struct ib_ucontext *context, 278 struct ib_uobject **uobj) 279 { 280 *uobj = idr_read_uobj(&ib_uverbs_xrcd_idr, xrcd_handle, context, 0); 281 return *uobj ? (*uobj)->object : NULL; 282 } 283 284 static void put_xrcd_read(struct ib_uobject *uobj) 285 { 286 put_uobj_read(uobj); 287 } 288 289 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, 290 const char __user *buf, 291 int in_len, int out_len) 292 { 293 struct ib_uverbs_get_context cmd; 294 struct ib_uverbs_get_context_resp resp; 295 struct ib_udata udata; 296 struct ib_device *ibdev = file->device->ib_dev; 297 struct ib_ucontext *ucontext; 298 struct file *filp; 299 int ret; 300 301 if (out_len < sizeof resp) 302 return -ENOSPC; 303 304 if (copy_from_user(&cmd, buf, sizeof cmd)) 305 return -EFAULT; 306 307 mutex_lock(&file->mutex); 308 309 if (file->ucontext) { 310 ret = -EINVAL; 311 goto err; 312 } 313 314 INIT_UDATA(&udata, buf + sizeof cmd, 315 (unsigned long) cmd.response + sizeof resp, 316 in_len - sizeof cmd, out_len - sizeof resp); 317 318 ucontext = ibdev->alloc_ucontext(ibdev, &udata); 319 if (IS_ERR(ucontext)) { 320 ret = PTR_ERR(ucontext); 321 goto err; 322 } 323 324 ucontext->device = ibdev; 325 INIT_LIST_HEAD(&ucontext->pd_list); 326 INIT_LIST_HEAD(&ucontext->mr_list); 327 INIT_LIST_HEAD(&ucontext->mw_list); 328 INIT_LIST_HEAD(&ucontext->cq_list); 329 INIT_LIST_HEAD(&ucontext->qp_list); 330 INIT_LIST_HEAD(&ucontext->srq_list); 331 INIT_LIST_HEAD(&ucontext->ah_list); 332 INIT_LIST_HEAD(&ucontext->xrcd_list); 333 ucontext->closing = 0; 334 335 resp.num_comp_vectors = file->device->num_comp_vectors; 336 337 ret = get_unused_fd(); 338 if (ret < 0) 339 goto err_free; 340 resp.async_fd = ret; 341 342 filp = ib_uverbs_alloc_event_file(file, 1); 343 if (IS_ERR(filp)) { 344 ret = PTR_ERR(filp); 345 goto err_fd; 346 } 347 348 if (copy_to_user((void __user *) (unsigned long) cmd.response, 349 &resp, sizeof resp)) { 350 ret = -EFAULT; 351 goto err_file; 352 } 353 354 file->async_file = filp->private_data; 355 356 INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev, 357 ib_uverbs_event_handler); 358 ret = ib_register_event_handler(&file->event_handler); 359 if (ret) 360 goto err_file; 361 362 kref_get(&file->async_file->ref); 363 kref_get(&file->ref); 364 file->ucontext = ucontext; 365 366 fd_install(resp.async_fd, filp); 367 368 mutex_unlock(&file->mutex); 369 370 return in_len; 371 372 err_file: 373 fput(filp); 374 375 err_fd: 376 put_unused_fd(resp.async_fd); 377 378 err_free: 379 ibdev->dealloc_ucontext(ucontext); 380 381 err: 382 mutex_unlock(&file->mutex); 383 return ret; 384 } 385 386 ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, 387 const char __user *buf, 388 int in_len, int out_len) 389 { 390 struct ib_uverbs_query_device cmd; 391 struct ib_uverbs_query_device_resp resp; 392 struct ib_device_attr attr; 393 int ret; 394 395 if (out_len < sizeof resp) 396 return -ENOSPC; 397 398 if (copy_from_user(&cmd, buf, sizeof cmd)) 399 return -EFAULT; 400 401 ret = ib_query_device(file->device->ib_dev, &attr); 402 if (ret) 403 return ret; 404 405 memset(&resp, 0, sizeof resp); 406 407 resp.fw_ver = attr.fw_ver; 408 resp.node_guid = file->device->ib_dev->node_guid; 409 resp.sys_image_guid = attr.sys_image_guid; 410 resp.max_mr_size = attr.max_mr_size; 411 resp.page_size_cap = attr.page_size_cap; 412 resp.vendor_id = attr.vendor_id; 413 resp.vendor_part_id = attr.vendor_part_id; 414 resp.hw_ver = attr.hw_ver; 415 resp.max_qp = attr.max_qp; 416 resp.max_qp_wr = attr.max_qp_wr; 417 resp.device_cap_flags = attr.device_cap_flags; 418 resp.max_sge = attr.max_sge; 419 resp.max_sge_rd = attr.max_sge_rd; 420 resp.max_cq = attr.max_cq; 421 resp.max_cqe = attr.max_cqe; 422 resp.max_mr = attr.max_mr; 423 resp.max_pd = attr.max_pd; 424 resp.max_qp_rd_atom = attr.max_qp_rd_atom; 425 resp.max_ee_rd_atom = attr.max_ee_rd_atom; 426 resp.max_res_rd_atom = attr.max_res_rd_atom; 427 resp.max_qp_init_rd_atom = attr.max_qp_init_rd_atom; 428 resp.max_ee_init_rd_atom = attr.max_ee_init_rd_atom; 429 resp.atomic_cap = attr.atomic_cap; 430 resp.max_ee = attr.max_ee; 431 resp.max_rdd = attr.max_rdd; 432 resp.max_mw = attr.max_mw; 433 resp.max_raw_ipv6_qp = attr.max_raw_ipv6_qp; 434 resp.max_raw_ethy_qp = attr.max_raw_ethy_qp; 435 resp.max_mcast_grp = attr.max_mcast_grp; 436 resp.max_mcast_qp_attach = attr.max_mcast_qp_attach; 437 resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach; 438 resp.max_ah = attr.max_ah; 439 resp.max_fmr = attr.max_fmr; 440 resp.max_map_per_fmr = attr.max_map_per_fmr; 441 resp.max_srq = attr.max_srq; 442 resp.max_srq_wr = attr.max_srq_wr; 443 resp.max_srq_sge = attr.max_srq_sge; 444 resp.max_pkeys = attr.max_pkeys; 445 resp.local_ca_ack_delay = attr.local_ca_ack_delay; 446 resp.phys_port_cnt = file->device->ib_dev->phys_port_cnt; 447 448 if (copy_to_user((void __user *) (unsigned long) cmd.response, 449 &resp, sizeof resp)) 450 return -EFAULT; 451 452 return in_len; 453 } 454 455 ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file, 456 const char __user *buf, 457 int in_len, int out_len) 458 { 459 struct ib_uverbs_query_port cmd; 460 struct ib_uverbs_query_port_resp resp; 461 struct ib_port_attr attr; 462 int ret; 463 464 if (out_len < sizeof resp) 465 return -ENOSPC; 466 467 if (copy_from_user(&cmd, buf, sizeof cmd)) 468 return -EFAULT; 469 470 ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr); 471 if (ret) 472 return ret; 473 474 memset(&resp, 0, sizeof resp); 475 476 resp.state = attr.state; 477 resp.max_mtu = attr.max_mtu; 478 resp.active_mtu = attr.active_mtu; 479 resp.gid_tbl_len = attr.gid_tbl_len; 480 resp.port_cap_flags = attr.port_cap_flags; 481 resp.max_msg_sz = attr.max_msg_sz; 482 resp.bad_pkey_cntr = attr.bad_pkey_cntr; 483 resp.qkey_viol_cntr = attr.qkey_viol_cntr; 484 resp.pkey_tbl_len = attr.pkey_tbl_len; 485 resp.lid = attr.lid; 486 resp.sm_lid = attr.sm_lid; 487 resp.lmc = attr.lmc; 488 resp.max_vl_num = attr.max_vl_num; 489 resp.sm_sl = attr.sm_sl; 490 resp.subnet_timeout = attr.subnet_timeout; 491 resp.init_type_reply = attr.init_type_reply; 492 resp.active_width = attr.active_width; 493 resp.active_speed = attr.active_speed; 494 resp.phys_state = attr.phys_state; 495 resp.link_layer = rdma_port_get_link_layer(file->device->ib_dev, 496 cmd.port_num); 497 498 if (copy_to_user((void __user *) (unsigned long) cmd.response, 499 &resp, sizeof resp)) 500 return -EFAULT; 501 502 return in_len; 503 } 504 505 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, 506 const char __user *buf, 507 int in_len, int out_len) 508 { 509 struct ib_uverbs_alloc_pd cmd; 510 struct ib_uverbs_alloc_pd_resp resp; 511 struct ib_udata udata; 512 struct ib_uobject *uobj; 513 struct ib_pd *pd; 514 int ret; 515 516 if (out_len < sizeof resp) 517 return -ENOSPC; 518 519 if (copy_from_user(&cmd, buf, sizeof cmd)) 520 return -EFAULT; 521 522 INIT_UDATA(&udata, buf + sizeof cmd, 523 (unsigned long) cmd.response + sizeof resp, 524 in_len - sizeof cmd, out_len - sizeof resp); 525 526 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 527 if (!uobj) 528 return -ENOMEM; 529 530 init_uobj(uobj, 0, file->ucontext, &pd_lock_class); 531 down_write(&uobj->mutex); 532 533 pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, 534 file->ucontext, &udata); 535 if (IS_ERR(pd)) { 536 ret = PTR_ERR(pd); 537 goto err; 538 } 539 540 pd->device = file->device->ib_dev; 541 pd->uobject = uobj; 542 atomic_set(&pd->usecnt, 0); 543 544 uobj->object = pd; 545 ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj); 546 if (ret) 547 goto err_idr; 548 549 memset(&resp, 0, sizeof resp); 550 resp.pd_handle = uobj->id; 551 552 if (copy_to_user((void __user *) (unsigned long) cmd.response, 553 &resp, sizeof resp)) { 554 ret = -EFAULT; 555 goto err_copy; 556 } 557 558 mutex_lock(&file->mutex); 559 list_add_tail(&uobj->list, &file->ucontext->pd_list); 560 mutex_unlock(&file->mutex); 561 562 uobj->live = 1; 563 564 up_write(&uobj->mutex); 565 566 return in_len; 567 568 err_copy: 569 idr_remove_uobj(&ib_uverbs_pd_idr, uobj); 570 571 err_idr: 572 ib_dealloc_pd(pd); 573 574 err: 575 put_uobj_write(uobj); 576 return ret; 577 } 578 579 ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, 580 const char __user *buf, 581 int in_len, int out_len) 582 { 583 struct ib_uverbs_dealloc_pd cmd; 584 struct ib_uobject *uobj; 585 int ret; 586 587 if (copy_from_user(&cmd, buf, sizeof cmd)) 588 return -EFAULT; 589 590 uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext); 591 if (!uobj) 592 return -EINVAL; 593 594 ret = ib_dealloc_pd(uobj->object); 595 if (!ret) 596 uobj->live = 0; 597 598 put_uobj_write(uobj); 599 600 if (ret) 601 return ret; 602 603 idr_remove_uobj(&ib_uverbs_pd_idr, uobj); 604 605 mutex_lock(&file->mutex); 606 list_del(&uobj->list); 607 mutex_unlock(&file->mutex); 608 609 put_uobj(uobj); 610 611 return in_len; 612 } 613 614 struct xrcd_table_entry { 615 struct rb_node node; 616 struct ib_xrcd *xrcd; 617 struct inode *inode; 618 }; 619 620 static int xrcd_table_insert(struct ib_uverbs_device *dev, 621 struct inode *inode, 622 struct ib_xrcd *xrcd) 623 { 624 struct xrcd_table_entry *entry, *scan; 625 struct rb_node **p = &dev->xrcd_tree.rb_node; 626 struct rb_node *parent = NULL; 627 628 entry = kmalloc(sizeof *entry, GFP_KERNEL); 629 if (!entry) 630 return -ENOMEM; 631 632 entry->xrcd = xrcd; 633 entry->inode = inode; 634 635 while (*p) { 636 parent = *p; 637 scan = rb_entry(parent, struct xrcd_table_entry, node); 638 639 if (inode < scan->inode) { 640 p = &(*p)->rb_left; 641 } else if (inode > scan->inode) { 642 p = &(*p)->rb_right; 643 } else { 644 kfree(entry); 645 return -EEXIST; 646 } 647 } 648 649 rb_link_node(&entry->node, parent, p); 650 rb_insert_color(&entry->node, &dev->xrcd_tree); 651 igrab(inode); 652 return 0; 653 } 654 655 static struct xrcd_table_entry *xrcd_table_search(struct ib_uverbs_device *dev, 656 struct inode *inode) 657 { 658 struct xrcd_table_entry *entry; 659 struct rb_node *p = dev->xrcd_tree.rb_node; 660 661 while (p) { 662 entry = rb_entry(p, struct xrcd_table_entry, node); 663 664 if (inode < entry->inode) 665 p = p->rb_left; 666 else if (inode > entry->inode) 667 p = p->rb_right; 668 else 669 return entry; 670 } 671 672 return NULL; 673 } 674 675 static struct ib_xrcd *find_xrcd(struct ib_uverbs_device *dev, struct inode *inode) 676 { 677 struct xrcd_table_entry *entry; 678 679 entry = xrcd_table_search(dev, inode); 680 if (!entry) 681 return NULL; 682 683 return entry->xrcd; 684 } 685 686 static void xrcd_table_delete(struct ib_uverbs_device *dev, 687 struct inode *inode) 688 { 689 struct xrcd_table_entry *entry; 690 691 entry = xrcd_table_search(dev, inode); 692 if (entry) { 693 iput(inode); 694 rb_erase(&entry->node, &dev->xrcd_tree); 695 kfree(entry); 696 } 697 } 698 699 ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file, 700 const char __user *buf, int in_len, 701 int out_len) 702 { 703 struct ib_uverbs_open_xrcd cmd; 704 struct ib_uverbs_open_xrcd_resp resp; 705 struct ib_udata udata; 706 struct ib_uxrcd_object *obj; 707 struct ib_xrcd *xrcd = NULL; 708 struct fd f = {NULL, 0}; 709 struct inode *inode = NULL; 710 int ret = 0; 711 int new_xrcd = 0; 712 713 if (out_len < sizeof resp) 714 return -ENOSPC; 715 716 if (copy_from_user(&cmd, buf, sizeof cmd)) 717 return -EFAULT; 718 719 INIT_UDATA(&udata, buf + sizeof cmd, 720 (unsigned long) cmd.response + sizeof resp, 721 in_len - sizeof cmd, out_len - sizeof resp); 722 723 mutex_lock(&file->device->xrcd_tree_mutex); 724 725 if (cmd.fd != -1) { 726 /* search for file descriptor */ 727 f = fdget(cmd.fd); 728 if (!f.file) { 729 ret = -EBADF; 730 goto err_tree_mutex_unlock; 731 } 732 733 inode = file_inode(f.file); 734 xrcd = find_xrcd(file->device, inode); 735 if (!xrcd && !(cmd.oflags & O_CREAT)) { 736 /* no file descriptor. Need CREATE flag */ 737 ret = -EAGAIN; 738 goto err_tree_mutex_unlock; 739 } 740 741 if (xrcd && cmd.oflags & O_EXCL) { 742 ret = -EINVAL; 743 goto err_tree_mutex_unlock; 744 } 745 } 746 747 obj = kmalloc(sizeof *obj, GFP_KERNEL); 748 if (!obj) { 749 ret = -ENOMEM; 750 goto err_tree_mutex_unlock; 751 } 752 753 init_uobj(&obj->uobject, 0, file->ucontext, &xrcd_lock_class); 754 755 down_write(&obj->uobject.mutex); 756 757 if (!xrcd) { 758 xrcd = file->device->ib_dev->alloc_xrcd(file->device->ib_dev, 759 file->ucontext, &udata); 760 if (IS_ERR(xrcd)) { 761 ret = PTR_ERR(xrcd); 762 goto err; 763 } 764 765 xrcd->inode = inode; 766 xrcd->device = file->device->ib_dev; 767 atomic_set(&xrcd->usecnt, 0); 768 mutex_init(&xrcd->tgt_qp_mutex); 769 INIT_LIST_HEAD(&xrcd->tgt_qp_list); 770 new_xrcd = 1; 771 } 772 773 atomic_set(&obj->refcnt, 0); 774 obj->uobject.object = xrcd; 775 ret = idr_add_uobj(&ib_uverbs_xrcd_idr, &obj->uobject); 776 if (ret) 777 goto err_idr; 778 779 memset(&resp, 0, sizeof resp); 780 resp.xrcd_handle = obj->uobject.id; 781 782 if (inode) { 783 if (new_xrcd) { 784 /* create new inode/xrcd table entry */ 785 ret = xrcd_table_insert(file->device, inode, xrcd); 786 if (ret) 787 goto err_insert_xrcd; 788 } 789 atomic_inc(&xrcd->usecnt); 790 } 791 792 if (copy_to_user((void __user *) (unsigned long) cmd.response, 793 &resp, sizeof resp)) { 794 ret = -EFAULT; 795 goto err_copy; 796 } 797 798 if (f.file) 799 fdput(f); 800 801 mutex_lock(&file->mutex); 802 list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list); 803 mutex_unlock(&file->mutex); 804 805 obj->uobject.live = 1; 806 up_write(&obj->uobject.mutex); 807 808 mutex_unlock(&file->device->xrcd_tree_mutex); 809 return in_len; 810 811 err_copy: 812 if (inode) { 813 if (new_xrcd) 814 xrcd_table_delete(file->device, inode); 815 atomic_dec(&xrcd->usecnt); 816 } 817 818 err_insert_xrcd: 819 idr_remove_uobj(&ib_uverbs_xrcd_idr, &obj->uobject); 820 821 err_idr: 822 ib_dealloc_xrcd(xrcd); 823 824 err: 825 put_uobj_write(&obj->uobject); 826 827 err_tree_mutex_unlock: 828 if (f.file) 829 fdput(f); 830 831 mutex_unlock(&file->device->xrcd_tree_mutex); 832 833 return ret; 834 } 835 836 ssize_t ib_uverbs_close_xrcd(struct ib_uverbs_file *file, 837 const char __user *buf, int in_len, 838 int out_len) 839 { 840 struct ib_uverbs_close_xrcd cmd; 841 struct ib_uobject *uobj; 842 struct ib_xrcd *xrcd = NULL; 843 struct inode *inode = NULL; 844 struct ib_uxrcd_object *obj; 845 int live; 846 int ret = 0; 847 848 if (copy_from_user(&cmd, buf, sizeof cmd)) 849 return -EFAULT; 850 851 mutex_lock(&file->device->xrcd_tree_mutex); 852 uobj = idr_write_uobj(&ib_uverbs_xrcd_idr, cmd.xrcd_handle, file->ucontext); 853 if (!uobj) { 854 ret = -EINVAL; 855 goto out; 856 } 857 858 xrcd = uobj->object; 859 inode = xrcd->inode; 860 obj = container_of(uobj, struct ib_uxrcd_object, uobject); 861 if (atomic_read(&obj->refcnt)) { 862 put_uobj_write(uobj); 863 ret = -EBUSY; 864 goto out; 865 } 866 867 if (!inode || atomic_dec_and_test(&xrcd->usecnt)) { 868 ret = ib_dealloc_xrcd(uobj->object); 869 if (!ret) 870 uobj->live = 0; 871 } 872 873 live = uobj->live; 874 if (inode && ret) 875 atomic_inc(&xrcd->usecnt); 876 877 put_uobj_write(uobj); 878 879 if (ret) 880 goto out; 881 882 if (inode && !live) 883 xrcd_table_delete(file->device, inode); 884 885 idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj); 886 mutex_lock(&file->mutex); 887 list_del(&uobj->list); 888 mutex_unlock(&file->mutex); 889 890 put_uobj(uobj); 891 ret = in_len; 892 893 out: 894 mutex_unlock(&file->device->xrcd_tree_mutex); 895 return ret; 896 } 897 898 void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, 899 struct ib_xrcd *xrcd) 900 { 901 struct inode *inode; 902 903 inode = xrcd->inode; 904 if (inode && !atomic_dec_and_test(&xrcd->usecnt)) 905 return; 906 907 ib_dealloc_xrcd(xrcd); 908 909 if (inode) 910 xrcd_table_delete(dev, inode); 911 } 912 913 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, 914 const char __user *buf, int in_len, 915 int out_len) 916 { 917 struct ib_uverbs_reg_mr cmd; 918 struct ib_uverbs_reg_mr_resp resp; 919 struct ib_udata udata; 920 struct ib_uobject *uobj; 921 struct ib_pd *pd; 922 struct ib_mr *mr; 923 int ret; 924 925 if (out_len < sizeof resp) 926 return -ENOSPC; 927 928 if (copy_from_user(&cmd, buf, sizeof cmd)) 929 return -EFAULT; 930 931 INIT_UDATA(&udata, buf + sizeof cmd, 932 (unsigned long) cmd.response + sizeof resp, 933 in_len - sizeof cmd, out_len - sizeof resp); 934 935 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) 936 return -EINVAL; 937 938 /* 939 * Local write permission is required if remote write or 940 * remote atomic permission is also requested. 941 */ 942 if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) && 943 !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE)) 944 return -EINVAL; 945 946 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 947 if (!uobj) 948 return -ENOMEM; 949 950 init_uobj(uobj, 0, file->ucontext, &mr_lock_class); 951 down_write(&uobj->mutex); 952 953 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 954 if (!pd) { 955 ret = -EINVAL; 956 goto err_free; 957 } 958 959 mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va, 960 cmd.access_flags, &udata); 961 if (IS_ERR(mr)) { 962 ret = PTR_ERR(mr); 963 goto err_put; 964 } 965 966 mr->device = pd->device; 967 mr->pd = pd; 968 mr->uobject = uobj; 969 atomic_inc(&pd->usecnt); 970 atomic_set(&mr->usecnt, 0); 971 972 uobj->object = mr; 973 ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj); 974 if (ret) 975 goto err_unreg; 976 977 memset(&resp, 0, sizeof resp); 978 resp.lkey = mr->lkey; 979 resp.rkey = mr->rkey; 980 resp.mr_handle = uobj->id; 981 982 if (copy_to_user((void __user *) (unsigned long) cmd.response, 983 &resp, sizeof resp)) { 984 ret = -EFAULT; 985 goto err_copy; 986 } 987 988 put_pd_read(pd); 989 990 mutex_lock(&file->mutex); 991 list_add_tail(&uobj->list, &file->ucontext->mr_list); 992 mutex_unlock(&file->mutex); 993 994 uobj->live = 1; 995 996 up_write(&uobj->mutex); 997 998 return in_len; 999 1000 err_copy: 1001 idr_remove_uobj(&ib_uverbs_mr_idr, uobj); 1002 1003 err_unreg: 1004 ib_dereg_mr(mr); 1005 1006 err_put: 1007 put_pd_read(pd); 1008 1009 err_free: 1010 put_uobj_write(uobj); 1011 return ret; 1012 } 1013 1014 ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, 1015 const char __user *buf, int in_len, 1016 int out_len) 1017 { 1018 struct ib_uverbs_dereg_mr cmd; 1019 struct ib_mr *mr; 1020 struct ib_uobject *uobj; 1021 int ret = -EINVAL; 1022 1023 if (copy_from_user(&cmd, buf, sizeof cmd)) 1024 return -EFAULT; 1025 1026 uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext); 1027 if (!uobj) 1028 return -EINVAL; 1029 1030 mr = uobj->object; 1031 1032 ret = ib_dereg_mr(mr); 1033 if (!ret) 1034 uobj->live = 0; 1035 1036 put_uobj_write(uobj); 1037 1038 if (ret) 1039 return ret; 1040 1041 idr_remove_uobj(&ib_uverbs_mr_idr, uobj); 1042 1043 mutex_lock(&file->mutex); 1044 list_del(&uobj->list); 1045 mutex_unlock(&file->mutex); 1046 1047 put_uobj(uobj); 1048 1049 return in_len; 1050 } 1051 1052 ssize_t ib_uverbs_alloc_mw(struct ib_uverbs_file *file, 1053 const char __user *buf, int in_len, 1054 int out_len) 1055 { 1056 struct ib_uverbs_alloc_mw cmd; 1057 struct ib_uverbs_alloc_mw_resp resp; 1058 struct ib_uobject *uobj; 1059 struct ib_pd *pd; 1060 struct ib_mw *mw; 1061 int ret; 1062 1063 if (out_len < sizeof(resp)) 1064 return -ENOSPC; 1065 1066 if (copy_from_user(&cmd, buf, sizeof(cmd))) 1067 return -EFAULT; 1068 1069 uobj = kmalloc(sizeof(*uobj), GFP_KERNEL); 1070 if (!uobj) 1071 return -ENOMEM; 1072 1073 init_uobj(uobj, 0, file->ucontext, &mw_lock_class); 1074 down_write(&uobj->mutex); 1075 1076 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1077 if (!pd) { 1078 ret = -EINVAL; 1079 goto err_free; 1080 } 1081 1082 mw = pd->device->alloc_mw(pd, cmd.mw_type); 1083 if (IS_ERR(mw)) { 1084 ret = PTR_ERR(mw); 1085 goto err_put; 1086 } 1087 1088 mw->device = pd->device; 1089 mw->pd = pd; 1090 mw->uobject = uobj; 1091 atomic_inc(&pd->usecnt); 1092 1093 uobj->object = mw; 1094 ret = idr_add_uobj(&ib_uverbs_mw_idr, uobj); 1095 if (ret) 1096 goto err_unalloc; 1097 1098 memset(&resp, 0, sizeof(resp)); 1099 resp.rkey = mw->rkey; 1100 resp.mw_handle = uobj->id; 1101 1102 if (copy_to_user((void __user *)(unsigned long)cmd.response, 1103 &resp, sizeof(resp))) { 1104 ret = -EFAULT; 1105 goto err_copy; 1106 } 1107 1108 put_pd_read(pd); 1109 1110 mutex_lock(&file->mutex); 1111 list_add_tail(&uobj->list, &file->ucontext->mw_list); 1112 mutex_unlock(&file->mutex); 1113 1114 uobj->live = 1; 1115 1116 up_write(&uobj->mutex); 1117 1118 return in_len; 1119 1120 err_copy: 1121 idr_remove_uobj(&ib_uverbs_mw_idr, uobj); 1122 1123 err_unalloc: 1124 ib_dealloc_mw(mw); 1125 1126 err_put: 1127 put_pd_read(pd); 1128 1129 err_free: 1130 put_uobj_write(uobj); 1131 return ret; 1132 } 1133 1134 ssize_t ib_uverbs_dealloc_mw(struct ib_uverbs_file *file, 1135 const char __user *buf, int in_len, 1136 int out_len) 1137 { 1138 struct ib_uverbs_dealloc_mw cmd; 1139 struct ib_mw *mw; 1140 struct ib_uobject *uobj; 1141 int ret = -EINVAL; 1142 1143 if (copy_from_user(&cmd, buf, sizeof(cmd))) 1144 return -EFAULT; 1145 1146 uobj = idr_write_uobj(&ib_uverbs_mw_idr, cmd.mw_handle, file->ucontext); 1147 if (!uobj) 1148 return -EINVAL; 1149 1150 mw = uobj->object; 1151 1152 ret = ib_dealloc_mw(mw); 1153 if (!ret) 1154 uobj->live = 0; 1155 1156 put_uobj_write(uobj); 1157 1158 if (ret) 1159 return ret; 1160 1161 idr_remove_uobj(&ib_uverbs_mw_idr, uobj); 1162 1163 mutex_lock(&file->mutex); 1164 list_del(&uobj->list); 1165 mutex_unlock(&file->mutex); 1166 1167 put_uobj(uobj); 1168 1169 return in_len; 1170 } 1171 1172 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, 1173 const char __user *buf, int in_len, 1174 int out_len) 1175 { 1176 struct ib_uverbs_create_comp_channel cmd; 1177 struct ib_uverbs_create_comp_channel_resp resp; 1178 struct file *filp; 1179 int ret; 1180 1181 if (out_len < sizeof resp) 1182 return -ENOSPC; 1183 1184 if (copy_from_user(&cmd, buf, sizeof cmd)) 1185 return -EFAULT; 1186 1187 ret = get_unused_fd(); 1188 if (ret < 0) 1189 return ret; 1190 resp.fd = ret; 1191 1192 filp = ib_uverbs_alloc_event_file(file, 0); 1193 if (IS_ERR(filp)) { 1194 put_unused_fd(resp.fd); 1195 return PTR_ERR(filp); 1196 } 1197 1198 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1199 &resp, sizeof resp)) { 1200 put_unused_fd(resp.fd); 1201 fput(filp); 1202 return -EFAULT; 1203 } 1204 1205 fd_install(resp.fd, filp); 1206 return in_len; 1207 } 1208 1209 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, 1210 const char __user *buf, int in_len, 1211 int out_len) 1212 { 1213 struct ib_uverbs_create_cq cmd; 1214 struct ib_uverbs_create_cq_resp resp; 1215 struct ib_udata udata; 1216 struct ib_ucq_object *obj; 1217 struct ib_uverbs_event_file *ev_file = NULL; 1218 struct ib_cq *cq; 1219 int ret; 1220 1221 if (out_len < sizeof resp) 1222 return -ENOSPC; 1223 1224 if (copy_from_user(&cmd, buf, sizeof cmd)) 1225 return -EFAULT; 1226 1227 INIT_UDATA(&udata, buf + sizeof cmd, 1228 (unsigned long) cmd.response + sizeof resp, 1229 in_len - sizeof cmd, out_len - sizeof resp); 1230 1231 if (cmd.comp_vector >= file->device->num_comp_vectors) 1232 return -EINVAL; 1233 1234 obj = kmalloc(sizeof *obj, GFP_KERNEL); 1235 if (!obj) 1236 return -ENOMEM; 1237 1238 init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_class); 1239 down_write(&obj->uobject.mutex); 1240 1241 if (cmd.comp_channel >= 0) { 1242 ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); 1243 if (!ev_file) { 1244 ret = -EINVAL; 1245 goto err; 1246 } 1247 } 1248 1249 obj->uverbs_file = file; 1250 obj->comp_events_reported = 0; 1251 obj->async_events_reported = 0; 1252 INIT_LIST_HEAD(&obj->comp_list); 1253 INIT_LIST_HEAD(&obj->async_list); 1254 1255 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 1256 cmd.comp_vector, 1257 file->ucontext, &udata); 1258 if (IS_ERR(cq)) { 1259 ret = PTR_ERR(cq); 1260 goto err_file; 1261 } 1262 1263 cq->device = file->device->ib_dev; 1264 cq->uobject = &obj->uobject; 1265 cq->comp_handler = ib_uverbs_comp_handler; 1266 cq->event_handler = ib_uverbs_cq_event_handler; 1267 cq->cq_context = ev_file; 1268 atomic_set(&cq->usecnt, 0); 1269 1270 obj->uobject.object = cq; 1271 ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject); 1272 if (ret) 1273 goto err_free; 1274 1275 memset(&resp, 0, sizeof resp); 1276 resp.cq_handle = obj->uobject.id; 1277 resp.cqe = cq->cqe; 1278 1279 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1280 &resp, sizeof resp)) { 1281 ret = -EFAULT; 1282 goto err_copy; 1283 } 1284 1285 mutex_lock(&file->mutex); 1286 list_add_tail(&obj->uobject.list, &file->ucontext->cq_list); 1287 mutex_unlock(&file->mutex); 1288 1289 obj->uobject.live = 1; 1290 1291 up_write(&obj->uobject.mutex); 1292 1293 return in_len; 1294 1295 err_copy: 1296 idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); 1297 1298 err_free: 1299 ib_destroy_cq(cq); 1300 1301 err_file: 1302 if (ev_file) 1303 ib_uverbs_release_ucq(file, ev_file, obj); 1304 1305 err: 1306 put_uobj_write(&obj->uobject); 1307 return ret; 1308 } 1309 1310 ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, 1311 const char __user *buf, int in_len, 1312 int out_len) 1313 { 1314 struct ib_uverbs_resize_cq cmd; 1315 struct ib_uverbs_resize_cq_resp resp; 1316 struct ib_udata udata; 1317 struct ib_cq *cq; 1318 int ret = -EINVAL; 1319 1320 if (copy_from_user(&cmd, buf, sizeof cmd)) 1321 return -EFAULT; 1322 1323 INIT_UDATA(&udata, buf + sizeof cmd, 1324 (unsigned long) cmd.response + sizeof resp, 1325 in_len - sizeof cmd, out_len - sizeof resp); 1326 1327 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); 1328 if (!cq) 1329 return -EINVAL; 1330 1331 ret = cq->device->resize_cq(cq, cmd.cqe, &udata); 1332 if (ret) 1333 goto out; 1334 1335 resp.cqe = cq->cqe; 1336 1337 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1338 &resp, sizeof resp.cqe)) 1339 ret = -EFAULT; 1340 1341 out: 1342 put_cq_read(cq); 1343 1344 return ret ? ret : in_len; 1345 } 1346 1347 static int copy_wc_to_user(void __user *dest, struct ib_wc *wc) 1348 { 1349 struct ib_uverbs_wc tmp; 1350 1351 tmp.wr_id = wc->wr_id; 1352 tmp.status = wc->status; 1353 tmp.opcode = wc->opcode; 1354 tmp.vendor_err = wc->vendor_err; 1355 tmp.byte_len = wc->byte_len; 1356 tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data; 1357 tmp.qp_num = wc->qp->qp_num; 1358 tmp.src_qp = wc->src_qp; 1359 tmp.wc_flags = wc->wc_flags; 1360 tmp.pkey_index = wc->pkey_index; 1361 tmp.slid = wc->slid; 1362 tmp.sl = wc->sl; 1363 tmp.dlid_path_bits = wc->dlid_path_bits; 1364 tmp.port_num = wc->port_num; 1365 tmp.reserved = 0; 1366 1367 if (copy_to_user(dest, &tmp, sizeof tmp)) 1368 return -EFAULT; 1369 1370 return 0; 1371 } 1372 1373 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, 1374 const char __user *buf, int in_len, 1375 int out_len) 1376 { 1377 struct ib_uverbs_poll_cq cmd; 1378 struct ib_uverbs_poll_cq_resp resp; 1379 u8 __user *header_ptr; 1380 u8 __user *data_ptr; 1381 struct ib_cq *cq; 1382 struct ib_wc wc; 1383 int ret; 1384 1385 if (copy_from_user(&cmd, buf, sizeof cmd)) 1386 return -EFAULT; 1387 1388 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); 1389 if (!cq) 1390 return -EINVAL; 1391 1392 /* we copy a struct ib_uverbs_poll_cq_resp to user space */ 1393 header_ptr = (void __user *)(unsigned long) cmd.response; 1394 data_ptr = header_ptr + sizeof resp; 1395 1396 memset(&resp, 0, sizeof resp); 1397 while (resp.count < cmd.ne) { 1398 ret = ib_poll_cq(cq, 1, &wc); 1399 if (ret < 0) 1400 goto out_put; 1401 if (!ret) 1402 break; 1403 1404 ret = copy_wc_to_user(data_ptr, &wc); 1405 if (ret) 1406 goto out_put; 1407 1408 data_ptr += sizeof(struct ib_uverbs_wc); 1409 ++resp.count; 1410 } 1411 1412 if (copy_to_user(header_ptr, &resp, sizeof resp)) { 1413 ret = -EFAULT; 1414 goto out_put; 1415 } 1416 1417 ret = in_len; 1418 1419 out_put: 1420 put_cq_read(cq); 1421 return ret; 1422 } 1423 1424 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, 1425 const char __user *buf, int in_len, 1426 int out_len) 1427 { 1428 struct ib_uverbs_req_notify_cq cmd; 1429 struct ib_cq *cq; 1430 1431 if (copy_from_user(&cmd, buf, sizeof cmd)) 1432 return -EFAULT; 1433 1434 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); 1435 if (!cq) 1436 return -EINVAL; 1437 1438 ib_req_notify_cq(cq, cmd.solicited_only ? 1439 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 1440 1441 put_cq_read(cq); 1442 1443 return in_len; 1444 } 1445 1446 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, 1447 const char __user *buf, int in_len, 1448 int out_len) 1449 { 1450 struct ib_uverbs_destroy_cq cmd; 1451 struct ib_uverbs_destroy_cq_resp resp; 1452 struct ib_uobject *uobj; 1453 struct ib_cq *cq; 1454 struct ib_ucq_object *obj; 1455 struct ib_uverbs_event_file *ev_file; 1456 int ret = -EINVAL; 1457 1458 if (copy_from_user(&cmd, buf, sizeof cmd)) 1459 return -EFAULT; 1460 1461 uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); 1462 if (!uobj) 1463 return -EINVAL; 1464 cq = uobj->object; 1465 ev_file = cq->cq_context; 1466 obj = container_of(cq->uobject, struct ib_ucq_object, uobject); 1467 1468 ret = ib_destroy_cq(cq); 1469 if (!ret) 1470 uobj->live = 0; 1471 1472 put_uobj_write(uobj); 1473 1474 if (ret) 1475 return ret; 1476 1477 idr_remove_uobj(&ib_uverbs_cq_idr, uobj); 1478 1479 mutex_lock(&file->mutex); 1480 list_del(&uobj->list); 1481 mutex_unlock(&file->mutex); 1482 1483 ib_uverbs_release_ucq(file, ev_file, obj); 1484 1485 memset(&resp, 0, sizeof resp); 1486 resp.comp_events_reported = obj->comp_events_reported; 1487 resp.async_events_reported = obj->async_events_reported; 1488 1489 put_uobj(uobj); 1490 1491 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1492 &resp, sizeof resp)) 1493 return -EFAULT; 1494 1495 return in_len; 1496 } 1497 1498 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, 1499 const char __user *buf, int in_len, 1500 int out_len) 1501 { 1502 struct ib_uverbs_create_qp cmd; 1503 struct ib_uverbs_create_qp_resp resp; 1504 struct ib_udata udata; 1505 struct ib_uqp_object *obj; 1506 struct ib_device *device; 1507 struct ib_pd *pd = NULL; 1508 struct ib_xrcd *xrcd = NULL; 1509 struct ib_uobject *uninitialized_var(xrcd_uobj); 1510 struct ib_cq *scq = NULL, *rcq = NULL; 1511 struct ib_srq *srq = NULL; 1512 struct ib_qp *qp; 1513 struct ib_qp_init_attr attr; 1514 int ret; 1515 1516 if (out_len < sizeof resp) 1517 return -ENOSPC; 1518 1519 if (copy_from_user(&cmd, buf, sizeof cmd)) 1520 return -EFAULT; 1521 1522 if (cmd.qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW)) 1523 return -EPERM; 1524 1525 INIT_UDATA(&udata, buf + sizeof cmd, 1526 (unsigned long) cmd.response + sizeof resp, 1527 in_len - sizeof cmd, out_len - sizeof resp); 1528 1529 obj = kmalloc(sizeof *obj, GFP_KERNEL); 1530 if (!obj) 1531 return -ENOMEM; 1532 1533 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class); 1534 down_write(&obj->uevent.uobject.mutex); 1535 1536 if (cmd.qp_type == IB_QPT_XRC_TGT) { 1537 xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj); 1538 if (!xrcd) { 1539 ret = -EINVAL; 1540 goto err_put; 1541 } 1542 device = xrcd->device; 1543 } else { 1544 if (cmd.qp_type == IB_QPT_XRC_INI) { 1545 cmd.max_recv_wr = cmd.max_recv_sge = 0; 1546 } else { 1547 if (cmd.is_srq) { 1548 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 1549 if (!srq || srq->srq_type != IB_SRQT_BASIC) { 1550 ret = -EINVAL; 1551 goto err_put; 1552 } 1553 } 1554 1555 if (cmd.recv_cq_handle != cmd.send_cq_handle) { 1556 rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0); 1557 if (!rcq) { 1558 ret = -EINVAL; 1559 goto err_put; 1560 } 1561 } 1562 } 1563 1564 scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq); 1565 rcq = rcq ?: scq; 1566 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 1567 if (!pd || !scq) { 1568 ret = -EINVAL; 1569 goto err_put; 1570 } 1571 1572 device = pd->device; 1573 } 1574 1575 attr.event_handler = ib_uverbs_qp_event_handler; 1576 attr.qp_context = file; 1577 attr.send_cq = scq; 1578 attr.recv_cq = rcq; 1579 attr.srq = srq; 1580 attr.xrcd = xrcd; 1581 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 1582 attr.qp_type = cmd.qp_type; 1583 attr.create_flags = 0; 1584 1585 attr.cap.max_send_wr = cmd.max_send_wr; 1586 attr.cap.max_recv_wr = cmd.max_recv_wr; 1587 attr.cap.max_send_sge = cmd.max_send_sge; 1588 attr.cap.max_recv_sge = cmd.max_recv_sge; 1589 attr.cap.max_inline_data = cmd.max_inline_data; 1590 1591 obj->uevent.events_reported = 0; 1592 INIT_LIST_HEAD(&obj->uevent.event_list); 1593 INIT_LIST_HEAD(&obj->mcast_list); 1594 1595 if (cmd.qp_type == IB_QPT_XRC_TGT) 1596 qp = ib_create_qp(pd, &attr); 1597 else 1598 qp = device->create_qp(pd, &attr, &udata); 1599 1600 if (IS_ERR(qp)) { 1601 ret = PTR_ERR(qp); 1602 goto err_put; 1603 } 1604 1605 if (cmd.qp_type != IB_QPT_XRC_TGT) { 1606 qp->real_qp = qp; 1607 qp->device = device; 1608 qp->pd = pd; 1609 qp->send_cq = attr.send_cq; 1610 qp->recv_cq = attr.recv_cq; 1611 qp->srq = attr.srq; 1612 qp->event_handler = attr.event_handler; 1613 qp->qp_context = attr.qp_context; 1614 qp->qp_type = attr.qp_type; 1615 atomic_set(&qp->usecnt, 0); 1616 atomic_inc(&pd->usecnt); 1617 atomic_inc(&attr.send_cq->usecnt); 1618 if (attr.recv_cq) 1619 atomic_inc(&attr.recv_cq->usecnt); 1620 if (attr.srq) 1621 atomic_inc(&attr.srq->usecnt); 1622 } 1623 qp->uobject = &obj->uevent.uobject; 1624 1625 obj->uevent.uobject.object = qp; 1626 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1627 if (ret) 1628 goto err_destroy; 1629 1630 memset(&resp, 0, sizeof resp); 1631 resp.qpn = qp->qp_num; 1632 resp.qp_handle = obj->uevent.uobject.id; 1633 resp.max_recv_sge = attr.cap.max_recv_sge; 1634 resp.max_send_sge = attr.cap.max_send_sge; 1635 resp.max_recv_wr = attr.cap.max_recv_wr; 1636 resp.max_send_wr = attr.cap.max_send_wr; 1637 resp.max_inline_data = attr.cap.max_inline_data; 1638 1639 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1640 &resp, sizeof resp)) { 1641 ret = -EFAULT; 1642 goto err_copy; 1643 } 1644 1645 if (xrcd) 1646 put_xrcd_read(xrcd_uobj); 1647 if (pd) 1648 put_pd_read(pd); 1649 if (scq) 1650 put_cq_read(scq); 1651 if (rcq && rcq != scq) 1652 put_cq_read(rcq); 1653 if (srq) 1654 put_srq_read(srq); 1655 1656 mutex_lock(&file->mutex); 1657 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list); 1658 mutex_unlock(&file->mutex); 1659 1660 obj->uevent.uobject.live = 1; 1661 1662 up_write(&obj->uevent.uobject.mutex); 1663 1664 return in_len; 1665 1666 err_copy: 1667 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1668 1669 err_destroy: 1670 ib_destroy_qp(qp); 1671 1672 err_put: 1673 if (xrcd) 1674 put_xrcd_read(xrcd_uobj); 1675 if (pd) 1676 put_pd_read(pd); 1677 if (scq) 1678 put_cq_read(scq); 1679 if (rcq && rcq != scq) 1680 put_cq_read(rcq); 1681 if (srq) 1682 put_srq_read(srq); 1683 1684 put_uobj_write(&obj->uevent.uobject); 1685 return ret; 1686 } 1687 1688 ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file, 1689 const char __user *buf, int in_len, int out_len) 1690 { 1691 struct ib_uverbs_open_qp cmd; 1692 struct ib_uverbs_create_qp_resp resp; 1693 struct ib_udata udata; 1694 struct ib_uqp_object *obj; 1695 struct ib_xrcd *xrcd; 1696 struct ib_uobject *uninitialized_var(xrcd_uobj); 1697 struct ib_qp *qp; 1698 struct ib_qp_open_attr attr; 1699 int ret; 1700 1701 if (out_len < sizeof resp) 1702 return -ENOSPC; 1703 1704 if (copy_from_user(&cmd, buf, sizeof cmd)) 1705 return -EFAULT; 1706 1707 INIT_UDATA(&udata, buf + sizeof cmd, 1708 (unsigned long) cmd.response + sizeof resp, 1709 in_len - sizeof cmd, out_len - sizeof resp); 1710 1711 obj = kmalloc(sizeof *obj, GFP_KERNEL); 1712 if (!obj) 1713 return -ENOMEM; 1714 1715 init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_class); 1716 down_write(&obj->uevent.uobject.mutex); 1717 1718 xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj); 1719 if (!xrcd) { 1720 ret = -EINVAL; 1721 goto err_put; 1722 } 1723 1724 attr.event_handler = ib_uverbs_qp_event_handler; 1725 attr.qp_context = file; 1726 attr.qp_num = cmd.qpn; 1727 attr.qp_type = cmd.qp_type; 1728 1729 obj->uevent.events_reported = 0; 1730 INIT_LIST_HEAD(&obj->uevent.event_list); 1731 INIT_LIST_HEAD(&obj->mcast_list); 1732 1733 qp = ib_open_qp(xrcd, &attr); 1734 if (IS_ERR(qp)) { 1735 ret = PTR_ERR(qp); 1736 goto err_put; 1737 } 1738 1739 qp->uobject = &obj->uevent.uobject; 1740 1741 obj->uevent.uobject.object = qp; 1742 ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1743 if (ret) 1744 goto err_destroy; 1745 1746 memset(&resp, 0, sizeof resp); 1747 resp.qpn = qp->qp_num; 1748 resp.qp_handle = obj->uevent.uobject.id; 1749 1750 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1751 &resp, sizeof resp)) { 1752 ret = -EFAULT; 1753 goto err_remove; 1754 } 1755 1756 put_xrcd_read(xrcd_uobj); 1757 1758 mutex_lock(&file->mutex); 1759 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list); 1760 mutex_unlock(&file->mutex); 1761 1762 obj->uevent.uobject.live = 1; 1763 1764 up_write(&obj->uevent.uobject.mutex); 1765 1766 return in_len; 1767 1768 err_remove: 1769 idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject); 1770 1771 err_destroy: 1772 ib_destroy_qp(qp); 1773 1774 err_put: 1775 put_xrcd_read(xrcd_uobj); 1776 put_uobj_write(&obj->uevent.uobject); 1777 return ret; 1778 } 1779 1780 ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, 1781 const char __user *buf, int in_len, 1782 int out_len) 1783 { 1784 struct ib_uverbs_query_qp cmd; 1785 struct ib_uverbs_query_qp_resp resp; 1786 struct ib_qp *qp; 1787 struct ib_qp_attr *attr; 1788 struct ib_qp_init_attr *init_attr; 1789 int ret; 1790 1791 if (copy_from_user(&cmd, buf, sizeof cmd)) 1792 return -EFAULT; 1793 1794 attr = kmalloc(sizeof *attr, GFP_KERNEL); 1795 init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL); 1796 if (!attr || !init_attr) { 1797 ret = -ENOMEM; 1798 goto out; 1799 } 1800 1801 qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1802 if (!qp) { 1803 ret = -EINVAL; 1804 goto out; 1805 } 1806 1807 ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr); 1808 1809 put_qp_read(qp); 1810 1811 if (ret) 1812 goto out; 1813 1814 memset(&resp, 0, sizeof resp); 1815 1816 resp.qp_state = attr->qp_state; 1817 resp.cur_qp_state = attr->cur_qp_state; 1818 resp.path_mtu = attr->path_mtu; 1819 resp.path_mig_state = attr->path_mig_state; 1820 resp.qkey = attr->qkey; 1821 resp.rq_psn = attr->rq_psn; 1822 resp.sq_psn = attr->sq_psn; 1823 resp.dest_qp_num = attr->dest_qp_num; 1824 resp.qp_access_flags = attr->qp_access_flags; 1825 resp.pkey_index = attr->pkey_index; 1826 resp.alt_pkey_index = attr->alt_pkey_index; 1827 resp.sq_draining = attr->sq_draining; 1828 resp.max_rd_atomic = attr->max_rd_atomic; 1829 resp.max_dest_rd_atomic = attr->max_dest_rd_atomic; 1830 resp.min_rnr_timer = attr->min_rnr_timer; 1831 resp.port_num = attr->port_num; 1832 resp.timeout = attr->timeout; 1833 resp.retry_cnt = attr->retry_cnt; 1834 resp.rnr_retry = attr->rnr_retry; 1835 resp.alt_port_num = attr->alt_port_num; 1836 resp.alt_timeout = attr->alt_timeout; 1837 1838 memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16); 1839 resp.dest.flow_label = attr->ah_attr.grh.flow_label; 1840 resp.dest.sgid_index = attr->ah_attr.grh.sgid_index; 1841 resp.dest.hop_limit = attr->ah_attr.grh.hop_limit; 1842 resp.dest.traffic_class = attr->ah_attr.grh.traffic_class; 1843 resp.dest.dlid = attr->ah_attr.dlid; 1844 resp.dest.sl = attr->ah_attr.sl; 1845 resp.dest.src_path_bits = attr->ah_attr.src_path_bits; 1846 resp.dest.static_rate = attr->ah_attr.static_rate; 1847 resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH); 1848 resp.dest.port_num = attr->ah_attr.port_num; 1849 1850 memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16); 1851 resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label; 1852 resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index; 1853 resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit; 1854 resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class; 1855 resp.alt_dest.dlid = attr->alt_ah_attr.dlid; 1856 resp.alt_dest.sl = attr->alt_ah_attr.sl; 1857 resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits; 1858 resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate; 1859 resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH); 1860 resp.alt_dest.port_num = attr->alt_ah_attr.port_num; 1861 1862 resp.max_send_wr = init_attr->cap.max_send_wr; 1863 resp.max_recv_wr = init_attr->cap.max_recv_wr; 1864 resp.max_send_sge = init_attr->cap.max_send_sge; 1865 resp.max_recv_sge = init_attr->cap.max_recv_sge; 1866 resp.max_inline_data = init_attr->cap.max_inline_data; 1867 resp.sq_sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR; 1868 1869 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1870 &resp, sizeof resp)) 1871 ret = -EFAULT; 1872 1873 out: 1874 kfree(attr); 1875 kfree(init_attr); 1876 1877 return ret ? ret : in_len; 1878 } 1879 1880 /* Remove ignored fields set in the attribute mask */ 1881 static int modify_qp_mask(enum ib_qp_type qp_type, int mask) 1882 { 1883 switch (qp_type) { 1884 case IB_QPT_XRC_INI: 1885 return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER); 1886 case IB_QPT_XRC_TGT: 1887 return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT | 1888 IB_QP_RNR_RETRY); 1889 default: 1890 return mask; 1891 } 1892 } 1893 1894 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, 1895 const char __user *buf, int in_len, 1896 int out_len) 1897 { 1898 struct ib_uverbs_modify_qp cmd; 1899 struct ib_udata udata; 1900 struct ib_qp *qp; 1901 struct ib_qp_attr *attr; 1902 int ret; 1903 1904 if (copy_from_user(&cmd, buf, sizeof cmd)) 1905 return -EFAULT; 1906 1907 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, 1908 out_len); 1909 1910 attr = kmalloc(sizeof *attr, GFP_KERNEL); 1911 if (!attr) 1912 return -ENOMEM; 1913 1914 qp = idr_read_qp(cmd.qp_handle, file->ucontext); 1915 if (!qp) { 1916 ret = -EINVAL; 1917 goto out; 1918 } 1919 1920 attr->qp_state = cmd.qp_state; 1921 attr->cur_qp_state = cmd.cur_qp_state; 1922 attr->path_mtu = cmd.path_mtu; 1923 attr->path_mig_state = cmd.path_mig_state; 1924 attr->qkey = cmd.qkey; 1925 attr->rq_psn = cmd.rq_psn; 1926 attr->sq_psn = cmd.sq_psn; 1927 attr->dest_qp_num = cmd.dest_qp_num; 1928 attr->qp_access_flags = cmd.qp_access_flags; 1929 attr->pkey_index = cmd.pkey_index; 1930 attr->alt_pkey_index = cmd.alt_pkey_index; 1931 attr->en_sqd_async_notify = cmd.en_sqd_async_notify; 1932 attr->max_rd_atomic = cmd.max_rd_atomic; 1933 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; 1934 attr->min_rnr_timer = cmd.min_rnr_timer; 1935 attr->port_num = cmd.port_num; 1936 attr->timeout = cmd.timeout; 1937 attr->retry_cnt = cmd.retry_cnt; 1938 attr->rnr_retry = cmd.rnr_retry; 1939 attr->alt_port_num = cmd.alt_port_num; 1940 attr->alt_timeout = cmd.alt_timeout; 1941 1942 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); 1943 attr->ah_attr.grh.flow_label = cmd.dest.flow_label; 1944 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; 1945 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; 1946 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; 1947 attr->ah_attr.dlid = cmd.dest.dlid; 1948 attr->ah_attr.sl = cmd.dest.sl; 1949 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; 1950 attr->ah_attr.static_rate = cmd.dest.static_rate; 1951 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; 1952 attr->ah_attr.port_num = cmd.dest.port_num; 1953 1954 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); 1955 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; 1956 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; 1957 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; 1958 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; 1959 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; 1960 attr->alt_ah_attr.sl = cmd.alt_dest.sl; 1961 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; 1962 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; 1963 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; 1964 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 1965 1966 if (qp->real_qp == qp) { 1967 ret = qp->device->modify_qp(qp, attr, 1968 modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); 1969 } else { 1970 ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask)); 1971 } 1972 1973 put_qp_read(qp); 1974 1975 if (ret) 1976 goto out; 1977 1978 ret = in_len; 1979 1980 out: 1981 kfree(attr); 1982 1983 return ret; 1984 } 1985 1986 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, 1987 const char __user *buf, int in_len, 1988 int out_len) 1989 { 1990 struct ib_uverbs_destroy_qp cmd; 1991 struct ib_uverbs_destroy_qp_resp resp; 1992 struct ib_uobject *uobj; 1993 struct ib_qp *qp; 1994 struct ib_uqp_object *obj; 1995 int ret = -EINVAL; 1996 1997 if (copy_from_user(&cmd, buf, sizeof cmd)) 1998 return -EFAULT; 1999 2000 memset(&resp, 0, sizeof resp); 2001 2002 uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext); 2003 if (!uobj) 2004 return -EINVAL; 2005 qp = uobj->object; 2006 obj = container_of(uobj, struct ib_uqp_object, uevent.uobject); 2007 2008 if (!list_empty(&obj->mcast_list)) { 2009 put_uobj_write(uobj); 2010 return -EBUSY; 2011 } 2012 2013 ret = ib_destroy_qp(qp); 2014 if (!ret) 2015 uobj->live = 0; 2016 2017 put_uobj_write(uobj); 2018 2019 if (ret) 2020 return ret; 2021 2022 idr_remove_uobj(&ib_uverbs_qp_idr, uobj); 2023 2024 mutex_lock(&file->mutex); 2025 list_del(&uobj->list); 2026 mutex_unlock(&file->mutex); 2027 2028 ib_uverbs_release_uevent(file, &obj->uevent); 2029 2030 resp.events_reported = obj->uevent.events_reported; 2031 2032 put_uobj(uobj); 2033 2034 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2035 &resp, sizeof resp)) 2036 return -EFAULT; 2037 2038 return in_len; 2039 } 2040 2041 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, 2042 const char __user *buf, int in_len, 2043 int out_len) 2044 { 2045 struct ib_uverbs_post_send cmd; 2046 struct ib_uverbs_post_send_resp resp; 2047 struct ib_uverbs_send_wr *user_wr; 2048 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr; 2049 struct ib_qp *qp; 2050 int i, sg_ind; 2051 int is_ud; 2052 ssize_t ret = -EINVAL; 2053 2054 if (copy_from_user(&cmd, buf, sizeof cmd)) 2055 return -EFAULT; 2056 2057 if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count + 2058 cmd.sge_count * sizeof (struct ib_uverbs_sge)) 2059 return -EINVAL; 2060 2061 if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr)) 2062 return -EINVAL; 2063 2064 user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL); 2065 if (!user_wr) 2066 return -ENOMEM; 2067 2068 qp = idr_read_qp(cmd.qp_handle, file->ucontext); 2069 if (!qp) 2070 goto out; 2071 2072 is_ud = qp->qp_type == IB_QPT_UD; 2073 sg_ind = 0; 2074 last = NULL; 2075 for (i = 0; i < cmd.wr_count; ++i) { 2076 if (copy_from_user(user_wr, 2077 buf + sizeof cmd + i * cmd.wqe_size, 2078 cmd.wqe_size)) { 2079 ret = -EFAULT; 2080 goto out_put; 2081 } 2082 2083 if (user_wr->num_sge + sg_ind > cmd.sge_count) { 2084 ret = -EINVAL; 2085 goto out_put; 2086 } 2087 2088 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + 2089 user_wr->num_sge * sizeof (struct ib_sge), 2090 GFP_KERNEL); 2091 if (!next) { 2092 ret = -ENOMEM; 2093 goto out_put; 2094 } 2095 2096 if (!last) 2097 wr = next; 2098 else 2099 last->next = next; 2100 last = next; 2101 2102 next->next = NULL; 2103 next->wr_id = user_wr->wr_id; 2104 next->num_sge = user_wr->num_sge; 2105 next->opcode = user_wr->opcode; 2106 next->send_flags = user_wr->send_flags; 2107 2108 if (is_ud) { 2109 next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah, 2110 file->ucontext); 2111 if (!next->wr.ud.ah) { 2112 ret = -EINVAL; 2113 goto out_put; 2114 } 2115 next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn; 2116 next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey; 2117 } else { 2118 switch (next->opcode) { 2119 case IB_WR_RDMA_WRITE_WITH_IMM: 2120 next->ex.imm_data = 2121 (__be32 __force) user_wr->ex.imm_data; 2122 case IB_WR_RDMA_WRITE: 2123 case IB_WR_RDMA_READ: 2124 next->wr.rdma.remote_addr = 2125 user_wr->wr.rdma.remote_addr; 2126 next->wr.rdma.rkey = 2127 user_wr->wr.rdma.rkey; 2128 break; 2129 case IB_WR_SEND_WITH_IMM: 2130 next->ex.imm_data = 2131 (__be32 __force) user_wr->ex.imm_data; 2132 break; 2133 case IB_WR_SEND_WITH_INV: 2134 next->ex.invalidate_rkey = 2135 user_wr->ex.invalidate_rkey; 2136 break; 2137 case IB_WR_ATOMIC_CMP_AND_SWP: 2138 case IB_WR_ATOMIC_FETCH_AND_ADD: 2139 next->wr.atomic.remote_addr = 2140 user_wr->wr.atomic.remote_addr; 2141 next->wr.atomic.compare_add = 2142 user_wr->wr.atomic.compare_add; 2143 next->wr.atomic.swap = user_wr->wr.atomic.swap; 2144 next->wr.atomic.rkey = user_wr->wr.atomic.rkey; 2145 break; 2146 default: 2147 break; 2148 } 2149 } 2150 2151 if (next->num_sge) { 2152 next->sg_list = (void *) next + 2153 ALIGN(sizeof *next, sizeof (struct ib_sge)); 2154 if (copy_from_user(next->sg_list, 2155 buf + sizeof cmd + 2156 cmd.wr_count * cmd.wqe_size + 2157 sg_ind * sizeof (struct ib_sge), 2158 next->num_sge * sizeof (struct ib_sge))) { 2159 ret = -EFAULT; 2160 goto out_put; 2161 } 2162 sg_ind += next->num_sge; 2163 } else 2164 next->sg_list = NULL; 2165 } 2166 2167 resp.bad_wr = 0; 2168 ret = qp->device->post_send(qp->real_qp, wr, &bad_wr); 2169 if (ret) 2170 for (next = wr; next; next = next->next) { 2171 ++resp.bad_wr; 2172 if (next == bad_wr) 2173 break; 2174 } 2175 2176 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2177 &resp, sizeof resp)) 2178 ret = -EFAULT; 2179 2180 out_put: 2181 put_qp_read(qp); 2182 2183 while (wr) { 2184 if (is_ud && wr->wr.ud.ah) 2185 put_ah_read(wr->wr.ud.ah); 2186 next = wr->next; 2187 kfree(wr); 2188 wr = next; 2189 } 2190 2191 out: 2192 kfree(user_wr); 2193 2194 return ret ? ret : in_len; 2195 } 2196 2197 static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf, 2198 int in_len, 2199 u32 wr_count, 2200 u32 sge_count, 2201 u32 wqe_size) 2202 { 2203 struct ib_uverbs_recv_wr *user_wr; 2204 struct ib_recv_wr *wr = NULL, *last, *next; 2205 int sg_ind; 2206 int i; 2207 int ret; 2208 2209 if (in_len < wqe_size * wr_count + 2210 sge_count * sizeof (struct ib_uverbs_sge)) 2211 return ERR_PTR(-EINVAL); 2212 2213 if (wqe_size < sizeof (struct ib_uverbs_recv_wr)) 2214 return ERR_PTR(-EINVAL); 2215 2216 user_wr = kmalloc(wqe_size, GFP_KERNEL); 2217 if (!user_wr) 2218 return ERR_PTR(-ENOMEM); 2219 2220 sg_ind = 0; 2221 last = NULL; 2222 for (i = 0; i < wr_count; ++i) { 2223 if (copy_from_user(user_wr, buf + i * wqe_size, 2224 wqe_size)) { 2225 ret = -EFAULT; 2226 goto err; 2227 } 2228 2229 if (user_wr->num_sge + sg_ind > sge_count) { 2230 ret = -EINVAL; 2231 goto err; 2232 } 2233 2234 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + 2235 user_wr->num_sge * sizeof (struct ib_sge), 2236 GFP_KERNEL); 2237 if (!next) { 2238 ret = -ENOMEM; 2239 goto err; 2240 } 2241 2242 if (!last) 2243 wr = next; 2244 else 2245 last->next = next; 2246 last = next; 2247 2248 next->next = NULL; 2249 next->wr_id = user_wr->wr_id; 2250 next->num_sge = user_wr->num_sge; 2251 2252 if (next->num_sge) { 2253 next->sg_list = (void *) next + 2254 ALIGN(sizeof *next, sizeof (struct ib_sge)); 2255 if (copy_from_user(next->sg_list, 2256 buf + wr_count * wqe_size + 2257 sg_ind * sizeof (struct ib_sge), 2258 next->num_sge * sizeof (struct ib_sge))) { 2259 ret = -EFAULT; 2260 goto err; 2261 } 2262 sg_ind += next->num_sge; 2263 } else 2264 next->sg_list = NULL; 2265 } 2266 2267 kfree(user_wr); 2268 return wr; 2269 2270 err: 2271 kfree(user_wr); 2272 2273 while (wr) { 2274 next = wr->next; 2275 kfree(wr); 2276 wr = next; 2277 } 2278 2279 return ERR_PTR(ret); 2280 } 2281 2282 ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, 2283 const char __user *buf, int in_len, 2284 int out_len) 2285 { 2286 struct ib_uverbs_post_recv cmd; 2287 struct ib_uverbs_post_recv_resp resp; 2288 struct ib_recv_wr *wr, *next, *bad_wr; 2289 struct ib_qp *qp; 2290 ssize_t ret = -EINVAL; 2291 2292 if (copy_from_user(&cmd, buf, sizeof cmd)) 2293 return -EFAULT; 2294 2295 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, 2296 in_len - sizeof cmd, cmd.wr_count, 2297 cmd.sge_count, cmd.wqe_size); 2298 if (IS_ERR(wr)) 2299 return PTR_ERR(wr); 2300 2301 qp = idr_read_qp(cmd.qp_handle, file->ucontext); 2302 if (!qp) 2303 goto out; 2304 2305 resp.bad_wr = 0; 2306 ret = qp->device->post_recv(qp->real_qp, wr, &bad_wr); 2307 2308 put_qp_read(qp); 2309 2310 if (ret) 2311 for (next = wr; next; next = next->next) { 2312 ++resp.bad_wr; 2313 if (next == bad_wr) 2314 break; 2315 } 2316 2317 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2318 &resp, sizeof resp)) 2319 ret = -EFAULT; 2320 2321 out: 2322 while (wr) { 2323 next = wr->next; 2324 kfree(wr); 2325 wr = next; 2326 } 2327 2328 return ret ? ret : in_len; 2329 } 2330 2331 ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, 2332 const char __user *buf, int in_len, 2333 int out_len) 2334 { 2335 struct ib_uverbs_post_srq_recv cmd; 2336 struct ib_uverbs_post_srq_recv_resp resp; 2337 struct ib_recv_wr *wr, *next, *bad_wr; 2338 struct ib_srq *srq; 2339 ssize_t ret = -EINVAL; 2340 2341 if (copy_from_user(&cmd, buf, sizeof cmd)) 2342 return -EFAULT; 2343 2344 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, 2345 in_len - sizeof cmd, cmd.wr_count, 2346 cmd.sge_count, cmd.wqe_size); 2347 if (IS_ERR(wr)) 2348 return PTR_ERR(wr); 2349 2350 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 2351 if (!srq) 2352 goto out; 2353 2354 resp.bad_wr = 0; 2355 ret = srq->device->post_srq_recv(srq, wr, &bad_wr); 2356 2357 put_srq_read(srq); 2358 2359 if (ret) 2360 for (next = wr; next; next = next->next) { 2361 ++resp.bad_wr; 2362 if (next == bad_wr) 2363 break; 2364 } 2365 2366 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2367 &resp, sizeof resp)) 2368 ret = -EFAULT; 2369 2370 out: 2371 while (wr) { 2372 next = wr->next; 2373 kfree(wr); 2374 wr = next; 2375 } 2376 2377 return ret ? ret : in_len; 2378 } 2379 2380 ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, 2381 const char __user *buf, int in_len, 2382 int out_len) 2383 { 2384 struct ib_uverbs_create_ah cmd; 2385 struct ib_uverbs_create_ah_resp resp; 2386 struct ib_uobject *uobj; 2387 struct ib_pd *pd; 2388 struct ib_ah *ah; 2389 struct ib_ah_attr attr; 2390 int ret; 2391 2392 if (out_len < sizeof resp) 2393 return -ENOSPC; 2394 2395 if (copy_from_user(&cmd, buf, sizeof cmd)) 2396 return -EFAULT; 2397 2398 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 2399 if (!uobj) 2400 return -ENOMEM; 2401 2402 init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_class); 2403 down_write(&uobj->mutex); 2404 2405 pd = idr_read_pd(cmd.pd_handle, file->ucontext); 2406 if (!pd) { 2407 ret = -EINVAL; 2408 goto err; 2409 } 2410 2411 attr.dlid = cmd.attr.dlid; 2412 attr.sl = cmd.attr.sl; 2413 attr.src_path_bits = cmd.attr.src_path_bits; 2414 attr.static_rate = cmd.attr.static_rate; 2415 attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0; 2416 attr.port_num = cmd.attr.port_num; 2417 attr.grh.flow_label = cmd.attr.grh.flow_label; 2418 attr.grh.sgid_index = cmd.attr.grh.sgid_index; 2419 attr.grh.hop_limit = cmd.attr.grh.hop_limit; 2420 attr.grh.traffic_class = cmd.attr.grh.traffic_class; 2421 memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); 2422 2423 ah = ib_create_ah(pd, &attr); 2424 if (IS_ERR(ah)) { 2425 ret = PTR_ERR(ah); 2426 goto err_put; 2427 } 2428 2429 ah->uobject = uobj; 2430 uobj->object = ah; 2431 2432 ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj); 2433 if (ret) 2434 goto err_destroy; 2435 2436 resp.ah_handle = uobj->id; 2437 2438 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2439 &resp, sizeof resp)) { 2440 ret = -EFAULT; 2441 goto err_copy; 2442 } 2443 2444 put_pd_read(pd); 2445 2446 mutex_lock(&file->mutex); 2447 list_add_tail(&uobj->list, &file->ucontext->ah_list); 2448 mutex_unlock(&file->mutex); 2449 2450 uobj->live = 1; 2451 2452 up_write(&uobj->mutex); 2453 2454 return in_len; 2455 2456 err_copy: 2457 idr_remove_uobj(&ib_uverbs_ah_idr, uobj); 2458 2459 err_destroy: 2460 ib_destroy_ah(ah); 2461 2462 err_put: 2463 put_pd_read(pd); 2464 2465 err: 2466 put_uobj_write(uobj); 2467 return ret; 2468 } 2469 2470 ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, 2471 const char __user *buf, int in_len, int out_len) 2472 { 2473 struct ib_uverbs_destroy_ah cmd; 2474 struct ib_ah *ah; 2475 struct ib_uobject *uobj; 2476 int ret; 2477 2478 if (copy_from_user(&cmd, buf, sizeof cmd)) 2479 return -EFAULT; 2480 2481 uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext); 2482 if (!uobj) 2483 return -EINVAL; 2484 ah = uobj->object; 2485 2486 ret = ib_destroy_ah(ah); 2487 if (!ret) 2488 uobj->live = 0; 2489 2490 put_uobj_write(uobj); 2491 2492 if (ret) 2493 return ret; 2494 2495 idr_remove_uobj(&ib_uverbs_ah_idr, uobj); 2496 2497 mutex_lock(&file->mutex); 2498 list_del(&uobj->list); 2499 mutex_unlock(&file->mutex); 2500 2501 put_uobj(uobj); 2502 2503 return in_len; 2504 } 2505 2506 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, 2507 const char __user *buf, int in_len, 2508 int out_len) 2509 { 2510 struct ib_uverbs_attach_mcast cmd; 2511 struct ib_qp *qp; 2512 struct ib_uqp_object *obj; 2513 struct ib_uverbs_mcast_entry *mcast; 2514 int ret; 2515 2516 if (copy_from_user(&cmd, buf, sizeof cmd)) 2517 return -EFAULT; 2518 2519 qp = idr_write_qp(cmd.qp_handle, file->ucontext); 2520 if (!qp) 2521 return -EINVAL; 2522 2523 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 2524 2525 list_for_each_entry(mcast, &obj->mcast_list, list) 2526 if (cmd.mlid == mcast->lid && 2527 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 2528 ret = 0; 2529 goto out_put; 2530 } 2531 2532 mcast = kmalloc(sizeof *mcast, GFP_KERNEL); 2533 if (!mcast) { 2534 ret = -ENOMEM; 2535 goto out_put; 2536 } 2537 2538 mcast->lid = cmd.mlid; 2539 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw); 2540 2541 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid); 2542 if (!ret) 2543 list_add_tail(&mcast->list, &obj->mcast_list); 2544 else 2545 kfree(mcast); 2546 2547 out_put: 2548 put_qp_write(qp); 2549 2550 return ret ? ret : in_len; 2551 } 2552 2553 ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, 2554 const char __user *buf, int in_len, 2555 int out_len) 2556 { 2557 struct ib_uverbs_detach_mcast cmd; 2558 struct ib_uqp_object *obj; 2559 struct ib_qp *qp; 2560 struct ib_uverbs_mcast_entry *mcast; 2561 int ret = -EINVAL; 2562 2563 if (copy_from_user(&cmd, buf, sizeof cmd)) 2564 return -EFAULT; 2565 2566 qp = idr_write_qp(cmd.qp_handle, file->ucontext); 2567 if (!qp) 2568 return -EINVAL; 2569 2570 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 2571 if (ret) 2572 goto out_put; 2573 2574 obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 2575 2576 list_for_each_entry(mcast, &obj->mcast_list, list) 2577 if (cmd.mlid == mcast->lid && 2578 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 2579 list_del(&mcast->list); 2580 kfree(mcast); 2581 break; 2582 } 2583 2584 out_put: 2585 put_qp_write(qp); 2586 2587 return ret ? ret : in_len; 2588 } 2589 2590 static int __uverbs_create_xsrq(struct ib_uverbs_file *file, 2591 struct ib_uverbs_create_xsrq *cmd, 2592 struct ib_udata *udata) 2593 { 2594 struct ib_uverbs_create_srq_resp resp; 2595 struct ib_usrq_object *obj; 2596 struct ib_pd *pd; 2597 struct ib_srq *srq; 2598 struct ib_uobject *uninitialized_var(xrcd_uobj); 2599 struct ib_srq_init_attr attr; 2600 int ret; 2601 2602 obj = kmalloc(sizeof *obj, GFP_KERNEL); 2603 if (!obj) 2604 return -ENOMEM; 2605 2606 init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_class); 2607 down_write(&obj->uevent.uobject.mutex); 2608 2609 if (cmd->srq_type == IB_SRQT_XRC) { 2610 attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj); 2611 if (!attr.ext.xrc.xrcd) { 2612 ret = -EINVAL; 2613 goto err; 2614 } 2615 2616 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject); 2617 atomic_inc(&obj->uxrcd->refcnt); 2618 2619 attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0); 2620 if (!attr.ext.xrc.cq) { 2621 ret = -EINVAL; 2622 goto err_put_xrcd; 2623 } 2624 } 2625 2626 pd = idr_read_pd(cmd->pd_handle, file->ucontext); 2627 if (!pd) { 2628 ret = -EINVAL; 2629 goto err_put_cq; 2630 } 2631 2632 attr.event_handler = ib_uverbs_srq_event_handler; 2633 attr.srq_context = file; 2634 attr.srq_type = cmd->srq_type; 2635 attr.attr.max_wr = cmd->max_wr; 2636 attr.attr.max_sge = cmd->max_sge; 2637 attr.attr.srq_limit = cmd->srq_limit; 2638 2639 obj->uevent.events_reported = 0; 2640 INIT_LIST_HEAD(&obj->uevent.event_list); 2641 2642 srq = pd->device->create_srq(pd, &attr, udata); 2643 if (IS_ERR(srq)) { 2644 ret = PTR_ERR(srq); 2645 goto err_put; 2646 } 2647 2648 srq->device = pd->device; 2649 srq->pd = pd; 2650 srq->srq_type = cmd->srq_type; 2651 srq->uobject = &obj->uevent.uobject; 2652 srq->event_handler = attr.event_handler; 2653 srq->srq_context = attr.srq_context; 2654 2655 if (cmd->srq_type == IB_SRQT_XRC) { 2656 srq->ext.xrc.cq = attr.ext.xrc.cq; 2657 srq->ext.xrc.xrcd = attr.ext.xrc.xrcd; 2658 atomic_inc(&attr.ext.xrc.cq->usecnt); 2659 atomic_inc(&attr.ext.xrc.xrcd->usecnt); 2660 } 2661 2662 atomic_inc(&pd->usecnt); 2663 atomic_set(&srq->usecnt, 0); 2664 2665 obj->uevent.uobject.object = srq; 2666 ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject); 2667 if (ret) 2668 goto err_destroy; 2669 2670 memset(&resp, 0, sizeof resp); 2671 resp.srq_handle = obj->uevent.uobject.id; 2672 resp.max_wr = attr.attr.max_wr; 2673 resp.max_sge = attr.attr.max_sge; 2674 if (cmd->srq_type == IB_SRQT_XRC) 2675 resp.srqn = srq->ext.xrc.srq_num; 2676 2677 if (copy_to_user((void __user *) (unsigned long) cmd->response, 2678 &resp, sizeof resp)) { 2679 ret = -EFAULT; 2680 goto err_copy; 2681 } 2682 2683 if (cmd->srq_type == IB_SRQT_XRC) { 2684 put_uobj_read(xrcd_uobj); 2685 put_cq_read(attr.ext.xrc.cq); 2686 } 2687 put_pd_read(pd); 2688 2689 mutex_lock(&file->mutex); 2690 list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list); 2691 mutex_unlock(&file->mutex); 2692 2693 obj->uevent.uobject.live = 1; 2694 2695 up_write(&obj->uevent.uobject.mutex); 2696 2697 return 0; 2698 2699 err_copy: 2700 idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject); 2701 2702 err_destroy: 2703 ib_destroy_srq(srq); 2704 2705 err_put: 2706 put_pd_read(pd); 2707 2708 err_put_cq: 2709 if (cmd->srq_type == IB_SRQT_XRC) 2710 put_cq_read(attr.ext.xrc.cq); 2711 2712 err_put_xrcd: 2713 if (cmd->srq_type == IB_SRQT_XRC) { 2714 atomic_dec(&obj->uxrcd->refcnt); 2715 put_uobj_read(xrcd_uobj); 2716 } 2717 2718 err: 2719 put_uobj_write(&obj->uevent.uobject); 2720 return ret; 2721 } 2722 2723 ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 2724 const char __user *buf, int in_len, 2725 int out_len) 2726 { 2727 struct ib_uverbs_create_srq cmd; 2728 struct ib_uverbs_create_xsrq xcmd; 2729 struct ib_uverbs_create_srq_resp resp; 2730 struct ib_udata udata; 2731 int ret; 2732 2733 if (out_len < sizeof resp) 2734 return -ENOSPC; 2735 2736 if (copy_from_user(&cmd, buf, sizeof cmd)) 2737 return -EFAULT; 2738 2739 xcmd.response = cmd.response; 2740 xcmd.user_handle = cmd.user_handle; 2741 xcmd.srq_type = IB_SRQT_BASIC; 2742 xcmd.pd_handle = cmd.pd_handle; 2743 xcmd.max_wr = cmd.max_wr; 2744 xcmd.max_sge = cmd.max_sge; 2745 xcmd.srq_limit = cmd.srq_limit; 2746 2747 INIT_UDATA(&udata, buf + sizeof cmd, 2748 (unsigned long) cmd.response + sizeof resp, 2749 in_len - sizeof cmd, out_len - sizeof resp); 2750 2751 ret = __uverbs_create_xsrq(file, &xcmd, &udata); 2752 if (ret) 2753 return ret; 2754 2755 return in_len; 2756 } 2757 2758 ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file, 2759 const char __user *buf, int in_len, int out_len) 2760 { 2761 struct ib_uverbs_create_xsrq cmd; 2762 struct ib_uverbs_create_srq_resp resp; 2763 struct ib_udata udata; 2764 int ret; 2765 2766 if (out_len < sizeof resp) 2767 return -ENOSPC; 2768 2769 if (copy_from_user(&cmd, buf, sizeof cmd)) 2770 return -EFAULT; 2771 2772 INIT_UDATA(&udata, buf + sizeof cmd, 2773 (unsigned long) cmd.response + sizeof resp, 2774 in_len - sizeof cmd, out_len - sizeof resp); 2775 2776 ret = __uverbs_create_xsrq(file, &cmd, &udata); 2777 if (ret) 2778 return ret; 2779 2780 return in_len; 2781 } 2782 2783 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, 2784 const char __user *buf, int in_len, 2785 int out_len) 2786 { 2787 struct ib_uverbs_modify_srq cmd; 2788 struct ib_udata udata; 2789 struct ib_srq *srq; 2790 struct ib_srq_attr attr; 2791 int ret; 2792 2793 if (copy_from_user(&cmd, buf, sizeof cmd)) 2794 return -EFAULT; 2795 2796 INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, 2797 out_len); 2798 2799 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 2800 if (!srq) 2801 return -EINVAL; 2802 2803 attr.max_wr = cmd.max_wr; 2804 attr.srq_limit = cmd.srq_limit; 2805 2806 ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata); 2807 2808 put_srq_read(srq); 2809 2810 return ret ? ret : in_len; 2811 } 2812 2813 ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file, 2814 const char __user *buf, 2815 int in_len, int out_len) 2816 { 2817 struct ib_uverbs_query_srq cmd; 2818 struct ib_uverbs_query_srq_resp resp; 2819 struct ib_srq_attr attr; 2820 struct ib_srq *srq; 2821 int ret; 2822 2823 if (out_len < sizeof resp) 2824 return -ENOSPC; 2825 2826 if (copy_from_user(&cmd, buf, sizeof cmd)) 2827 return -EFAULT; 2828 2829 srq = idr_read_srq(cmd.srq_handle, file->ucontext); 2830 if (!srq) 2831 return -EINVAL; 2832 2833 ret = ib_query_srq(srq, &attr); 2834 2835 put_srq_read(srq); 2836 2837 if (ret) 2838 return ret; 2839 2840 memset(&resp, 0, sizeof resp); 2841 2842 resp.max_wr = attr.max_wr; 2843 resp.max_sge = attr.max_sge; 2844 resp.srq_limit = attr.srq_limit; 2845 2846 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2847 &resp, sizeof resp)) 2848 return -EFAULT; 2849 2850 return in_len; 2851 } 2852 2853 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, 2854 const char __user *buf, int in_len, 2855 int out_len) 2856 { 2857 struct ib_uverbs_destroy_srq cmd; 2858 struct ib_uverbs_destroy_srq_resp resp; 2859 struct ib_uobject *uobj; 2860 struct ib_srq *srq; 2861 struct ib_uevent_object *obj; 2862 int ret = -EINVAL; 2863 2864 if (copy_from_user(&cmd, buf, sizeof cmd)) 2865 return -EFAULT; 2866 2867 uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext); 2868 if (!uobj) 2869 return -EINVAL; 2870 srq = uobj->object; 2871 obj = container_of(uobj, struct ib_uevent_object, uobject); 2872 2873 ret = ib_destroy_srq(srq); 2874 if (!ret) 2875 uobj->live = 0; 2876 2877 put_uobj_write(uobj); 2878 2879 if (ret) 2880 return ret; 2881 2882 idr_remove_uobj(&ib_uverbs_srq_idr, uobj); 2883 2884 mutex_lock(&file->mutex); 2885 list_del(&uobj->list); 2886 mutex_unlock(&file->mutex); 2887 2888 ib_uverbs_release_uevent(file, obj); 2889 2890 memset(&resp, 0, sizeof resp); 2891 resp.events_reported = obj->events_reported; 2892 2893 put_uobj(uobj); 2894 2895 if (copy_to_user((void __user *) (unsigned long) cmd.response, 2896 &resp, sizeof resp)) 2897 ret = -EFAULT; 2898 2899 return ret ? ret : in_len; 2900 } 2901