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