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_qp *qp; 728 struct ib_qp_init_attr attr; 729 int ret; 730 731 if (out_len < sizeof resp) 732 return -ENOSPC; 733 734 if (copy_from_user(&cmd, buf, sizeof cmd)) 735 return -EFAULT; 736 737 INIT_UDATA(&udata, buf + sizeof cmd, 738 (unsigned long) cmd.response + sizeof resp, 739 in_len - sizeof cmd, out_len - sizeof resp); 740 741 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 742 if (!uobj) 743 return -ENOMEM; 744 745 down(&ib_uverbs_idr_mutex); 746 747 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 748 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 749 rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); 750 751 if (!pd || pd->uobject->context != file->ucontext || 752 !scq || scq->uobject->context != file->ucontext || 753 !rcq || rcq->uobject->context != file->ucontext) { 754 ret = -EINVAL; 755 goto err_up; 756 } 757 758 attr.event_handler = ib_uverbs_qp_event_handler; 759 attr.qp_context = file; 760 attr.send_cq = scq; 761 attr.recv_cq = rcq; 762 attr.srq = NULL; 763 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 764 attr.qp_type = cmd.qp_type; 765 766 attr.cap.max_send_wr = cmd.max_send_wr; 767 attr.cap.max_recv_wr = cmd.max_recv_wr; 768 attr.cap.max_send_sge = cmd.max_send_sge; 769 attr.cap.max_recv_sge = cmd.max_recv_sge; 770 attr.cap.max_inline_data = cmd.max_inline_data; 771 772 uobj->user_handle = cmd.user_handle; 773 uobj->context = file->ucontext; 774 775 qp = pd->device->create_qp(pd, &attr, &udata); 776 if (IS_ERR(qp)) { 777 ret = PTR_ERR(qp); 778 goto err_up; 779 } 780 781 qp->device = pd->device; 782 qp->pd = pd; 783 qp->send_cq = attr.send_cq; 784 qp->recv_cq = attr.recv_cq; 785 qp->srq = attr.srq; 786 qp->uobject = uobj; 787 qp->event_handler = attr.event_handler; 788 qp->qp_context = attr.qp_context; 789 qp->qp_type = attr.qp_type; 790 atomic_inc(&pd->usecnt); 791 atomic_inc(&attr.send_cq->usecnt); 792 atomic_inc(&attr.recv_cq->usecnt); 793 if (attr.srq) 794 atomic_inc(&attr.srq->usecnt); 795 796 memset(&resp, 0, sizeof resp); 797 resp.qpn = qp->qp_num; 798 799 retry: 800 if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) { 801 ret = -ENOMEM; 802 goto err_destroy; 803 } 804 805 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id); 806 807 if (ret == -EAGAIN) 808 goto retry; 809 if (ret) 810 goto err_destroy; 811 812 resp.qp_handle = uobj->id; 813 814 spin_lock_irq(&file->ucontext->lock); 815 list_add_tail(&uobj->list, &file->ucontext->qp_list); 816 spin_unlock_irq(&file->ucontext->lock); 817 818 if (copy_to_user((void __user *) (unsigned long) cmd.response, 819 &resp, sizeof resp)) { 820 ret = -EFAULT; 821 goto err_list; 822 } 823 824 up(&ib_uverbs_idr_mutex); 825 826 return in_len; 827 828 err_list: 829 spin_lock_irq(&file->ucontext->lock); 830 list_del(&uobj->list); 831 spin_unlock_irq(&file->ucontext->lock); 832 833 err_destroy: 834 ib_destroy_qp(qp); 835 836 err_up: 837 up(&ib_uverbs_idr_mutex); 838 839 kfree(uobj); 840 return ret; 841 } 842 843 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, 844 const char __user *buf, int in_len, 845 int out_len) 846 { 847 struct ib_uverbs_modify_qp cmd; 848 struct ib_qp *qp; 849 struct ib_qp_attr *attr; 850 int ret; 851 852 if (copy_from_user(&cmd, buf, sizeof cmd)) 853 return -EFAULT; 854 855 attr = kmalloc(sizeof *attr, GFP_KERNEL); 856 if (!attr) 857 return -ENOMEM; 858 859 down(&ib_uverbs_idr_mutex); 860 861 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 862 if (!qp || qp->uobject->context != file->ucontext) { 863 ret = -EINVAL; 864 goto out; 865 } 866 867 attr->qp_state = cmd.qp_state; 868 attr->cur_qp_state = cmd.cur_qp_state; 869 attr->path_mtu = cmd.path_mtu; 870 attr->path_mig_state = cmd.path_mig_state; 871 attr->qkey = cmd.qkey; 872 attr->rq_psn = cmd.rq_psn; 873 attr->sq_psn = cmd.sq_psn; 874 attr->dest_qp_num = cmd.dest_qp_num; 875 attr->qp_access_flags = cmd.qp_access_flags; 876 attr->pkey_index = cmd.pkey_index; 877 attr->alt_pkey_index = cmd.pkey_index; 878 attr->en_sqd_async_notify = cmd.en_sqd_async_notify; 879 attr->max_rd_atomic = cmd.max_rd_atomic; 880 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; 881 attr->min_rnr_timer = cmd.min_rnr_timer; 882 attr->port_num = cmd.port_num; 883 attr->timeout = cmd.timeout; 884 attr->retry_cnt = cmd.retry_cnt; 885 attr->rnr_retry = cmd.rnr_retry; 886 attr->alt_port_num = cmd.alt_port_num; 887 attr->alt_timeout = cmd.alt_timeout; 888 889 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); 890 attr->ah_attr.grh.flow_label = cmd.dest.flow_label; 891 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; 892 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; 893 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; 894 attr->ah_attr.dlid = cmd.dest.dlid; 895 attr->ah_attr.sl = cmd.dest.sl; 896 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; 897 attr->ah_attr.static_rate = cmd.dest.static_rate; 898 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; 899 attr->ah_attr.port_num = cmd.dest.port_num; 900 901 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); 902 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; 903 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; 904 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; 905 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; 906 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; 907 attr->alt_ah_attr.sl = cmd.alt_dest.sl; 908 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; 909 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; 910 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; 911 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 912 913 ret = ib_modify_qp(qp, attr, cmd.attr_mask); 914 if (ret) 915 goto out; 916 917 ret = in_len; 918 919 out: 920 up(&ib_uverbs_idr_mutex); 921 kfree(attr); 922 923 return ret; 924 } 925 926 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, 927 const char __user *buf, int in_len, 928 int out_len) 929 { 930 struct ib_uverbs_destroy_qp cmd; 931 struct ib_qp *qp; 932 struct ib_uobject *uobj; 933 int ret = -EINVAL; 934 935 if (copy_from_user(&cmd, buf, sizeof cmd)) 936 return -EFAULT; 937 938 down(&ib_uverbs_idr_mutex); 939 940 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 941 if (!qp || qp->uobject->context != file->ucontext) 942 goto out; 943 944 uobj = qp->uobject; 945 946 ret = ib_destroy_qp(qp); 947 if (ret) 948 goto out; 949 950 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 951 952 spin_lock_irq(&file->ucontext->lock); 953 list_del(&uobj->list); 954 spin_unlock_irq(&file->ucontext->lock); 955 956 kfree(uobj); 957 958 out: 959 up(&ib_uverbs_idr_mutex); 960 961 return ret ? ret : in_len; 962 } 963 964 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, 965 const char __user *buf, int in_len, 966 int out_len) 967 { 968 struct ib_uverbs_attach_mcast cmd; 969 struct ib_qp *qp; 970 int ret = -EINVAL; 971 972 if (copy_from_user(&cmd, buf, sizeof cmd)) 973 return -EFAULT; 974 975 down(&ib_uverbs_idr_mutex); 976 977 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 978 if (qp && qp->uobject->context == file->ucontext) 979 ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 980 981 up(&ib_uverbs_idr_mutex); 982 983 return ret ? ret : in_len; 984 } 985 986 ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, 987 const char __user *buf, int in_len, 988 int out_len) 989 { 990 struct ib_uverbs_detach_mcast cmd; 991 struct ib_qp *qp; 992 int ret = -EINVAL; 993 994 if (copy_from_user(&cmd, buf, sizeof cmd)) 995 return -EFAULT; 996 997 down(&ib_uverbs_idr_mutex); 998 999 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1000 if (qp && qp->uobject->context == file->ucontext) 1001 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1002 1003 up(&ib_uverbs_idr_mutex); 1004 1005 return ret ? ret : in_len; 1006 } 1007