1 /* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * Copyright (c) 2005 Cisco Systems. All rights reserved. 4 * Copyright (c) 2005 PathScale, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $ 35 */ 36 37 #include <linux/file.h> 38 #include <linux/fs.h> 39 40 #include <asm/uaccess.h> 41 42 #include "uverbs.h" 43 44 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \ 45 do { \ 46 (udata)->inbuf = (void __user *) (ibuf); \ 47 (udata)->outbuf = (void __user *) (obuf); \ 48 (udata)->inlen = (ilen); \ 49 (udata)->outlen = (olen); \ 50 } while (0) 51 52 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, 53 const char __user *buf, 54 int in_len, int out_len) 55 { 56 struct ib_uverbs_get_context cmd; 57 struct ib_uverbs_get_context_resp resp; 58 struct ib_udata udata; 59 struct ib_device *ibdev = file->device->ib_dev; 60 struct ib_ucontext *ucontext; 61 struct file *filp; 62 int ret; 63 64 if (out_len < sizeof resp) 65 return -ENOSPC; 66 67 if (copy_from_user(&cmd, buf, sizeof cmd)) 68 return -EFAULT; 69 70 down(&file->mutex); 71 72 if (file->ucontext) { 73 ret = -EINVAL; 74 goto err; 75 } 76 77 INIT_UDATA(&udata, buf + sizeof cmd, 78 (unsigned long) cmd.response + sizeof resp, 79 in_len - sizeof cmd, out_len - sizeof resp); 80 81 ucontext = ibdev->alloc_ucontext(ibdev, &udata); 82 if (IS_ERR(ucontext)) 83 return PTR_ERR(file->ucontext); 84 85 ucontext->device = ibdev; 86 INIT_LIST_HEAD(&ucontext->pd_list); 87 INIT_LIST_HEAD(&ucontext->mr_list); 88 INIT_LIST_HEAD(&ucontext->mw_list); 89 INIT_LIST_HEAD(&ucontext->cq_list); 90 INIT_LIST_HEAD(&ucontext->qp_list); 91 INIT_LIST_HEAD(&ucontext->srq_list); 92 INIT_LIST_HEAD(&ucontext->ah_list); 93 94 resp.num_comp_vectors = file->device->num_comp_vectors; 95 96 filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd); 97 if (IS_ERR(filp)) { 98 ret = PTR_ERR(filp); 99 goto err_free; 100 } 101 102 if (copy_to_user((void __user *) (unsigned long) cmd.response, 103 &resp, sizeof resp)) { 104 ret = -EFAULT; 105 goto err_file; 106 } 107 108 file->async_file = filp->private_data; 109 110 INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev, 111 ib_uverbs_event_handler); 112 ret = ib_register_event_handler(&file->event_handler); 113 if (ret) 114 goto err_file; 115 116 kref_get(&file->async_file->ref); 117 kref_get(&file->ref); 118 file->ucontext = ucontext; 119 120 fd_install(resp.async_fd, filp); 121 122 up(&file->mutex); 123 124 return in_len; 125 126 err_file: 127 put_unused_fd(resp.async_fd); 128 fput(filp); 129 130 err_free: 131 ibdev->dealloc_ucontext(ucontext); 132 133 err: 134 up(&file->mutex); 135 return ret; 136 } 137 138 ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, 139 const char __user *buf, 140 int in_len, int out_len) 141 { 142 struct ib_uverbs_query_device cmd; 143 struct ib_uverbs_query_device_resp resp; 144 struct ib_device_attr attr; 145 int ret; 146 147 if (out_len < sizeof resp) 148 return -ENOSPC; 149 150 if (copy_from_user(&cmd, buf, sizeof cmd)) 151 return -EFAULT; 152 153 ret = ib_query_device(file->device->ib_dev, &attr); 154 if (ret) 155 return ret; 156 157 memset(&resp, 0, sizeof resp); 158 159 resp.fw_ver = attr.fw_ver; 160 resp.node_guid = attr.node_guid; 161 resp.sys_image_guid = attr.sys_image_guid; 162 resp.max_mr_size = attr.max_mr_size; 163 resp.page_size_cap = attr.page_size_cap; 164 resp.vendor_id = attr.vendor_id; 165 resp.vendor_part_id = attr.vendor_part_id; 166 resp.hw_ver = attr.hw_ver; 167 resp.max_qp = attr.max_qp; 168 resp.max_qp_wr = attr.max_qp_wr; 169 resp.device_cap_flags = attr.device_cap_flags; 170 resp.max_sge = attr.max_sge; 171 resp.max_sge_rd = attr.max_sge_rd; 172 resp.max_cq = attr.max_cq; 173 resp.max_cqe = attr.max_cqe; 174 resp.max_mr = attr.max_mr; 175 resp.max_pd = attr.max_pd; 176 resp.max_qp_rd_atom = attr.max_qp_rd_atom; 177 resp.max_ee_rd_atom = attr.max_ee_rd_atom; 178 resp.max_res_rd_atom = attr.max_res_rd_atom; 179 resp.max_qp_init_rd_atom = attr.max_qp_init_rd_atom; 180 resp.max_ee_init_rd_atom = attr.max_ee_init_rd_atom; 181 resp.atomic_cap = attr.atomic_cap; 182 resp.max_ee = attr.max_ee; 183 resp.max_rdd = attr.max_rdd; 184 resp.max_mw = attr.max_mw; 185 resp.max_raw_ipv6_qp = attr.max_raw_ipv6_qp; 186 resp.max_raw_ethy_qp = attr.max_raw_ethy_qp; 187 resp.max_mcast_grp = attr.max_mcast_grp; 188 resp.max_mcast_qp_attach = attr.max_mcast_qp_attach; 189 resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach; 190 resp.max_ah = attr.max_ah; 191 resp.max_fmr = attr.max_fmr; 192 resp.max_map_per_fmr = attr.max_map_per_fmr; 193 resp.max_srq = attr.max_srq; 194 resp.max_srq_wr = attr.max_srq_wr; 195 resp.max_srq_sge = attr.max_srq_sge; 196 resp.max_pkeys = attr.max_pkeys; 197 resp.local_ca_ack_delay = attr.local_ca_ack_delay; 198 resp.phys_port_cnt = file->device->ib_dev->phys_port_cnt; 199 200 if (copy_to_user((void __user *) (unsigned long) cmd.response, 201 &resp, sizeof resp)) 202 return -EFAULT; 203 204 return in_len; 205 } 206 207 ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file, 208 const char __user *buf, 209 int in_len, int out_len) 210 { 211 struct ib_uverbs_query_port cmd; 212 struct ib_uverbs_query_port_resp resp; 213 struct ib_port_attr attr; 214 int ret; 215 216 if (out_len < sizeof resp) 217 return -ENOSPC; 218 219 if (copy_from_user(&cmd, buf, sizeof cmd)) 220 return -EFAULT; 221 222 ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr); 223 if (ret) 224 return ret; 225 226 memset(&resp, 0, sizeof resp); 227 228 resp.state = attr.state; 229 resp.max_mtu = attr.max_mtu; 230 resp.active_mtu = attr.active_mtu; 231 resp.gid_tbl_len = attr.gid_tbl_len; 232 resp.port_cap_flags = attr.port_cap_flags; 233 resp.max_msg_sz = attr.max_msg_sz; 234 resp.bad_pkey_cntr = attr.bad_pkey_cntr; 235 resp.qkey_viol_cntr = attr.qkey_viol_cntr; 236 resp.pkey_tbl_len = attr.pkey_tbl_len; 237 resp.lid = attr.lid; 238 resp.sm_lid = attr.sm_lid; 239 resp.lmc = attr.lmc; 240 resp.max_vl_num = attr.max_vl_num; 241 resp.sm_sl = attr.sm_sl; 242 resp.subnet_timeout = attr.subnet_timeout; 243 resp.init_type_reply = attr.init_type_reply; 244 resp.active_width = attr.active_width; 245 resp.active_speed = attr.active_speed; 246 resp.phys_state = attr.phys_state; 247 248 if (copy_to_user((void __user *) (unsigned long) cmd.response, 249 &resp, sizeof resp)) 250 return -EFAULT; 251 252 return in_len; 253 } 254 255 ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, 256 const char __user *buf, 257 int in_len, int out_len) 258 { 259 struct ib_uverbs_alloc_pd cmd; 260 struct ib_uverbs_alloc_pd_resp resp; 261 struct ib_udata udata; 262 struct ib_uobject *uobj; 263 struct ib_pd *pd; 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 INIT_UDATA(&udata, buf + sizeof cmd, 273 (unsigned long) cmd.response + sizeof resp, 274 in_len - sizeof cmd, out_len - sizeof resp); 275 276 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 277 if (!uobj) 278 return -ENOMEM; 279 280 uobj->context = file->ucontext; 281 282 pd = file->device->ib_dev->alloc_pd(file->device->ib_dev, 283 file->ucontext, &udata); 284 if (IS_ERR(pd)) { 285 ret = PTR_ERR(pd); 286 goto err; 287 } 288 289 pd->device = file->device->ib_dev; 290 pd->uobject = uobj; 291 atomic_set(&pd->usecnt, 0); 292 293 down(&ib_uverbs_idr_mutex); 294 295 retry: 296 if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { 297 ret = -ENOMEM; 298 goto err_up; 299 } 300 301 ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id); 302 303 if (ret == -EAGAIN) 304 goto retry; 305 if (ret) 306 goto err_up; 307 308 memset(&resp, 0, sizeof resp); 309 resp.pd_handle = uobj->id; 310 311 if (copy_to_user((void __user *) (unsigned long) cmd.response, 312 &resp, sizeof resp)) { 313 ret = -EFAULT; 314 goto err_idr; 315 } 316 317 down(&file->mutex); 318 list_add_tail(&uobj->list, &file->ucontext->pd_list); 319 up(&file->mutex); 320 321 up(&ib_uverbs_idr_mutex); 322 323 return in_len; 324 325 err_idr: 326 idr_remove(&ib_uverbs_pd_idr, uobj->id); 327 328 err_up: 329 up(&ib_uverbs_idr_mutex); 330 ib_dealloc_pd(pd); 331 332 err: 333 kfree(uobj); 334 return ret; 335 } 336 337 ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, 338 const char __user *buf, 339 int in_len, int out_len) 340 { 341 struct ib_uverbs_dealloc_pd cmd; 342 struct ib_pd *pd; 343 struct ib_uobject *uobj; 344 int ret = -EINVAL; 345 346 if (copy_from_user(&cmd, buf, sizeof cmd)) 347 return -EFAULT; 348 349 down(&ib_uverbs_idr_mutex); 350 351 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 352 if (!pd || pd->uobject->context != file->ucontext) 353 goto out; 354 355 uobj = pd->uobject; 356 357 ret = ib_dealloc_pd(pd); 358 if (ret) 359 goto out; 360 361 idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); 362 363 down(&file->mutex); 364 list_del(&uobj->list); 365 up(&file->mutex); 366 367 kfree(uobj); 368 369 out: 370 up(&ib_uverbs_idr_mutex); 371 372 return ret ? ret : in_len; 373 } 374 375 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, 376 const char __user *buf, int in_len, 377 int out_len) 378 { 379 struct ib_uverbs_reg_mr cmd; 380 struct ib_uverbs_reg_mr_resp resp; 381 struct ib_udata udata; 382 struct ib_umem_object *obj; 383 struct ib_pd *pd; 384 struct ib_mr *mr; 385 int ret; 386 387 if (out_len < sizeof resp) 388 return -ENOSPC; 389 390 if (copy_from_user(&cmd, buf, sizeof cmd)) 391 return -EFAULT; 392 393 INIT_UDATA(&udata, buf + sizeof cmd, 394 (unsigned long) cmd.response + sizeof resp, 395 in_len - sizeof cmd, out_len - sizeof resp); 396 397 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) 398 return -EINVAL; 399 400 /* 401 * Local write permission is required if remote write or 402 * remote atomic permission is also requested. 403 */ 404 if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) && 405 !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE)) 406 return -EINVAL; 407 408 obj = kmalloc(sizeof *obj, GFP_KERNEL); 409 if (!obj) 410 return -ENOMEM; 411 412 obj->uobject.context = file->ucontext; 413 414 /* 415 * We ask for writable memory if any access flags other than 416 * "remote read" are set. "Local write" and "remote write" 417 * obviously require write access. "Remote atomic" can do 418 * things like fetch and add, which will modify memory, and 419 * "MW bind" can change permissions by binding a window. 420 */ 421 ret = ib_umem_get(file->device->ib_dev, &obj->umem, 422 (void *) (unsigned long) cmd.start, cmd.length, 423 !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ)); 424 if (ret) 425 goto err_free; 426 427 obj->umem.virt_base = cmd.hca_va; 428 429 down(&ib_uverbs_idr_mutex); 430 431 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 432 if (!pd || pd->uobject->context != file->ucontext) { 433 ret = -EINVAL; 434 goto err_up; 435 } 436 437 if (!pd->device->reg_user_mr) { 438 ret = -ENOSYS; 439 goto err_up; 440 } 441 442 mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); 443 if (IS_ERR(mr)) { 444 ret = PTR_ERR(mr); 445 goto err_up; 446 } 447 448 mr->device = pd->device; 449 mr->pd = pd; 450 mr->uobject = &obj->uobject; 451 atomic_inc(&pd->usecnt); 452 atomic_set(&mr->usecnt, 0); 453 454 memset(&resp, 0, sizeof resp); 455 resp.lkey = mr->lkey; 456 resp.rkey = mr->rkey; 457 458 retry: 459 if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) { 460 ret = -ENOMEM; 461 goto err_unreg; 462 } 463 464 ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id); 465 466 if (ret == -EAGAIN) 467 goto retry; 468 if (ret) 469 goto err_unreg; 470 471 resp.mr_handle = obj->uobject.id; 472 473 if (copy_to_user((void __user *) (unsigned long) cmd.response, 474 &resp, sizeof resp)) { 475 ret = -EFAULT; 476 goto err_idr; 477 } 478 479 down(&file->mutex); 480 list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); 481 up(&file->mutex); 482 483 up(&ib_uverbs_idr_mutex); 484 485 return in_len; 486 487 err_idr: 488 idr_remove(&ib_uverbs_mr_idr, obj->uobject.id); 489 490 err_unreg: 491 ib_dereg_mr(mr); 492 493 err_up: 494 up(&ib_uverbs_idr_mutex); 495 496 ib_umem_release(file->device->ib_dev, &obj->umem); 497 498 err_free: 499 kfree(obj); 500 return ret; 501 } 502 503 ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, 504 const char __user *buf, int in_len, 505 int out_len) 506 { 507 struct ib_uverbs_dereg_mr cmd; 508 struct ib_mr *mr; 509 struct ib_umem_object *memobj; 510 int ret = -EINVAL; 511 512 if (copy_from_user(&cmd, buf, sizeof cmd)) 513 return -EFAULT; 514 515 down(&ib_uverbs_idr_mutex); 516 517 mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); 518 if (!mr || mr->uobject->context != file->ucontext) 519 goto out; 520 521 memobj = container_of(mr->uobject, struct ib_umem_object, uobject); 522 523 ret = ib_dereg_mr(mr); 524 if (ret) 525 goto out; 526 527 idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); 528 529 down(&file->mutex); 530 list_del(&memobj->uobject.list); 531 up(&file->mutex); 532 533 ib_umem_release(file->device->ib_dev, &memobj->umem); 534 kfree(memobj); 535 536 out: 537 up(&ib_uverbs_idr_mutex); 538 539 return ret ? ret : in_len; 540 } 541 542 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, 543 const char __user *buf, int in_len, 544 int out_len) 545 { 546 struct ib_uverbs_create_comp_channel cmd; 547 struct ib_uverbs_create_comp_channel_resp resp; 548 struct file *filp; 549 550 if (out_len < sizeof resp) 551 return -ENOSPC; 552 553 if (copy_from_user(&cmd, buf, sizeof cmd)) 554 return -EFAULT; 555 556 filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd); 557 if (IS_ERR(filp)) 558 return PTR_ERR(filp); 559 560 if (copy_to_user((void __user *) (unsigned long) cmd.response, 561 &resp, sizeof resp)) { 562 put_unused_fd(resp.fd); 563 fput(filp); 564 return -EFAULT; 565 } 566 567 fd_install(resp.fd, filp); 568 return in_len; 569 } 570 571 ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, 572 const char __user *buf, int in_len, 573 int out_len) 574 { 575 struct ib_uverbs_create_cq cmd; 576 struct ib_uverbs_create_cq_resp resp; 577 struct ib_udata udata; 578 struct ib_ucq_object *uobj; 579 struct ib_uverbs_event_file *ev_file = NULL; 580 struct ib_cq *cq; 581 int ret; 582 583 if (out_len < sizeof resp) 584 return -ENOSPC; 585 586 if (copy_from_user(&cmd, buf, sizeof cmd)) 587 return -EFAULT; 588 589 INIT_UDATA(&udata, buf + sizeof cmd, 590 (unsigned long) cmd.response + sizeof resp, 591 in_len - sizeof cmd, out_len - sizeof resp); 592 593 if (cmd.comp_vector >= file->device->num_comp_vectors) 594 return -EINVAL; 595 596 if (cmd.comp_channel >= 0) 597 ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); 598 599 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 600 if (!uobj) 601 return -ENOMEM; 602 603 uobj->uobject.user_handle = cmd.user_handle; 604 uobj->uobject.context = file->ucontext; 605 uobj->uverbs_file = file; 606 uobj->comp_events_reported = 0; 607 uobj->async_events_reported = 0; 608 INIT_LIST_HEAD(&uobj->comp_list); 609 INIT_LIST_HEAD(&uobj->async_list); 610 611 cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, 612 file->ucontext, &udata); 613 if (IS_ERR(cq)) { 614 ret = PTR_ERR(cq); 615 goto err; 616 } 617 618 cq->device = file->device->ib_dev; 619 cq->uobject = &uobj->uobject; 620 cq->comp_handler = ib_uverbs_comp_handler; 621 cq->event_handler = ib_uverbs_cq_event_handler; 622 cq->cq_context = ev_file; 623 atomic_set(&cq->usecnt, 0); 624 625 down(&ib_uverbs_idr_mutex); 626 627 retry: 628 if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { 629 ret = -ENOMEM; 630 goto err_up; 631 } 632 633 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); 634 635 if (ret == -EAGAIN) 636 goto retry; 637 if (ret) 638 goto err_up; 639 640 memset(&resp, 0, sizeof resp); 641 resp.cq_handle = uobj->uobject.id; 642 resp.cqe = cq->cqe; 643 644 if (copy_to_user((void __user *) (unsigned long) cmd.response, 645 &resp, sizeof resp)) { 646 ret = -EFAULT; 647 goto err_idr; 648 } 649 650 down(&file->mutex); 651 list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); 652 up(&file->mutex); 653 654 up(&ib_uverbs_idr_mutex); 655 656 return in_len; 657 658 err_idr: 659 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); 660 661 err_up: 662 up(&ib_uverbs_idr_mutex); 663 ib_destroy_cq(cq); 664 665 err: 666 kfree(uobj); 667 return ret; 668 } 669 670 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, 671 const char __user *buf, int in_len, 672 int out_len) 673 { 674 struct ib_uverbs_poll_cq cmd; 675 struct ib_uverbs_poll_cq_resp *resp; 676 struct ib_cq *cq; 677 struct ib_wc *wc; 678 int ret = 0; 679 int i; 680 int rsize; 681 682 if (copy_from_user(&cmd, buf, sizeof cmd)) 683 return -EFAULT; 684 685 wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL); 686 if (!wc) 687 return -ENOMEM; 688 689 rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc); 690 resp = kmalloc(rsize, GFP_KERNEL); 691 if (!resp) { 692 ret = -ENOMEM; 693 goto out_wc; 694 } 695 696 down(&ib_uverbs_idr_mutex); 697 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 698 if (!cq || cq->uobject->context != file->ucontext) { 699 ret = -EINVAL; 700 goto out; 701 } 702 703 resp->count = ib_poll_cq(cq, cmd.ne, wc); 704 705 for (i = 0; i < resp->count; i++) { 706 resp->wc[i].wr_id = wc[i].wr_id; 707 resp->wc[i].status = wc[i].status; 708 resp->wc[i].opcode = wc[i].opcode; 709 resp->wc[i].vendor_err = wc[i].vendor_err; 710 resp->wc[i].byte_len = wc[i].byte_len; 711 resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; 712 resp->wc[i].qp_num = wc[i].qp_num; 713 resp->wc[i].src_qp = wc[i].src_qp; 714 resp->wc[i].wc_flags = wc[i].wc_flags; 715 resp->wc[i].pkey_index = wc[i].pkey_index; 716 resp->wc[i].slid = wc[i].slid; 717 resp->wc[i].sl = wc[i].sl; 718 resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits; 719 resp->wc[i].port_num = wc[i].port_num; 720 } 721 722 if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize)) 723 ret = -EFAULT; 724 725 out: 726 up(&ib_uverbs_idr_mutex); 727 kfree(resp); 728 729 out_wc: 730 kfree(wc); 731 return ret ? ret : in_len; 732 } 733 734 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, 735 const char __user *buf, int in_len, 736 int out_len) 737 { 738 struct ib_uverbs_req_notify_cq cmd; 739 struct ib_cq *cq; 740 int ret = -EINVAL; 741 742 if (copy_from_user(&cmd, buf, sizeof cmd)) 743 return -EFAULT; 744 745 down(&ib_uverbs_idr_mutex); 746 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 747 if (cq && cq->uobject->context == file->ucontext) { 748 ib_req_notify_cq(cq, cmd.solicited_only ? 749 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); 750 ret = in_len; 751 } 752 up(&ib_uverbs_idr_mutex); 753 754 return ret; 755 } 756 757 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, 758 const char __user *buf, int in_len, 759 int out_len) 760 { 761 struct ib_uverbs_destroy_cq cmd; 762 struct ib_uverbs_destroy_cq_resp resp; 763 struct ib_cq *cq; 764 struct ib_ucq_object *uobj; 765 struct ib_uverbs_event_file *ev_file; 766 u64 user_handle; 767 int ret = -EINVAL; 768 769 if (copy_from_user(&cmd, buf, sizeof cmd)) 770 return -EFAULT; 771 772 memset(&resp, 0, sizeof resp); 773 774 down(&ib_uverbs_idr_mutex); 775 776 cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); 777 if (!cq || cq->uobject->context != file->ucontext) 778 goto out; 779 780 user_handle = cq->uobject->user_handle; 781 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject); 782 ev_file = cq->cq_context; 783 784 ret = ib_destroy_cq(cq); 785 if (ret) 786 goto out; 787 788 idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); 789 790 down(&file->mutex); 791 list_del(&uobj->uobject.list); 792 up(&file->mutex); 793 794 ib_uverbs_release_ucq(file, ev_file, uobj); 795 796 resp.comp_events_reported = uobj->comp_events_reported; 797 resp.async_events_reported = uobj->async_events_reported; 798 799 kfree(uobj); 800 801 if (copy_to_user((void __user *) (unsigned long) cmd.response, 802 &resp, sizeof resp)) 803 ret = -EFAULT; 804 805 out: 806 up(&ib_uverbs_idr_mutex); 807 808 return ret ? ret : in_len; 809 } 810 811 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, 812 const char __user *buf, int in_len, 813 int out_len) 814 { 815 struct ib_uverbs_create_qp cmd; 816 struct ib_uverbs_create_qp_resp resp; 817 struct ib_udata udata; 818 struct ib_uqp_object *uobj; 819 struct ib_pd *pd; 820 struct ib_cq *scq, *rcq; 821 struct ib_srq *srq; 822 struct ib_qp *qp; 823 struct ib_qp_init_attr attr; 824 int ret; 825 826 if (out_len < sizeof resp) 827 return -ENOSPC; 828 829 if (copy_from_user(&cmd, buf, sizeof cmd)) 830 return -EFAULT; 831 832 INIT_UDATA(&udata, buf + sizeof cmd, 833 (unsigned long) cmd.response + sizeof resp, 834 in_len - sizeof cmd, out_len - sizeof resp); 835 836 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 837 if (!uobj) 838 return -ENOMEM; 839 840 down(&ib_uverbs_idr_mutex); 841 842 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 843 scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); 844 rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); 845 srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL; 846 847 if (!pd || pd->uobject->context != file->ucontext || 848 !scq || scq->uobject->context != file->ucontext || 849 !rcq || rcq->uobject->context != file->ucontext || 850 (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) { 851 ret = -EINVAL; 852 goto err_up; 853 } 854 855 attr.event_handler = ib_uverbs_qp_event_handler; 856 attr.qp_context = file; 857 attr.send_cq = scq; 858 attr.recv_cq = rcq; 859 attr.srq = srq; 860 attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; 861 attr.qp_type = cmd.qp_type; 862 863 attr.cap.max_send_wr = cmd.max_send_wr; 864 attr.cap.max_recv_wr = cmd.max_recv_wr; 865 attr.cap.max_send_sge = cmd.max_send_sge; 866 attr.cap.max_recv_sge = cmd.max_recv_sge; 867 attr.cap.max_inline_data = cmd.max_inline_data; 868 869 uobj->uevent.uobject.user_handle = cmd.user_handle; 870 uobj->uevent.uobject.context = file->ucontext; 871 uobj->uevent.events_reported = 0; 872 INIT_LIST_HEAD(&uobj->uevent.event_list); 873 INIT_LIST_HEAD(&uobj->mcast_list); 874 875 qp = pd->device->create_qp(pd, &attr, &udata); 876 if (IS_ERR(qp)) { 877 ret = PTR_ERR(qp); 878 goto err_up; 879 } 880 881 qp->device = pd->device; 882 qp->pd = pd; 883 qp->send_cq = attr.send_cq; 884 qp->recv_cq = attr.recv_cq; 885 qp->srq = attr.srq; 886 qp->uobject = &uobj->uevent.uobject; 887 qp->event_handler = attr.event_handler; 888 qp->qp_context = attr.qp_context; 889 qp->qp_type = attr.qp_type; 890 atomic_inc(&pd->usecnt); 891 atomic_inc(&attr.send_cq->usecnt); 892 atomic_inc(&attr.recv_cq->usecnt); 893 if (attr.srq) 894 atomic_inc(&attr.srq->usecnt); 895 896 memset(&resp, 0, sizeof resp); 897 resp.qpn = qp->qp_num; 898 899 retry: 900 if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) { 901 ret = -ENOMEM; 902 goto err_destroy; 903 } 904 905 ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id); 906 907 if (ret == -EAGAIN) 908 goto retry; 909 if (ret) 910 goto err_destroy; 911 912 resp.qp_handle = uobj->uevent.uobject.id; 913 resp.max_recv_sge = attr.cap.max_recv_sge; 914 resp.max_send_sge = attr.cap.max_send_sge; 915 resp.max_recv_wr = attr.cap.max_recv_wr; 916 resp.max_send_wr = attr.cap.max_send_wr; 917 resp.max_inline_data = attr.cap.max_inline_data; 918 919 if (copy_to_user((void __user *) (unsigned long) cmd.response, 920 &resp, sizeof resp)) { 921 ret = -EFAULT; 922 goto err_idr; 923 } 924 925 down(&file->mutex); 926 list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); 927 up(&file->mutex); 928 929 up(&ib_uverbs_idr_mutex); 930 931 return in_len; 932 933 err_idr: 934 idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id); 935 936 err_destroy: 937 ib_destroy_qp(qp); 938 939 err_up: 940 up(&ib_uverbs_idr_mutex); 941 942 kfree(uobj); 943 return ret; 944 } 945 946 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, 947 const char __user *buf, int in_len, 948 int out_len) 949 { 950 struct ib_uverbs_modify_qp cmd; 951 struct ib_qp *qp; 952 struct ib_qp_attr *attr; 953 int ret; 954 955 if (copy_from_user(&cmd, buf, sizeof cmd)) 956 return -EFAULT; 957 958 attr = kmalloc(sizeof *attr, GFP_KERNEL); 959 if (!attr) 960 return -ENOMEM; 961 962 down(&ib_uverbs_idr_mutex); 963 964 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 965 if (!qp || qp->uobject->context != file->ucontext) { 966 ret = -EINVAL; 967 goto out; 968 } 969 970 attr->qp_state = cmd.qp_state; 971 attr->cur_qp_state = cmd.cur_qp_state; 972 attr->path_mtu = cmd.path_mtu; 973 attr->path_mig_state = cmd.path_mig_state; 974 attr->qkey = cmd.qkey; 975 attr->rq_psn = cmd.rq_psn; 976 attr->sq_psn = cmd.sq_psn; 977 attr->dest_qp_num = cmd.dest_qp_num; 978 attr->qp_access_flags = cmd.qp_access_flags; 979 attr->pkey_index = cmd.pkey_index; 980 attr->alt_pkey_index = cmd.pkey_index; 981 attr->en_sqd_async_notify = cmd.en_sqd_async_notify; 982 attr->max_rd_atomic = cmd.max_rd_atomic; 983 attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; 984 attr->min_rnr_timer = cmd.min_rnr_timer; 985 attr->port_num = cmd.port_num; 986 attr->timeout = cmd.timeout; 987 attr->retry_cnt = cmd.retry_cnt; 988 attr->rnr_retry = cmd.rnr_retry; 989 attr->alt_port_num = cmd.alt_port_num; 990 attr->alt_timeout = cmd.alt_timeout; 991 992 memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); 993 attr->ah_attr.grh.flow_label = cmd.dest.flow_label; 994 attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; 995 attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; 996 attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; 997 attr->ah_attr.dlid = cmd.dest.dlid; 998 attr->ah_attr.sl = cmd.dest.sl; 999 attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; 1000 attr->ah_attr.static_rate = cmd.dest.static_rate; 1001 attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; 1002 attr->ah_attr.port_num = cmd.dest.port_num; 1003 1004 memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); 1005 attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; 1006 attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; 1007 attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; 1008 attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; 1009 attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; 1010 attr->alt_ah_attr.sl = cmd.alt_dest.sl; 1011 attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; 1012 attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; 1013 attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; 1014 attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; 1015 1016 ret = ib_modify_qp(qp, attr, cmd.attr_mask); 1017 if (ret) 1018 goto out; 1019 1020 ret = in_len; 1021 1022 out: 1023 up(&ib_uverbs_idr_mutex); 1024 kfree(attr); 1025 1026 return ret; 1027 } 1028 1029 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, 1030 const char __user *buf, int in_len, 1031 int out_len) 1032 { 1033 struct ib_uverbs_destroy_qp cmd; 1034 struct ib_uverbs_destroy_qp_resp resp; 1035 struct ib_qp *qp; 1036 struct ib_uqp_object *uobj; 1037 int ret = -EINVAL; 1038 1039 if (copy_from_user(&cmd, buf, sizeof cmd)) 1040 return -EFAULT; 1041 1042 memset(&resp, 0, sizeof resp); 1043 1044 down(&ib_uverbs_idr_mutex); 1045 1046 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1047 if (!qp || qp->uobject->context != file->ucontext) 1048 goto out; 1049 1050 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1051 1052 if (!list_empty(&uobj->mcast_list)) { 1053 ret = -EBUSY; 1054 goto out; 1055 } 1056 1057 ret = ib_destroy_qp(qp); 1058 if (ret) 1059 goto out; 1060 1061 idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); 1062 1063 down(&file->mutex); 1064 list_del(&uobj->uevent.uobject.list); 1065 up(&file->mutex); 1066 1067 ib_uverbs_release_uevent(file, &uobj->uevent); 1068 1069 resp.events_reported = uobj->uevent.events_reported; 1070 1071 kfree(uobj); 1072 1073 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1074 &resp, sizeof resp)) 1075 ret = -EFAULT; 1076 1077 out: 1078 up(&ib_uverbs_idr_mutex); 1079 1080 return ret ? ret : in_len; 1081 } 1082 1083 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, 1084 const char __user *buf, int in_len, 1085 int out_len) 1086 { 1087 struct ib_uverbs_post_send cmd; 1088 struct ib_uverbs_post_send_resp resp; 1089 struct ib_uverbs_send_wr *user_wr; 1090 struct ib_send_wr *wr = NULL, *last, *next, *bad_wr; 1091 struct ib_qp *qp; 1092 int i, sg_ind; 1093 ssize_t ret = -EINVAL; 1094 1095 if (copy_from_user(&cmd, buf, sizeof cmd)) 1096 return -EFAULT; 1097 1098 if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count + 1099 cmd.sge_count * sizeof (struct ib_uverbs_sge)) 1100 return -EINVAL; 1101 1102 if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr)) 1103 return -EINVAL; 1104 1105 user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL); 1106 if (!user_wr) 1107 return -ENOMEM; 1108 1109 down(&ib_uverbs_idr_mutex); 1110 1111 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1112 if (!qp || qp->uobject->context != file->ucontext) 1113 goto out; 1114 1115 sg_ind = 0; 1116 last = NULL; 1117 for (i = 0; i < cmd.wr_count; ++i) { 1118 if (copy_from_user(user_wr, 1119 buf + sizeof cmd + i * cmd.wqe_size, 1120 cmd.wqe_size)) { 1121 ret = -EFAULT; 1122 goto out; 1123 } 1124 1125 if (user_wr->num_sge + sg_ind > cmd.sge_count) { 1126 ret = -EINVAL; 1127 goto out; 1128 } 1129 1130 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + 1131 user_wr->num_sge * sizeof (struct ib_sge), 1132 GFP_KERNEL); 1133 if (!next) { 1134 ret = -ENOMEM; 1135 goto out; 1136 } 1137 1138 if (!last) 1139 wr = next; 1140 else 1141 last->next = next; 1142 last = next; 1143 1144 next->next = NULL; 1145 next->wr_id = user_wr->wr_id; 1146 next->num_sge = user_wr->num_sge; 1147 next->opcode = user_wr->opcode; 1148 next->send_flags = user_wr->send_flags; 1149 next->imm_data = (__be32 __force) user_wr->imm_data; 1150 1151 if (qp->qp_type == IB_QPT_UD) { 1152 next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, 1153 user_wr->wr.ud.ah); 1154 if (!next->wr.ud.ah) { 1155 ret = -EINVAL; 1156 goto out; 1157 } 1158 next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn; 1159 next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey; 1160 } else { 1161 switch (next->opcode) { 1162 case IB_WR_RDMA_WRITE: 1163 case IB_WR_RDMA_WRITE_WITH_IMM: 1164 case IB_WR_RDMA_READ: 1165 next->wr.rdma.remote_addr = 1166 user_wr->wr.rdma.remote_addr; 1167 next->wr.rdma.rkey = 1168 user_wr->wr.rdma.rkey; 1169 break; 1170 case IB_WR_ATOMIC_CMP_AND_SWP: 1171 case IB_WR_ATOMIC_FETCH_AND_ADD: 1172 next->wr.atomic.remote_addr = 1173 user_wr->wr.atomic.remote_addr; 1174 next->wr.atomic.compare_add = 1175 user_wr->wr.atomic.compare_add; 1176 next->wr.atomic.swap = user_wr->wr.atomic.swap; 1177 next->wr.atomic.rkey = user_wr->wr.atomic.rkey; 1178 break; 1179 default: 1180 break; 1181 } 1182 } 1183 1184 if (next->num_sge) { 1185 next->sg_list = (void *) next + 1186 ALIGN(sizeof *next, sizeof (struct ib_sge)); 1187 if (copy_from_user(next->sg_list, 1188 buf + sizeof cmd + 1189 cmd.wr_count * cmd.wqe_size + 1190 sg_ind * sizeof (struct ib_sge), 1191 next->num_sge * sizeof (struct ib_sge))) { 1192 ret = -EFAULT; 1193 goto out; 1194 } 1195 sg_ind += next->num_sge; 1196 } else 1197 next->sg_list = NULL; 1198 } 1199 1200 resp.bad_wr = 0; 1201 ret = qp->device->post_send(qp, wr, &bad_wr); 1202 if (ret) 1203 for (next = wr; next; next = next->next) { 1204 ++resp.bad_wr; 1205 if (next == bad_wr) 1206 break; 1207 } 1208 1209 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1210 &resp, sizeof resp)) 1211 ret = -EFAULT; 1212 1213 out: 1214 up(&ib_uverbs_idr_mutex); 1215 1216 while (wr) { 1217 next = wr->next; 1218 kfree(wr); 1219 wr = next; 1220 } 1221 1222 kfree(user_wr); 1223 1224 return ret ? ret : in_len; 1225 } 1226 1227 static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf, 1228 int in_len, 1229 u32 wr_count, 1230 u32 sge_count, 1231 u32 wqe_size) 1232 { 1233 struct ib_uverbs_recv_wr *user_wr; 1234 struct ib_recv_wr *wr = NULL, *last, *next; 1235 int sg_ind; 1236 int i; 1237 int ret; 1238 1239 if (in_len < wqe_size * wr_count + 1240 sge_count * sizeof (struct ib_uverbs_sge)) 1241 return ERR_PTR(-EINVAL); 1242 1243 if (wqe_size < sizeof (struct ib_uverbs_recv_wr)) 1244 return ERR_PTR(-EINVAL); 1245 1246 user_wr = kmalloc(wqe_size, GFP_KERNEL); 1247 if (!user_wr) 1248 return ERR_PTR(-ENOMEM); 1249 1250 sg_ind = 0; 1251 last = NULL; 1252 for (i = 0; i < wr_count; ++i) { 1253 if (copy_from_user(user_wr, buf + i * wqe_size, 1254 wqe_size)) { 1255 ret = -EFAULT; 1256 goto err; 1257 } 1258 1259 if (user_wr->num_sge + sg_ind > sge_count) { 1260 ret = -EINVAL; 1261 goto err; 1262 } 1263 1264 next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) + 1265 user_wr->num_sge * sizeof (struct ib_sge), 1266 GFP_KERNEL); 1267 if (!next) { 1268 ret = -ENOMEM; 1269 goto err; 1270 } 1271 1272 if (!last) 1273 wr = next; 1274 else 1275 last->next = next; 1276 last = next; 1277 1278 next->next = NULL; 1279 next->wr_id = user_wr->wr_id; 1280 next->num_sge = user_wr->num_sge; 1281 1282 if (next->num_sge) { 1283 next->sg_list = (void *) next + 1284 ALIGN(sizeof *next, sizeof (struct ib_sge)); 1285 if (copy_from_user(next->sg_list, 1286 buf + wr_count * wqe_size + 1287 sg_ind * sizeof (struct ib_sge), 1288 next->num_sge * sizeof (struct ib_sge))) { 1289 ret = -EFAULT; 1290 goto err; 1291 } 1292 sg_ind += next->num_sge; 1293 } else 1294 next->sg_list = NULL; 1295 } 1296 1297 kfree(user_wr); 1298 return wr; 1299 1300 err: 1301 kfree(user_wr); 1302 1303 while (wr) { 1304 next = wr->next; 1305 kfree(wr); 1306 wr = next; 1307 } 1308 1309 return ERR_PTR(ret); 1310 } 1311 1312 ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, 1313 const char __user *buf, int in_len, 1314 int out_len) 1315 { 1316 struct ib_uverbs_post_recv cmd; 1317 struct ib_uverbs_post_recv_resp resp; 1318 struct ib_recv_wr *wr, *next, *bad_wr; 1319 struct ib_qp *qp; 1320 ssize_t ret = -EINVAL; 1321 1322 if (copy_from_user(&cmd, buf, sizeof cmd)) 1323 return -EFAULT; 1324 1325 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, 1326 in_len - sizeof cmd, cmd.wr_count, 1327 cmd.sge_count, cmd.wqe_size); 1328 if (IS_ERR(wr)) 1329 return PTR_ERR(wr); 1330 1331 down(&ib_uverbs_idr_mutex); 1332 1333 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1334 if (!qp || qp->uobject->context != file->ucontext) 1335 goto out; 1336 1337 resp.bad_wr = 0; 1338 ret = qp->device->post_recv(qp, wr, &bad_wr); 1339 if (ret) 1340 for (next = wr; next; next = next->next) { 1341 ++resp.bad_wr; 1342 if (next == bad_wr) 1343 break; 1344 } 1345 1346 1347 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1348 &resp, sizeof resp)) 1349 ret = -EFAULT; 1350 1351 out: 1352 up(&ib_uverbs_idr_mutex); 1353 1354 while (wr) { 1355 next = wr->next; 1356 kfree(wr); 1357 wr = next; 1358 } 1359 1360 return ret ? ret : in_len; 1361 } 1362 1363 ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, 1364 const char __user *buf, int in_len, 1365 int out_len) 1366 { 1367 struct ib_uverbs_post_srq_recv cmd; 1368 struct ib_uverbs_post_srq_recv_resp resp; 1369 struct ib_recv_wr *wr, *next, *bad_wr; 1370 struct ib_srq *srq; 1371 ssize_t ret = -EINVAL; 1372 1373 if (copy_from_user(&cmd, buf, sizeof cmd)) 1374 return -EFAULT; 1375 1376 wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd, 1377 in_len - sizeof cmd, cmd.wr_count, 1378 cmd.sge_count, cmd.wqe_size); 1379 if (IS_ERR(wr)) 1380 return PTR_ERR(wr); 1381 1382 down(&ib_uverbs_idr_mutex); 1383 1384 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1385 if (!srq || srq->uobject->context != file->ucontext) 1386 goto out; 1387 1388 resp.bad_wr = 0; 1389 ret = srq->device->post_srq_recv(srq, wr, &bad_wr); 1390 if (ret) 1391 for (next = wr; next; next = next->next) { 1392 ++resp.bad_wr; 1393 if (next == bad_wr) 1394 break; 1395 } 1396 1397 1398 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1399 &resp, sizeof resp)) 1400 ret = -EFAULT; 1401 1402 out: 1403 up(&ib_uverbs_idr_mutex); 1404 1405 while (wr) { 1406 next = wr->next; 1407 kfree(wr); 1408 wr = next; 1409 } 1410 1411 return ret ? ret : in_len; 1412 } 1413 1414 ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, 1415 const char __user *buf, int in_len, 1416 int out_len) 1417 { 1418 struct ib_uverbs_create_ah cmd; 1419 struct ib_uverbs_create_ah_resp resp; 1420 struct ib_uobject *uobj; 1421 struct ib_pd *pd; 1422 struct ib_ah *ah; 1423 struct ib_ah_attr attr; 1424 int ret; 1425 1426 if (out_len < sizeof resp) 1427 return -ENOSPC; 1428 1429 if (copy_from_user(&cmd, buf, sizeof cmd)) 1430 return -EFAULT; 1431 1432 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 1433 if (!uobj) 1434 return -ENOMEM; 1435 1436 down(&ib_uverbs_idr_mutex); 1437 1438 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1439 if (!pd || pd->uobject->context != file->ucontext) { 1440 ret = -EINVAL; 1441 goto err_up; 1442 } 1443 1444 uobj->user_handle = cmd.user_handle; 1445 uobj->context = file->ucontext; 1446 1447 attr.dlid = cmd.attr.dlid; 1448 attr.sl = cmd.attr.sl; 1449 attr.src_path_bits = cmd.attr.src_path_bits; 1450 attr.static_rate = cmd.attr.static_rate; 1451 attr.port_num = cmd.attr.port_num; 1452 attr.grh.flow_label = cmd.attr.grh.flow_label; 1453 attr.grh.sgid_index = cmd.attr.grh.sgid_index; 1454 attr.grh.hop_limit = cmd.attr.grh.hop_limit; 1455 attr.grh.traffic_class = cmd.attr.grh.traffic_class; 1456 memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); 1457 1458 ah = ib_create_ah(pd, &attr); 1459 if (IS_ERR(ah)) { 1460 ret = PTR_ERR(ah); 1461 goto err_up; 1462 } 1463 1464 ah->uobject = uobj; 1465 1466 retry: 1467 if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) { 1468 ret = -ENOMEM; 1469 goto err_destroy; 1470 } 1471 1472 ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id); 1473 1474 if (ret == -EAGAIN) 1475 goto retry; 1476 if (ret) 1477 goto err_destroy; 1478 1479 resp.ah_handle = uobj->id; 1480 1481 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1482 &resp, sizeof resp)) { 1483 ret = -EFAULT; 1484 goto err_idr; 1485 } 1486 1487 down(&file->mutex); 1488 list_add_tail(&uobj->list, &file->ucontext->ah_list); 1489 up(&file->mutex); 1490 1491 up(&ib_uverbs_idr_mutex); 1492 1493 return in_len; 1494 1495 err_idr: 1496 idr_remove(&ib_uverbs_ah_idr, uobj->id); 1497 1498 err_destroy: 1499 ib_destroy_ah(ah); 1500 1501 err_up: 1502 up(&ib_uverbs_idr_mutex); 1503 1504 kfree(uobj); 1505 return ret; 1506 } 1507 1508 ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, 1509 const char __user *buf, int in_len, int out_len) 1510 { 1511 struct ib_uverbs_destroy_ah cmd; 1512 struct ib_ah *ah; 1513 struct ib_uobject *uobj; 1514 int ret = -EINVAL; 1515 1516 if (copy_from_user(&cmd, buf, sizeof cmd)) 1517 return -EFAULT; 1518 1519 down(&ib_uverbs_idr_mutex); 1520 1521 ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); 1522 if (!ah || ah->uobject->context != file->ucontext) 1523 goto out; 1524 1525 uobj = ah->uobject; 1526 1527 ret = ib_destroy_ah(ah); 1528 if (ret) 1529 goto out; 1530 1531 idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); 1532 1533 down(&file->mutex); 1534 list_del(&uobj->list); 1535 up(&file->mutex); 1536 1537 kfree(uobj); 1538 1539 out: 1540 up(&ib_uverbs_idr_mutex); 1541 1542 return ret ? ret : in_len; 1543 } 1544 1545 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, 1546 const char __user *buf, int in_len, 1547 int out_len) 1548 { 1549 struct ib_uverbs_attach_mcast cmd; 1550 struct ib_qp *qp; 1551 struct ib_uqp_object *uobj; 1552 struct ib_uverbs_mcast_entry *mcast; 1553 int ret = -EINVAL; 1554 1555 if (copy_from_user(&cmd, buf, sizeof cmd)) 1556 return -EFAULT; 1557 1558 down(&ib_uverbs_idr_mutex); 1559 1560 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1561 if (!qp || qp->uobject->context != file->ucontext) 1562 goto out; 1563 1564 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1565 1566 list_for_each_entry(mcast, &uobj->mcast_list, list) 1567 if (cmd.mlid == mcast->lid && 1568 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 1569 ret = 0; 1570 goto out; 1571 } 1572 1573 mcast = kmalloc(sizeof *mcast, GFP_KERNEL); 1574 if (!mcast) { 1575 ret = -ENOMEM; 1576 goto out; 1577 } 1578 1579 mcast->lid = cmd.mlid; 1580 memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw); 1581 1582 ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid); 1583 if (!ret) { 1584 uobj = container_of(qp->uobject, struct ib_uqp_object, 1585 uevent.uobject); 1586 list_add_tail(&mcast->list, &uobj->mcast_list); 1587 } else 1588 kfree(mcast); 1589 1590 out: 1591 up(&ib_uverbs_idr_mutex); 1592 1593 return ret ? ret : in_len; 1594 } 1595 1596 ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, 1597 const char __user *buf, int in_len, 1598 int out_len) 1599 { 1600 struct ib_uverbs_detach_mcast cmd; 1601 struct ib_uqp_object *uobj; 1602 struct ib_qp *qp; 1603 struct ib_uverbs_mcast_entry *mcast; 1604 int ret = -EINVAL; 1605 1606 if (copy_from_user(&cmd, buf, sizeof cmd)) 1607 return -EFAULT; 1608 1609 down(&ib_uverbs_idr_mutex); 1610 1611 qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); 1612 if (!qp || qp->uobject->context != file->ucontext) 1613 goto out; 1614 1615 ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); 1616 if (ret) 1617 goto out; 1618 1619 uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject); 1620 1621 list_for_each_entry(mcast, &uobj->mcast_list, list) 1622 if (cmd.mlid == mcast->lid && 1623 !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) { 1624 list_del(&mcast->list); 1625 kfree(mcast); 1626 break; 1627 } 1628 1629 out: 1630 up(&ib_uverbs_idr_mutex); 1631 1632 return ret ? ret : in_len; 1633 } 1634 1635 ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, 1636 const char __user *buf, int in_len, 1637 int out_len) 1638 { 1639 struct ib_uverbs_create_srq cmd; 1640 struct ib_uverbs_create_srq_resp resp; 1641 struct ib_udata udata; 1642 struct ib_uevent_object *uobj; 1643 struct ib_pd *pd; 1644 struct ib_srq *srq; 1645 struct ib_srq_init_attr attr; 1646 int ret; 1647 1648 if (out_len < sizeof resp) 1649 return -ENOSPC; 1650 1651 if (copy_from_user(&cmd, buf, sizeof cmd)) 1652 return -EFAULT; 1653 1654 INIT_UDATA(&udata, buf + sizeof cmd, 1655 (unsigned long) cmd.response + sizeof resp, 1656 in_len - sizeof cmd, out_len - sizeof resp); 1657 1658 uobj = kmalloc(sizeof *uobj, GFP_KERNEL); 1659 if (!uobj) 1660 return -ENOMEM; 1661 1662 down(&ib_uverbs_idr_mutex); 1663 1664 pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); 1665 1666 if (!pd || pd->uobject->context != file->ucontext) { 1667 ret = -EINVAL; 1668 goto err_up; 1669 } 1670 1671 attr.event_handler = ib_uverbs_srq_event_handler; 1672 attr.srq_context = file; 1673 attr.attr.max_wr = cmd.max_wr; 1674 attr.attr.max_sge = cmd.max_sge; 1675 attr.attr.srq_limit = cmd.srq_limit; 1676 1677 uobj->uobject.user_handle = cmd.user_handle; 1678 uobj->uobject.context = file->ucontext; 1679 uobj->events_reported = 0; 1680 INIT_LIST_HEAD(&uobj->event_list); 1681 1682 srq = pd->device->create_srq(pd, &attr, &udata); 1683 if (IS_ERR(srq)) { 1684 ret = PTR_ERR(srq); 1685 goto err_up; 1686 } 1687 1688 srq->device = pd->device; 1689 srq->pd = pd; 1690 srq->uobject = &uobj->uobject; 1691 srq->event_handler = attr.event_handler; 1692 srq->srq_context = attr.srq_context; 1693 atomic_inc(&pd->usecnt); 1694 atomic_set(&srq->usecnt, 0); 1695 1696 memset(&resp, 0, sizeof resp); 1697 1698 retry: 1699 if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) { 1700 ret = -ENOMEM; 1701 goto err_destroy; 1702 } 1703 1704 ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id); 1705 1706 if (ret == -EAGAIN) 1707 goto retry; 1708 if (ret) 1709 goto err_destroy; 1710 1711 resp.srq_handle = uobj->uobject.id; 1712 1713 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1714 &resp, sizeof resp)) { 1715 ret = -EFAULT; 1716 goto err_idr; 1717 } 1718 1719 down(&file->mutex); 1720 list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); 1721 up(&file->mutex); 1722 1723 up(&ib_uverbs_idr_mutex); 1724 1725 return in_len; 1726 1727 err_idr: 1728 idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id); 1729 1730 err_destroy: 1731 ib_destroy_srq(srq); 1732 1733 err_up: 1734 up(&ib_uverbs_idr_mutex); 1735 1736 kfree(uobj); 1737 return ret; 1738 } 1739 1740 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, 1741 const char __user *buf, int in_len, 1742 int out_len) 1743 { 1744 struct ib_uverbs_modify_srq cmd; 1745 struct ib_srq *srq; 1746 struct ib_srq_attr attr; 1747 int ret; 1748 1749 if (copy_from_user(&cmd, buf, sizeof cmd)) 1750 return -EFAULT; 1751 1752 down(&ib_uverbs_idr_mutex); 1753 1754 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1755 if (!srq || srq->uobject->context != file->ucontext) { 1756 ret = -EINVAL; 1757 goto out; 1758 } 1759 1760 attr.max_wr = cmd.max_wr; 1761 attr.srq_limit = cmd.srq_limit; 1762 1763 ret = ib_modify_srq(srq, &attr, cmd.attr_mask); 1764 1765 out: 1766 up(&ib_uverbs_idr_mutex); 1767 1768 return ret ? ret : in_len; 1769 } 1770 1771 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, 1772 const char __user *buf, int in_len, 1773 int out_len) 1774 { 1775 struct ib_uverbs_destroy_srq cmd; 1776 struct ib_uverbs_destroy_srq_resp resp; 1777 struct ib_srq *srq; 1778 struct ib_uevent_object *uobj; 1779 int ret = -EINVAL; 1780 1781 if (copy_from_user(&cmd, buf, sizeof cmd)) 1782 return -EFAULT; 1783 1784 down(&ib_uverbs_idr_mutex); 1785 1786 memset(&resp, 0, sizeof resp); 1787 1788 srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); 1789 if (!srq || srq->uobject->context != file->ucontext) 1790 goto out; 1791 1792 uobj = container_of(srq->uobject, struct ib_uevent_object, uobject); 1793 1794 ret = ib_destroy_srq(srq); 1795 if (ret) 1796 goto out; 1797 1798 idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); 1799 1800 down(&file->mutex); 1801 list_del(&uobj->uobject.list); 1802 up(&file->mutex); 1803 1804 ib_uverbs_release_uevent(file, uobj); 1805 1806 resp.events_reported = uobj->events_reported; 1807 1808 kfree(uobj); 1809 1810 if (copy_to_user((void __user *) (unsigned long) cmd.response, 1811 &resp, sizeof resp)) 1812 ret = -EFAULT; 1813 1814 out: 1815 up(&ib_uverbs_idr_mutex); 1816 1817 return ret ? ret : in_len; 1818 } 1819