1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Cisco Systems. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 * 33 * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $ 34 */ 35 36 #include <asm/uaccess.h> 37 38 #include "uverbs.h" 39 40 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ 41 do { \ 42 (udata)->inbuf = (void __user *) (ibuf); \ 43 (udata)->outbuf = (void __user *) (obuf); \ 44 (udata)->inlen = (ilen); \ 45 (udata)->outlen = (olen); \ 46 } while (0) 47 48 ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file, 49 const char __user *buf, 50 int in_len, int out_len) 51 { 52 struct ib_uverbs_query_params cmd; 53 struct ib_uverbs_query_params_resp resp; 54 55 if (out_len < sizeof resp) 56 return -ENOSPC; 57 58 if (copy_from_user(&cmd, buf, sizeof cmd)) 59 return -EFAULT; 60 61 memset(&resp, 0, sizeof resp); 62 63 resp.num_cq_events = file->device->num_comp; 64 65 if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) 66 return -EFAULT; 67 68 return in_len; 69 } 70 71 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, 72 const char __user *buf, 73 int in_len, int out_len) 74 { 75 struct ib_uverbs_get_context cmd; 76 struct ib_uverbs_get_context_resp resp; 77 struct ib_udata udata; 78 struct ib_device *ibdev = file->device->ib_dev; 79 int i; 80 int ret = in_len; 81 82 if (out_len < sizeof resp) 83 return -ENOSPC; 84 85 if (copy_from_user(&cmd, buf, sizeof cmd)) 86 return -EFAULT; 87 88 INIT_UDATA(&udata, buf + sizeof cmd, 89 (unsigned long) cmd.response + sizeof resp, 90 in_len - sizeof cmd, out_len - sizeof resp); 91 92 file->ucontext = ibdev->alloc_ucontext(ibdev, &udata); 93 if (IS_ERR(file->ucontext)) { 94 ret = PTR_ERR(file->ucontext); 95 file->ucontext = NULL; 96 return ret; 97 } 98 99 file->ucontext->device = ibdev; 100 INIT_LIST_HEAD(&file->ucontext->pd_list); 101 INIT_LIST_HEAD(&file->ucontext->mr_list); 102 INIT_LIST_HEAD(&file->ucontext->mw_list); 103 INIT_LIST_HEAD(&file->ucontext->cq_list); 104 INIT_LIST_HEAD(&file->ucontext->qp_list); 105 INIT_LIST_HEAD(&file->ucontext->srq_list); 106 INIT_LIST_HEAD(&file->ucontext->ah_list); 107 spin_lock_init(&file->ucontext->lock); 108 109 resp.async_fd = file->async_file.fd; 110 for (i = 0; i < file->device->num_comp; ++i) 111 if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab + 112 i * sizeof (__u32), 113 &file->comp_file[i].fd, sizeof (__u32))) 114 goto err; 115 116 if (copy_to_user((void __user *) (unsigned long) cmd.response, 117 &resp, sizeof resp)) 118 goto err; 119 120 return in_len; 121 122 err: 123 ibdev->dealloc_ucontext(file->ucontext); 124 file->ucontext = NULL; 125 126 return -EFAULT; 127 } 128 129 ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, 130 const char __user *buf, 131 int in_len, int out_len) 132 { 133 struct ib_uverbs_query_device cmd; 134 struct ib_uverbs_query_device_resp resp; 135 struct ib_device_attr attr; 136 int ret; 137 138 if (out_len < sizeof resp) 139 return -ENOSPC; 140 141 if (copy_from_user(&cmd, buf, sizeof cmd)) 142 return -EFAULT; 143 144 ret = ib_query_device(file->device->ib_dev, &attr); 145 if (ret) 146 return ret; 147 148 memset(&resp, 0, sizeof resp); 149 150 resp.fw_ver = attr.fw_ver; 151 resp.node_guid = attr.node_guid; 152 resp.sys_image_guid = attr.sys_image_guid; 153 resp.max_mr_size = attr.max_mr_size; 154 resp.page_size_cap = attr.page_size_cap; 155 resp.vendor_id = attr.vendor_id; 156 resp.vendor_part_id = attr.vendor_part_id; 157 resp.hw_ver = attr.hw_ver; 158 resp.max_qp = attr.max_qp; 159 resp.max_qp_wr = attr.max_qp_wr; 160 resp.device_cap_flags = attr.device_cap_flags; 161 resp.max_sge = attr.max_sge; 162 resp.max_sge_rd = attr.max_sge_rd; 163 resp.max_cq = attr.max_cq; 164 resp.max_cqe = attr.max_cqe; 165 resp.max_mr = attr.max_mr; 166 resp.max_pd = attr.max_pd; 167 resp.max_qp_rd_atom = attr.max_qp_rd_atom; 168 resp.max_ee_rd_atom = attr.max_ee_rd_atom; 169 resp.max_res_rd_atom = attr.max_res_rd_atom; 170 resp.max_qp_init_rd_atom = attr.max_qp_init_rd_atom; 171 resp.max_ee_init_rd_atom = attr.max_ee_init_rd_atom; 172 resp.atomic_cap = attr.atomic_cap; 173 resp.max_ee = attr.max_ee; 174 resp.max_rdd = attr.max_rdd; 175 resp.max_mw = attr.max_mw; 176 resp.max_raw_ipv6_qp = attr.max_raw_ipv6_qp; 177 resp.max_raw_ethy_qp = attr.max_raw_ethy_qp; 178 resp.max_mcast_grp = attr.max_mcast_grp; 179 resp.max_mcast_qp_attach = attr.max_mcast_qp_attach; 180 resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach; 181 resp.max_ah = attr.max_ah; 182 resp.max_fmr = attr.max_fmr; 183 resp.max_map_per_fmr = attr.max_map_per_fmr; 184 resp.max_srq = attr.max_srq; 185 resp.max_srq_wr = attr.max_srq_wr; 186 resp.max_srq_sge = attr.max_srq_sge; 187 resp.max_pkeys = attr.max_pkeys; 188 resp.local_ca_ack_delay = attr.local_ca_ack_delay; 189 resp.phys_port_cnt = file->device->ib_dev->phys_port_cnt; 190 191 if (copy_to_user((void __user *) (unsigned long) cmd.response, 192 &resp, sizeof resp)) 193 return -EFAULT; 194 195 return in_len; 196 } 197 198 ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file, 199 const char __user *buf, 200 int in_len, int out_len) 201 { 202 struct ib_uverbs_query_port cmd; 203 struct ib_uverbs_query_port_resp resp; 204 struct ib_port_attr attr; 205 int ret; 206 207 if (out_len < sizeof resp) 208 return -ENOSPC; 209 210 if (copy_from_user(&cmd, buf, sizeof cmd)) 211 return -EFAULT; 212 213 ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr); 214 if (ret) 215 return ret; 216 217 memset(&resp, 0, sizeof resp); 218 219 resp.state = attr.state; 220 resp.max_mtu = attr.max_mtu; 221 resp.active_mtu = attr.active_mtu; 222 resp.gid_tbl_len = attr.gid_tbl_len; 223 resp.port_cap_flags = attr.port_cap_flags; 224 resp.max_msg_sz = attr.max_msg_sz; 225 resp.bad_pkey_cntr = attr.bad_pkey_cntr; 226 resp.qkey_viol_cntr = attr.qkey_viol_cntr; 227 resp.pkey_tbl_len = attr.pkey_tbl_len; 228 resp.lid = attr.lid; 229 resp.sm_lid = attr.sm_lid; 230 resp.lmc = attr.lmc; 231 resp.max_vl_num = attr.max_vl_num; 232 resp.sm_sl = attr.sm_sl; 233 resp.subnet_timeout = attr.subnet_timeout; 234 resp.init_type_reply = attr.init_type_reply; 235 resp.active_width = attr.active_width; 236 resp.active_speed = attr.active_speed; 237 resp.phys_state = attr.phys_state; 238 239 if (copy_to_user((void __user *) (unsigned long) cmd.response, 240 &resp, sizeof resp)) 241 return -EFAULT; 242 243 return in_len; 244 } 245 246 ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file, 247 const char __user *buf, 248 int in_len, int out_len) 249 { 250 struct ib_uverbs_query_gid cmd; 251 struct ib_uverbs_query_gid_resp resp; 252 int ret; 253 254 if (out_len < sizeof resp) 255 return -ENOSPC; 256 257 if (copy_from_user(&cmd, buf, sizeof cmd)) 258 return -EFAULT; 259 260 memset(&resp, 0, sizeof resp); 261 262 ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index, 263 (union ib_gid *) resp.gid); 264 if (ret) 265 return ret; 266 267 if (copy_to_user((void __user *) (unsigned long) cmd.response, 268 &resp, sizeof resp)) 269 return -EFAULT; 270 271 return in_len; 272 } 273 274 ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file, 275 const char __user *buf, 276 int in_len, int out_len) 277 { 278 struct ib_uverbs_query_pkey cmd; 279 struct ib_uverbs_query_pkey_resp resp; 280 int ret; 281 282 if (out_len < sizeof resp) 283 return -ENOSPC; 284 285 if (copy_from_user(&cmd, buf, sizeof cmd)) 286 return -EFAULT; 287 288 memset(&resp, 0, sizeof resp); 289 290 ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index, 291 &resp.pkey); 292 if (ret) 293 return ret; 294 295 if (copy_to_user((void __user *) (unsigned long) cmd.response, 296 &resp, sizeof resp)) 297 return -EFAULT; 298 299 return in_len; 300 } 301 302 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, 303 const char __user *buf, 304 int in_len, int out_len) 305 { 306 struct ib_uverbs_alloc_pd cmd; 307 struct ib_uverbs_alloc_pd_resp resp; 308 struct ib_udata udata; 309 struct ib_uobject *uobj; 310 struct ib_pd *pd; 311 int ret; 312 313 if (out_len < sizeof resp) 314 return -ENOSPC; 315 316 if (copy_from_user(&cmd, buf, sizeof cmd)) 317 return -EFAULT; 318 319 INIT_UDATA(&udata, buf + sizeof cmd, 320 (unsigned long) cmd.response + sizeof resp, 321 in_len - sizeof cmd, out_len - sizeof resp); 322 323 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 324 if (!uobj) 325 return -ENOMEM; 326 327 uobj->context = file->ucontext; 328 329 pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, 330 file->ucontext, &udata); 331 if (IS_ERR(pd)) { 332 ret = PTR_ERR(pd); 333 goto err; 334 } 335 336 pd->device = file->device->ib_dev; 337 pd->uobject = uobj; 338 atomic_set(&pd->usecnt, 0); 339 340 retry: 341 if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { 342 ret = -ENOMEM; 343 goto err_pd; 344 } 345 346 down(&ib_uverbs_idr_mutex); 347 ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); 348 up(&ib_uverbs_idr_mutex); 349 350 if (ret == -EAGAIN) 351 goto retry; 352 if (ret) 353 goto err_pd; 354 355 spin_lock_irq(&file->ucontext->lock); 356 list_add_tail(&uobj->list, &file->ucontext->pd_list); 357 spin_unlock_irq(&file->ucontext->lock); 358 359 memset(&resp, 0, sizeof resp); 360 resp.pd_handle = uobj->id; 361 362 if (copy_to_user((void __user *) (unsigned long) cmd.response, 363 &resp, sizeof resp)) { 364 ret = -EFAULT; 365 goto err_list; 366 } 367 368 return in_len; 369 370 err_list: 371 spin_lock_irq(&file->ucontext->lock); 372 list_del(&uobj->list); 373 spin_unlock_irq(&file->ucontext->lock); 374 375 down(&ib_uverbs_idr_mutex); 376 idr_remove(&ib_uverbs_pd_idr, uobj->id); 377 up(&ib_uverbs_idr_mutex); 378 379 err_pd: 380 ib_dealloc_pd(pd); 381 382 err: 383 kfree(uobj); 384 return ret; 385 } 386 387 ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, 388 const char __user *buf, 389 int in_len, int out_len) 390 { 391 struct ib_uverbs_dealloc_pd cmd; 392 struct ib_pd *pd; 393 struct ib_uobject *uobj; 394 int ret = -EINVAL; 395 396 if (copy_from_user(&cmd, buf, sizeof cmd)) 397 return -EFAULT; 398 399 down(&ib_uverbs_idr_mutex); 400 401 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 402 if (!pd || pd->uobject->context != file->ucontext) 403 goto out; 404 405 uobj = pd->uobject; 406 407 ret = ib_dealloc_pd(pd); 408 if (ret) 409 goto out; 410 411 idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); 412 413 spin_lock_irq(&file->ucontext->lock); 414 list_del(&uobj->list); 415 spin_unlock_irq(&file->ucontext->lock); 416 417 kfree(uobj); 418 419 out: 420 up(&ib_uverbs_idr_mutex); 421 422 return ret ? ret : in_len; 423 } 424 425 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, 426 const char __user *buf, int in_len, 427 int out_len) 428 { 429 struct ib_uverbs_reg_mr cmd; 430 struct ib_uverbs_reg_mr_resp resp; 431 struct ib_udata udata; 432 struct ib_umem_object *obj; 433 struct ib_pd *pd; 434 struct ib_mr *mr; 435 int ret; 436 437 if (out_len < sizeof resp) 438 return -ENOSPC; 439 440 if (copy_from_user(&cmd, buf, sizeof cmd)) 441 return -EFAULT; 442 443 INIT_UDATA(&udata, buf + sizeof cmd, 444 (unsigned long) cmd.response + sizeof resp, 445 in_len - sizeof cmd, out_len - sizeof resp); 446 447 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) 448 return -EINVAL; 449 450 obj = kmalloc(sizeof *obj, GFP_KERNEL); 451 if (!obj) 452 return -ENOMEM; 453 454 obj->uobject.context = file->ucontext; 455 456 /* 457 * We ask for writable memory if any access flags other than 458 * "remote read" are set. "Local write" and "remote write" 459 * obviously require write access. "Remote atomic" can do 460 * things like fetch and add, which will modify memory, and 461 * "MW bind" can change permissions by binding a window. 462 */ 463 ret = ib_umem_get(file->device->ib_dev, &obj->umem, 464 (void *) (unsigned long) cmd.start, cmd.length, 465 !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ)); 466 if (ret) 467 goto err_free; 468 469 obj->umem.virt_base = cmd.hca_va; 470 471 down(&ib_uverbs_idr_mutex); 472 473 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 474 if (!pd || pd->uobject->context != file->ucontext) { 475 ret = -EINVAL; 476 goto err_up; 477 } 478 479 if (!pd->device->reg_user_mr) { 480 ret = -ENOSYS; 481 goto err_up; 482 } 483 484 mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); 485 if (IS_ERR(mr)) { 486 ret = PTR_ERR(mr); 487 goto err_up; 488 } 489 490 mr->device = pd->device; 491 mr->pd = pd; 492 mr->uobject = &obj->uobject; 493 atomic_inc(&pd->usecnt); 494 atomic_set(&mr->usecnt, 0); 495 496 memset(&resp, 0, sizeof resp); 497 resp.lkey = mr->lkey; 498 resp.rkey = mr->rkey; 499 500 retry: 501 if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) { 502 ret = -ENOMEM; 503 goto err_unreg; 504 } 505 506 ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id); 507 508 if (ret == -EAGAIN) 509 goto retry; 510 if (ret) 511 goto err_unreg; 512 513 resp.mr_handle = obj->uobject.id; 514 515 spin_lock_irq(&file->ucontext->lock); 516 list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); 517 spin_unlock_irq(&file->ucontext->lock); 518 519 if (copy_to_user((void __user *) (unsigned long) cmd.response, 520 &resp, sizeof resp)) { 521 ret = -EFAULT; 522 goto err_list; 523 } 524 525 up(&ib_uverbs_idr_mutex); 526 527 return in_len; 528 529 err_list: 530 spin_lock_irq(&file->ucontext->lock); 531 list_del(&obj->uobject.list); 532 spin_unlock_irq(&file->ucontext->lock); 533 534 err_unreg: 535 ib_dereg_mr(mr); 536 537 err_up: 538 up(&ib_uverbs_idr_mutex); 539 540 ib_umem_release(file->device->ib_dev, &obj->umem); 541 542 err_free: 543 kfree(obj); 544 return ret; 545 } 546 547 ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, 548 const char __user *buf, int in_len, 549 int out_len) 550 { 551 struct ib_uverbs_dereg_mr cmd; 552 struct ib_mr *mr; 553 struct ib_umem_object *memobj; 554 int ret = -EINVAL; 555 556 if (copy_from_user(&cmd, buf, sizeof cmd)) 557 return -EFAULT; 558 559 down(&ib_uverbs_idr_mutex); 560 561 mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); 562 if (!mr || mr->uobject->context != file->ucontext) 563 goto out; 564 565 memobj = container_of(mr->uobject, struct ib_umem_object, uobject); 566 567 ret = ib_dereg_mr(mr); 568 if (ret) 569 goto out; 570 571 idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); 572 573 spin_lock_irq(&file->ucontext->lock); 574 list_del(&memobj->uobject.list); 575 spin_unlock_irq(&file->ucontext->lock); 576 577 ib_umem_release(file->device->ib_dev, &memobj->umem); 578 kfree(memobj); 579 580 out: 581 up(&ib_uverbs_idr_mutex); 582 583 return ret ? ret : in_len; 584 } 585 586 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, 587 const char __user *buf, int in_len, 588 int out_len) 589 { 590 struct ib_uverbs_create_cq cmd; 591 struct ib_uverbs_create_cq_resp resp; 592 struct ib_udata udata; 593 struct ib_uobject *uobj; 594 struct ib_cq *cq; 595 int ret; 596 597 if (out_len < sizeof resp) 598 return -ENOSPC; 599 600 if (copy_from_user(&cmd, buf, sizeof cmd)) 601 return -EFAULT; 602 603 INIT_UDATA(&udata, buf + sizeof cmd, 604 (unsigned long) cmd.response + sizeof resp, 605 in_len - sizeof cmd, out_len - sizeof resp); 606 607 if (cmd.event_handler >= file->device->num_comp) 608 return -EINVAL; 609 610 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 611 if (!uobj) 612 return -ENOMEM; 613 614 uobj->user_handle = cmd.user_handle; 615 uobj->context = file->ucontext; 616 617 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 618 file->ucontext, &udata); 619 if (IS_ERR(cq)) { 620 ret = PTR_ERR(cq); 621 goto err; 622 } 623 624 cq->device = file->device->ib_dev; 625 cq->uobject = uobj; 626 cq->comp_handler = ib_uverbs_comp_handler; 627 cq->event_handler = ib_uverbs_cq_event_handler; 628 cq->cq_context = file; 629 atomic_set(&cq->usecnt, 0); 630 631 retry: 632 if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { 633 ret = -ENOMEM; 634 goto err_cq; 635 } 636 637 down(&ib_uverbs_idr_mutex); 638 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id); 639 up(&ib_uverbs_idr_mutex); 640 641 if (ret == -EAGAIN) 642 goto retry; 643 if (ret) 644 goto err_cq; 645 646 spin_lock_irq(&file->ucontext->lock); 647 list_add_tail(&uobj->list, &file->ucontext->cq_list); 648 spin_unlock_irq(&file->ucontext->lock); 649 650 memset(&resp, 0, sizeof resp); 651 resp.cq_handle = uobj->id; 652 resp.cqe = cq->cqe; 653 654 if (copy_to_user((void __user *) (unsigned long) cmd.response, 655 &resp, sizeof resp)) { 656 ret = -EFAULT; 657 goto err_list; 658 } 659 660 return in_len; 661 662 err_list: 663 spin_lock_irq(&file->ucontext->lock); 664 list_del(&uobj->list); 665 spin_unlock_irq(&file->ucontext->lock); 666 667 down(&ib_uverbs_idr_mutex); 668 idr_remove(&ib_uverbs_cq_idr, uobj->id); 669 up(&ib_uverbs_idr_mutex); 670 671 err_cq: 672 ib_destroy_cq(cq); 673 674 err: 675 kfree(uobj); 676 return ret; 677 } 678 679 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, 680 const char __user *buf, int in_len, 681 int out_len) 682 { 683 struct ib_uverbs_destroy_cq cmd; 684 struct ib_cq *cq; 685 struct ib_uobject *uobj; 686 int ret = -EINVAL; 687 688 if (copy_from_user(&cmd, buf, sizeof cmd)) 689 return -EFAULT; 690 691 down(&ib_uverbs_idr_mutex); 692 693 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 694 if (!cq || cq->uobject->context != file->ucontext) 695 goto out; 696 697 uobj = cq->uobject; 698 699 ret = ib_destroy_cq(cq); 700 if (ret) 701 goto out; 702 703 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 704 705 spin_lock_irq(&file->ucontext->lock); 706 list_del(&uobj->list); 707 spin_unlock_irq(&file->ucontext->lock); 708 709 kfree(uobj); 710 711 out: 712 up(&ib_uverbs_idr_mutex); 713 714 return ret ? ret : in_len; 715 } 716 717 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, 718 const char __user *buf, int in_len, 719 int out_len) 720 { 721 struct ib_uverbs_create_qp cmd; 722 struct ib_uverbs_create_qp_resp resp; 723 struct ib_udata udata; 724 struct ib_uobject *uobj; 725 struct ib_pd *pd; 726 struct ib_cq *scq, *rcq; 727 struct ib_srq *srq; 728 struct ib_qp *qp; 729 struct ib_qp_init_attr attr; 730 int ret; 731 732 if (out_len < sizeof resp) 733 return -ENOSPC; 734 735 if (copy_from_user(&cmd, buf, sizeof cmd)) 736 return -EFAULT; 737 738 INIT_UDATA(&udata, buf + sizeof cmd, 739 (unsigned long) cmd.response + sizeof resp, 740 in_len - sizeof cmd, out_len - sizeof resp); 741 742 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 743 if (!uobj) 744 return -ENOMEM; 745 746 down(&ib_uverbs_idr_mutex); 747 748 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 749 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 750 rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); 751 srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL; 752 753 if (!pd || pd->uobject->context != file->ucontext || 754 !scq || scq->uobject->context != file->ucontext || 755 !rcq || rcq->uobject->context != file->ucontext || 756 (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) { 757 ret = -EINVAL; 758 goto err_up; 759 } 760 761 attr.event_handler = ib_uverbs_qp_event_handler; 762 attr.qp_context = file; 763 attr.send_cq = scq; 764 attr.recv_cq = rcq; 765 attr.srq = srq; 766 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 767 attr.qp_type = cmd.qp_type; 768 769 attr.cap.max_send_wr = cmd.max_send_wr; 770 attr.cap.max_recv_wr = cmd.max_recv_wr; 771 attr.cap.max_send_sge = cmd.max_send_sge; 772 attr.cap.max_recv_sge = cmd.max_recv_sge; 773 attr.cap.max_inline_data = cmd.max_inline_data; 774 775 uobj->user_handle = cmd.user_handle; 776 uobj->context = file->ucontext; 777 778 qp = pd->device->create_qp(pd, &attr, &udata); 779 if (IS_ERR(qp)) { 780 ret = PTR_ERR(qp); 781 goto err_up; 782 } 783 784 qp->device = pd->device; 785 qp->pd = pd; 786 qp->send_cq = attr.send_cq; 787 qp->recv_cq = attr.recv_cq; 788 qp->srq = attr.srq; 789 qp->uobject = uobj; 790 qp->event_handler = attr.event_handler; 791 qp->qp_context = attr.qp_context; 792 qp->qp_type = attr.qp_type; 793 atomic_inc(&pd->usecnt); 794 atomic_inc(&attr.send_cq->usecnt); 795 atomic_inc(&attr.recv_cq->usecnt); 796 if (attr.srq) 797 atomic_inc(&attr.srq->usecnt); 798 799 memset(&resp, 0, sizeof resp); 800 resp.qpn = qp->qp_num; 801 802 retry: 803 if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) { 804 ret = -ENOMEM; 805 goto err_destroy; 806 } 807 808 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id); 809 810 if (ret == -EAGAIN) 811 goto retry; 812 if (ret) 813 goto err_destroy; 814 815 resp.qp_handle = uobj->id; 816 817 spin_lock_irq(&file->ucontext->lock); 818 list_add_tail(&uobj->list, &file->ucontext->qp_list); 819 spin_unlock_irq(&file->ucontext->lock); 820 821 if (copy_to_user((void __user *) (unsigned long) cmd.response, 822 &resp, sizeof resp)) { 823 ret = -EFAULT; 824 goto err_list; 825 } 826 827 up(&ib_uverbs_idr_mutex); 828 829 return in_len; 830 831 err_list: 832 spin_lock_irq(&file->ucontext->lock); 833 list_del(&uobj->list); 834 spin_unlock_irq(&file->ucontext->lock); 835 836 err_destroy: 837 ib_destroy_qp(qp); 838 839 err_up: 840 up(&ib_uverbs_idr_mutex); 841 842 kfree(uobj); 843 return ret; 844 } 845 846 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, 847 const char __user *buf, int in_len, 848 int out_len) 849 { 850 struct ib_uverbs_modify_qp cmd; 851 struct ib_qp *qp; 852 struct ib_qp_attr *attr; 853 int ret; 854 855 if (copy_from_user(&cmd, buf, sizeof cmd)) 856 return -EFAULT; 857 858 attr = kmalloc(sizeof *attr, GFP_KERNEL); 859 if (!attr) 860 return -ENOMEM; 861 862 down(&ib_uverbs_idr_mutex); 863 864 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 865 if (!qp || qp->uobject->context != file->ucontext) { 866 ret = -EINVAL; 867 goto out; 868 } 869 870 attr->qp_state = cmd.qp_state; 871 attr->cur_qp_state = cmd.cur_qp_state; 872 attr->path_mtu = cmd.path_mtu; 873 attr->path_mig_state = cmd.path_mig_state; 874 attr->qkey = cmd.qkey; 875 attr->rq_psn = cmd.rq_psn; 876 attr->sq_psn = cmd.sq_psn; 877 attr->dest_qp_num = cmd.dest_qp_num; 878 attr->qp_access_flags = cmd.qp_access_flags; 879 attr->pkey_index = cmd.pkey_index; 880 attr->alt_pkey_index = cmd.pkey_index; 881 attr->en_sqd_async_notify = cmd.en_sqd_async_notify; 882 attr->max_rd_atomic = cmd.max_rd_atomic; 883 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; 884 attr->min_rnr_timer = cmd.min_rnr_timer; 885 attr->port_num = cmd.port_num; 886 attr->timeout = cmd.timeout; 887 attr->retry_cnt = cmd.retry_cnt; 888 attr->rnr_retry = cmd.rnr_retry; 889 attr->alt_port_num = cmd.alt_port_num; 890 attr->alt_timeout = cmd.alt_timeout; 891 892 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); 893 attr->ah_attr.grh.flow_label = cmd.dest.flow_label; 894 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; 895 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; 896 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; 897 attr->ah_attr.dlid = cmd.dest.dlid; 898 attr->ah_attr.sl = cmd.dest.sl; 899 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; 900 attr->ah_attr.static_rate = cmd.dest.static_rate; 901 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; 902 attr->ah_attr.port_num = cmd.dest.port_num; 903 904 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); 905 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; 906 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; 907 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; 908 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; 909 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; 910 attr->alt_ah_attr.sl = cmd.alt_dest.sl; 911 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; 912 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; 913 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; 914 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 915 916 ret = ib_modify_qp(qp, attr, cmd.attr_mask); 917 if (ret) 918 goto out; 919 920 ret = in_len; 921 922 out: 923 up(&ib_uverbs_idr_mutex); 924 kfree(attr); 925 926 return ret; 927 } 928 929 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, 930 const char __user *buf, int in_len, 931 int out_len) 932 { 933 struct ib_uverbs_destroy_qp cmd; 934 struct ib_qp *qp; 935 struct ib_uobject *uobj; 936 int ret = -EINVAL; 937 938 if (copy_from_user(&cmd, buf, sizeof cmd)) 939 return -EFAULT; 940 941 down(&ib_uverbs_idr_mutex); 942 943 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 944 if (!qp || qp->uobject->context != file->ucontext) 945 goto out; 946 947 uobj = qp->uobject; 948 949 ret = ib_destroy_qp(qp); 950 if (ret) 951 goto out; 952 953 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 954 955 spin_lock_irq(&file->ucontext->lock); 956 list_del(&uobj->list); 957 spin_unlock_irq(&file->ucontext->lock); 958 959 kfree(uobj); 960 961 out: 962 up(&ib_uverbs_idr_mutex); 963 964 return ret ? ret : in_len; 965 } 966 967 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, 968 const char __user *buf, int in_len, 969 int out_len) 970 { 971 struct ib_uverbs_attach_mcast cmd; 972 struct ib_qp *qp; 973 int ret = -EINVAL; 974 975 if (copy_from_user(&cmd, buf, sizeof cmd)) 976 return -EFAULT; 977 978 down(&ib_uverbs_idr_mutex); 979 980 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 981 if (qp && qp->uobject->context == file->ucontext) 982 ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 983 984 up(&ib_uverbs_idr_mutex); 985 986 return ret ? ret : in_len; 987 } 988 989 ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, 990 const char __user *buf, int in_len, 991 int out_len) 992 { 993 struct ib_uverbs_detach_mcast cmd; 994 struct ib_qp *qp; 995 int ret = -EINVAL; 996 997 if (copy_from_user(&cmd, buf, sizeof cmd)) 998 return -EFAULT; 999 1000 down(&ib_uverbs_idr_mutex); 1001 1002 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1003 if (qp && qp->uobject->context == file->ucontext) 1004 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1005 1006 up(&ib_uverbs_idr_mutex); 1007 1008 return ret ? ret : in_len; 1009 } 1010 1011 ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 1012 const char __user *buf, int in_len, 1013 int out_len) 1014 { 1015 struct ib_uverbs_create_srq cmd; 1016 struct ib_uverbs_create_srq_resp resp; 1017 struct ib_udata udata; 1018 struct ib_uobject *uobj; 1019 struct ib_pd *pd; 1020 struct ib_srq *srq; 1021 struct ib_srq_init_attr attr; 1022 int ret; 1023 1024 if (out_len < sizeof resp) 1025 return -ENOSPC; 1026 1027 if (copy_from_user(&cmd, buf, sizeof cmd)) 1028 return -EFAULT; 1029 1030 INIT_UDATA(&udata, buf + sizeof cmd, 1031 (unsigned long) cmd.response + sizeof resp, 1032 in_len - sizeof cmd, out_len - sizeof resp); 1033 1034 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 1035 if (!uobj) 1036 return -ENOMEM; 1037 1038 down(&ib_uverbs_idr_mutex); 1039 1040 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1041 1042 if (!pd || pd->uobject->context != file->ucontext) { 1043 ret = -EINVAL; 1044 goto err_up; 1045 } 1046 1047 attr.event_handler = ib_uverbs_srq_event_handler; 1048 attr.srq_context = file; 1049 attr.attr.max_wr = cmd.max_wr; 1050 attr.attr.max_sge = cmd.max_sge; 1051 attr.attr.srq_limit = cmd.srq_limit; 1052 1053 uobj->user_handle = cmd.user_handle; 1054 uobj->context = file->ucontext; 1055 1056 srq = pd->device->create_srq(pd, &attr, &udata); 1057 if (IS_ERR(srq)) { 1058 ret = PTR_ERR(srq); 1059 goto err_up; 1060 } 1061 1062 srq->device = pd->device; 1063 srq->pd = pd; 1064 srq->uobject = uobj; 1065 srq->event_handler = attr.event_handler; 1066 srq->srq_context = attr.srq_context; 1067 atomic_inc(&pd->usecnt); 1068 atomic_set(&srq->usecnt, 0); 1069 1070 memset(&resp, 0, sizeof resp); 1071 1072 retry: 1073 if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) { 1074 ret = -ENOMEM; 1075 goto err_destroy; 1076 } 1077 1078 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id); 1079 1080 if (ret == -EAGAIN) 1081 goto retry; 1082 if (ret) 1083 goto err_destroy; 1084 1085 resp.srq_handle = uobj->id; 1086 1087 spin_lock_irq(&file->ucontext->lock); 1088 list_add_tail(&uobj->list, &file->ucontext->srq_list); 1089 spin_unlock_irq(&file->ucontext->lock); 1090 1091 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1092 &resp, sizeof resp)) { 1093 ret = -EFAULT; 1094 goto err_list; 1095 } 1096 1097 up(&ib_uverbs_idr_mutex); 1098 1099 return in_len; 1100 1101 err_list: 1102 spin_lock_irq(&file->ucontext->lock); 1103 list_del(&uobj->list); 1104 spin_unlock_irq(&file->ucontext->lock); 1105 1106 err_destroy: 1107 ib_destroy_srq(srq); 1108 1109 err_up: 1110 up(&ib_uverbs_idr_mutex); 1111 1112 kfree(uobj); 1113 return ret; 1114 } 1115 1116 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, 1117 const char __user *buf, int in_len, 1118 int out_len) 1119 { 1120 struct ib_uverbs_modify_srq cmd; 1121 struct ib_srq *srq; 1122 struct ib_srq_attr attr; 1123 int ret; 1124 1125 if (copy_from_user(&cmd, buf, sizeof cmd)) 1126 return -EFAULT; 1127 1128 down(&ib_uverbs_idr_mutex); 1129 1130 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1131 if (!srq || srq->uobject->context != file->ucontext) { 1132 ret = -EINVAL; 1133 goto out; 1134 } 1135 1136 attr.max_wr = cmd.max_wr; 1137 attr.max_sge = cmd.max_sge; 1138 attr.srq_limit = cmd.srq_limit; 1139 1140 ret = ib_modify_srq(srq, &attr, cmd.attr_mask); 1141 1142 out: 1143 up(&ib_uverbs_idr_mutex); 1144 1145 return ret ? ret : in_len; 1146 } 1147 1148 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, 1149 const char __user *buf, int in_len, 1150 int out_len) 1151 { 1152 struct ib_uverbs_destroy_srq cmd; 1153 struct ib_srq *srq; 1154 struct ib_uobject *uobj; 1155 int ret = -EINVAL; 1156 1157 if (copy_from_user(&cmd, buf, sizeof cmd)) 1158 return -EFAULT; 1159 1160 down(&ib_uverbs_idr_mutex); 1161 1162 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1163 if (!srq || srq->uobject->context != file->ucontext) 1164 goto out; 1165 1166 uobj = srq->uobject; 1167 1168 ret = ib_destroy_srq(srq); 1169 if (ret) 1170 goto out; 1171 1172 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1173 1174 spin_lock_irq(&file->ucontext->lock); 1175 list_del(&uobj->list); 1176 spin_unlock_irq(&file->ucontext->lock); 1177 1178 kfree(uobj); 1179 1180 out: 1181 up(&ib_uverbs_idr_mutex); 1182 1183 return ret ? ret : in_len; 1184 } 1185