Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma

Pull rdma fixes from Doug Ledford:
"Nothing in this is overly interesting, it's mostly your garden variety
fixes.

There was some work in this merge cycle around the new ioctl kABI, so
there are fixes in here related to that (probably with more to come).

We've also recently added new netlink support with a goal of moving
the primary means of configuring the entire subsystem to netlink
(eventually, this is a long term project), so there are fixes for
that.

Then a few bnxt_re driver fixes, and a few minor WARN_ON removals, and
that covers this pull request. There are already a few more fixes on
the list as of this morning, so there will certainly be more to come
in this rc cycle ;-)

Summary:

- Lots of fixes for the new IOCTL interface and general uverbs flow.
Found through testing and syzkaller

- Bugfixes for the new resource track netlink reporting

- Remove some unneeded WARN_ONs that were triggering for some users
in IPoIB

- Various fixes for the bnxt_re driver"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (27 commits)
RDMA/uverbs: Fix kernel panic while using XRC_TGT QP type
RDMA/bnxt_re: Avoid system hang during device un-reg
RDMA/bnxt_re: Fix system crash during load/unload
RDMA/bnxt_re: Synchronize destroy_qp with poll_cq
RDMA/bnxt_re: Unpin SQ and RQ memory if QP create fails
RDMA/bnxt_re: Disable atomic capability on bnxt_re adapters
RDMA/restrack: don't use uaccess_kernel()
RDMA/verbs: Check existence of function prior to accessing it
RDMA/vmw_pvrdma: Fix usage of user response structures in ABI file
RDMA/uverbs: Sanitize user entered port numbers prior to access it
RDMA/uverbs: Fix circular locking dependency
RDMA/uverbs: Fix bad unlock balance in ib_uverbs_close_xrcd
RDMA/restrack: Increment CQ restrack object before committing
RDMA/uverbs: Protect from command mask overflow
IB/uverbs: Fix unbalanced unlock on error path for rdma_explicit_destroy
IB/uverbs: Improve lockdep_check
RDMA/uverbs: Protect from races between lookup and destroy of uobjects
IB/uverbs: Hold the uobj write lock after allocate
IB/uverbs: Fix possible oops with duplicate ioctl attributes
IB/uverbs: Add ioctl support for 32bit processes
...

+242 -115
+6 -1
drivers/infiniband/core/core_priv.h
··· 305 305 static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, 306 306 struct ib_pd *pd, 307 307 struct ib_qp_init_attr *attr, 308 - struct ib_udata *udata) 308 + struct ib_udata *udata, 309 + struct ib_uobject *uobj) 309 310 { 310 311 struct ib_qp *qp; 312 + 313 + if (!dev->create_qp) 314 + return ERR_PTR(-EOPNOTSUPP); 311 315 312 316 qp = dev->create_qp(pd, attr, udata); 313 317 if (IS_ERR(qp)) ··· 319 315 320 316 qp->device = dev; 321 317 qp->pd = pd; 318 + qp->uobject = uobj; 322 319 /* 323 320 * We don't track XRC QPs for now, because they don't have PD 324 321 * and more importantly they are created internaly by driver,
+28 -10
drivers/infiniband/core/rdma_core.c
··· 141 141 */ 142 142 uobj->context = context; 143 143 uobj->type = type; 144 - atomic_set(&uobj->usecnt, 0); 144 + /* 145 + * Allocated objects start out as write locked to deny any other 146 + * syscalls from accessing them until they are committed. See 147 + * rdma_alloc_commit_uobject 148 + */ 149 + atomic_set(&uobj->usecnt, -1); 145 150 kref_init(&uobj->ref); 146 151 147 152 return uobj; ··· 201 196 goto free; 202 197 } 203 198 204 - uverbs_uobject_get(uobj); 199 + /* 200 + * The idr_find is guaranteed to return a pointer to something that 201 + * isn't freed yet, or NULL, as the free after idr_remove goes through 202 + * kfree_rcu(). However the object may still have been released and 203 + * kfree() could be called at any time. 204 + */ 205 + if (!kref_get_unless_zero(&uobj->ref)) 206 + uobj = ERR_PTR(-ENOENT); 207 + 205 208 free: 206 209 rcu_read_unlock(); 207 210 return uobj; ··· 412 399 return ret; 413 400 } 414 401 415 - static void lockdep_check(struct ib_uobject *uobj, bool exclusive) 402 + static void assert_uverbs_usecnt(struct ib_uobject *uobj, bool exclusive) 416 403 { 417 404 #ifdef CONFIG_LOCKDEP 418 405 if (exclusive) 419 - WARN_ON(atomic_read(&uobj->usecnt) > 0); 406 + WARN_ON(atomic_read(&uobj->usecnt) != -1); 420 407 else 421 - WARN_ON(atomic_read(&uobj->usecnt) == -1); 408 + WARN_ON(atomic_read(&uobj->usecnt) <= 0); 422 409 #endif 423 410 } 424 411 ··· 457 444 WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n"); 458 445 return 0; 459 446 } 460 - lockdep_check(uobj, true); 447 + assert_uverbs_usecnt(uobj, true); 461 448 ret = _rdma_remove_commit_uobject(uobj, RDMA_REMOVE_DESTROY); 462 449 463 450 up_read(&ucontext->cleanup_rwsem); ··· 487 474 WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n"); 488 475 return 0; 489 476 } 490 - lockdep_check(uobject, true); 477 + assert_uverbs_usecnt(uobject, true); 491 478 ret = uobject->type->type_class->remove_commit(uobject, 492 479 RDMA_REMOVE_DESTROY); 493 480 if (ret) 494 - return ret; 481 + goto out; 495 482 496 483 uobject->type = &null_obj_type; 497 484 485 + out: 498 486 up_read(&ucontext->cleanup_rwsem); 499 - return 0; 487 + return ret; 500 488 } 501 489 502 490 static void alloc_commit_idr_uobject(struct ib_uobject *uobj) ··· 541 527 return ret; 542 528 } 543 529 530 + /* matches atomic_set(-1) in alloc_uobj */ 531 + assert_uverbs_usecnt(uobj, true); 532 + atomic_set(&uobj->usecnt, 0); 533 + 544 534 uobj->type->type_class->alloc_commit(uobj); 545 535 up_read(&uobj->context->cleanup_rwsem); 546 536 ··· 579 561 580 562 void rdma_lookup_put_uobject(struct ib_uobject *uobj, bool exclusive) 581 563 { 582 - lockdep_check(uobj, exclusive); 564 + assert_uverbs_usecnt(uobj, exclusive); 583 565 uobj->type->type_class->lookup_put(uobj, exclusive); 584 566 /* 585 567 * In order to unlock an object, either decrease its usecnt for
+16 -7
drivers/infiniband/core/restrack.c
··· 7 7 #include <rdma/restrack.h> 8 8 #include <linux/mutex.h> 9 9 #include <linux/sched/task.h> 10 - #include <linux/uaccess.h> 11 10 #include <linux/pid_namespace.h> 12 11 13 12 void rdma_restrack_init(struct rdma_restrack_root *res) ··· 62 63 { 63 64 enum rdma_restrack_type type = res->type; 64 65 struct ib_device *dev; 65 - struct ib_xrcd *xrcd; 66 66 struct ib_pd *pd; 67 67 struct ib_cq *cq; 68 68 struct ib_qp *qp; ··· 79 81 qp = container_of(res, struct ib_qp, res); 80 82 dev = qp->device; 81 83 break; 82 - case RDMA_RESTRACK_XRCD: 83 - xrcd = container_of(res, struct ib_xrcd, res); 84 - dev = xrcd->device; 85 - break; 86 84 default: 87 85 WARN_ONCE(true, "Wrong resource tracking type %u\n", type); 88 86 return NULL; 89 87 } 90 88 91 89 return dev; 90 + } 91 + 92 + static bool res_is_user(struct rdma_restrack_entry *res) 93 + { 94 + switch (res->type) { 95 + case RDMA_RESTRACK_PD: 96 + return container_of(res, struct ib_pd, res)->uobject; 97 + case RDMA_RESTRACK_CQ: 98 + return container_of(res, struct ib_cq, res)->uobject; 99 + case RDMA_RESTRACK_QP: 100 + return container_of(res, struct ib_qp, res)->uobject; 101 + default: 102 + WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type); 103 + return false; 104 + } 92 105 } 93 106 94 107 void rdma_restrack_add(struct rdma_restrack_entry *res) ··· 109 100 if (!dev) 110 101 return; 111 102 112 - if (!uaccess_kernel()) { 103 + if (res_is_user(res)) { 113 104 get_task_struct(current); 114 105 res->task = current; 115 106 res->kern_name = NULL;
+40 -10
drivers/infiniband/core/uverbs_cmd.c
··· 562 562 if (f.file) 563 563 fdput(f); 564 564 565 + mutex_unlock(&file->device->xrcd_tree_mutex); 566 + 565 567 uobj_alloc_commit(&obj->uobject); 566 568 567 - mutex_unlock(&file->device->xrcd_tree_mutex); 568 569 return in_len; 569 570 570 571 err_copy: ··· 604 603 605 604 uobj = uobj_get_write(uobj_get_type(xrcd), cmd.xrcd_handle, 606 605 file->ucontext); 607 - if (IS_ERR(uobj)) { 608 - mutex_unlock(&file->device->xrcd_tree_mutex); 606 + if (IS_ERR(uobj)) 609 607 return PTR_ERR(uobj); 610 - } 611 608 612 609 ret = uobj_remove_commit(uobj); 613 610 return ret ?: in_len; ··· 978 979 struct ib_uverbs_ex_create_cq_resp resp; 979 980 struct ib_cq_init_attr attr = {}; 980 981 982 + if (!ib_dev->create_cq) 983 + return ERR_PTR(-EOPNOTSUPP); 984 + 981 985 if (cmd->comp_vector >= file->device->num_comp_vectors) 982 986 return ERR_PTR(-EINVAL); 983 987 ··· 1032 1030 resp.response_length = offsetof(typeof(resp), response_length) + 1033 1031 sizeof(resp.response_length); 1034 1032 1033 + cq->res.type = RDMA_RESTRACK_CQ; 1034 + rdma_restrack_add(&cq->res); 1035 + 1035 1036 ret = cb(file, obj, &resp, ucore, context); 1036 1037 if (ret) 1037 1038 goto err_cb; 1038 1039 1039 1040 uobj_alloc_commit(&obj->uobject); 1040 - cq->res.type = RDMA_RESTRACK_CQ; 1041 - rdma_restrack_add(&cq->res); 1042 - 1043 1041 return obj; 1044 1042 1045 1043 err_cb: ··· 1520 1518 if (cmd->qp_type == IB_QPT_XRC_TGT) 1521 1519 qp = ib_create_qp(pd, &attr); 1522 1520 else 1523 - qp = _ib_create_qp(device, pd, &attr, uhw); 1521 + qp = _ib_create_qp(device, pd, &attr, uhw, 1522 + &obj->uevent.uobject); 1524 1523 1525 1524 if (IS_ERR(qp)) { 1526 1525 ret = PTR_ERR(qp); ··· 1553 1550 atomic_inc(&attr.srq->usecnt); 1554 1551 if (ind_tbl) 1555 1552 atomic_inc(&ind_tbl->usecnt); 1553 + } else { 1554 + /* It is done in _ib_create_qp for other QP types */ 1555 + qp->uobject = &obj->uevent.uobject; 1556 1556 } 1557 - qp->uobject = &obj->uevent.uobject; 1558 1557 1559 1558 obj->uevent.uobject.object = qp; 1560 1559 ··· 1976 1971 goto release_qp; 1977 1972 } 1978 1973 1974 + if ((cmd->base.attr_mask & IB_QP_AV) && 1975 + !rdma_is_port_valid(qp->device, cmd->base.dest.port_num)) { 1976 + ret = -EINVAL; 1977 + goto release_qp; 1978 + } 1979 + 1979 1980 if ((cmd->base.attr_mask & IB_QP_ALT_PATH) && 1980 - !rdma_is_port_valid(qp->device, cmd->base.alt_port_num)) { 1981 + (!rdma_is_port_valid(qp->device, cmd->base.alt_port_num) || 1982 + !rdma_is_port_valid(qp->device, cmd->base.alt_dest.port_num))) { 1981 1983 ret = -EINVAL; 1982 1984 goto release_qp; 1983 1985 } ··· 2953 2941 wq_init_attr.create_flags = cmd.create_flags; 2954 2942 obj->uevent.events_reported = 0; 2955 2943 INIT_LIST_HEAD(&obj->uevent.event_list); 2944 + 2945 + if (!pd->device->create_wq) { 2946 + err = -EOPNOTSUPP; 2947 + goto err_put_cq; 2948 + } 2956 2949 wq = pd->device->create_wq(pd, &wq_init_attr, uhw); 2957 2950 if (IS_ERR(wq)) { 2958 2951 err = PTR_ERR(wq); ··· 3101 3084 wq_attr.flags = cmd.flags; 3102 3085 wq_attr.flags_mask = cmd.flags_mask; 3103 3086 } 3087 + if (!wq->device->modify_wq) { 3088 + ret = -EOPNOTSUPP; 3089 + goto out; 3090 + } 3104 3091 ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw); 3092 + out: 3105 3093 uobj_put_obj_read(wq); 3106 3094 return ret; 3107 3095 } ··· 3203 3181 3204 3182 init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size; 3205 3183 init_attr.ind_tbl = wqs; 3184 + 3185 + if (!ib_dev->create_rwq_ind_table) { 3186 + err = -EOPNOTSUPP; 3187 + goto err_uobj; 3188 + } 3206 3189 rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw); 3207 3190 3208 3191 if (IS_ERR(rwq_ind_tbl)) { ··· 3796 3769 struct ib_uverbs_ex_query_device cmd; 3797 3770 struct ib_device_attr attr = {0}; 3798 3771 int err; 3772 + 3773 + if (!ib_dev->query_device) 3774 + return -EOPNOTSUPP; 3799 3775 3800 3776 if (ucore->inlen < sizeof(cmd)) 3801 3777 return -EINVAL;
+3
drivers/infiniband/core/uverbs_ioctl.c
··· 59 59 return 0; 60 60 } 61 61 62 + if (test_bit(attr_id, attr_bundle_h->valid_bitmap)) 63 + return -EINVAL; 64 + 62 65 spec = &attr_spec_bucket->attrs[attr_id]; 63 66 e = &elements[attr_id]; 64 67 e->uattr = uattr_ptr;
+9 -9
drivers/infiniband/core/uverbs_ioctl_merge.c
··· 114 114 short min = SHRT_MAX; 115 115 const void *elem; 116 116 int i, j, last_stored = -1; 117 + unsigned int equal_min = 0; 117 118 118 119 for_each_element(elem, i, j, elements, num_elements, num_offset, 119 120 data_offset) { ··· 137 136 */ 138 137 iters[last_stored == i ? num_iters - 1 : num_iters++] = elem; 139 138 last_stored = i; 139 + if (min == GET_ID(id)) 140 + equal_min++; 141 + else 142 + equal_min = 1; 140 143 min = GET_ID(id); 141 144 } 142 145 ··· 151 146 * Therefore, we need to clean the beginning of the array to make sure 152 147 * all ids of final elements are equal to min. 153 148 */ 154 - for (i = num_iters - 1; i >= 0 && 155 - GET_ID(*(u16 *)(iters[i] + id_offset)) == min; i--) 156 - ; 157 - 158 - num_iters -= i + 1; 159 - memmove(iters, iters + i + 1, sizeof(*iters) * num_iters); 149 + memmove(iters, iters + num_iters - equal_min, sizeof(*iters) * equal_min); 160 150 161 151 *min_id = min; 162 - return num_iters; 152 + return equal_min; 163 153 } 164 154 165 155 #define find_max_element_entry_id(num_elements, elements, num_objects_fld, \ ··· 322 322 hash = kzalloc(sizeof(*hash) + 323 323 ALIGN(sizeof(*hash->attrs) * (attr_max_bucket + 1), 324 324 sizeof(long)) + 325 - BITS_TO_LONGS(attr_max_bucket) * sizeof(long), 325 + BITS_TO_LONGS(attr_max_bucket + 1) * sizeof(long), 326 326 GFP_KERNEL); 327 327 if (!hash) { 328 328 res = -ENOMEM; ··· 509 509 * first handler which != NULL. This also defines the 510 510 * set of flags used for this handler. 511 511 */ 512 - for (i = num_object_defs - 1; 512 + for (i = num_method_defs - 1; 513 513 i >= 0 && !method_defs[i]->handler; i--) 514 514 ; 515 515 hash->methods[min_id++] = method;
+22 -7
drivers/infiniband/core/uverbs_main.c
··· 650 650 return -1; 651 651 } 652 652 653 + static bool verify_command_idx(u32 command, bool extended) 654 + { 655 + if (extended) 656 + return command < ARRAY_SIZE(uverbs_ex_cmd_table); 657 + 658 + return command < ARRAY_SIZE(uverbs_cmd_table); 659 + } 660 + 653 661 static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, 654 662 size_t count, loff_t *pos) 655 663 { 656 664 struct ib_uverbs_file *file = filp->private_data; 657 665 struct ib_device *ib_dev; 658 666 struct ib_uverbs_cmd_hdr hdr; 667 + bool extended_command; 659 668 __u32 command; 660 669 __u32 flags; 661 670 int srcu_key; ··· 697 688 } 698 689 699 690 command = hdr.command & IB_USER_VERBS_CMD_COMMAND_MASK; 691 + flags = (hdr.command & 692 + IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT; 693 + 694 + extended_command = flags & IB_USER_VERBS_CMD_FLAG_EXTENDED; 695 + if (!verify_command_idx(command, extended_command)) { 696 + ret = -EINVAL; 697 + goto out; 698 + } 699 + 700 700 if (verify_command_mask(ib_dev, command)) { 701 701 ret = -EOPNOTSUPP; 702 702 goto out; ··· 717 699 goto out; 718 700 } 719 701 720 - flags = (hdr.command & 721 - IB_USER_VERBS_CMD_FLAGS_MASK) >> IB_USER_VERBS_CMD_FLAGS_SHIFT; 722 - 723 702 if (!flags) { 724 - if (command >= ARRAY_SIZE(uverbs_cmd_table) || 725 - !uverbs_cmd_table[command]) { 703 + if (!uverbs_cmd_table[command]) { 726 704 ret = -EINVAL; 727 705 goto out; 728 706 } ··· 739 725 struct ib_udata uhw; 740 726 size_t written_count = count; 741 727 742 - if (command >= ARRAY_SIZE(uverbs_ex_cmd_table) || 743 - !uverbs_ex_cmd_table[command]) { 728 + if (!uverbs_ex_cmd_table[command]) { 744 729 ret = -ENOSYS; 745 730 goto out; 746 731 } ··· 955 942 .llseek = no_llseek, 956 943 #if IS_ENABLED(CONFIG_INFINIBAND_EXP_USER_ACCESS) 957 944 .unlocked_ioctl = ib_uverbs_ioctl, 945 + .compat_ioctl = ib_uverbs_ioctl, 958 946 #endif 959 947 }; 960 948 ··· 968 954 .llseek = no_llseek, 969 955 #if IS_ENABLED(CONFIG_INFINIBAND_EXP_USER_ACCESS) 970 956 .unlocked_ioctl = ib_uverbs_ioctl, 957 + .compat_ioctl = ib_uverbs_ioctl, 971 958 #endif 972 959 }; 973 960
+8 -4
drivers/infiniband/core/uverbs_std_types.c
··· 234 234 uverbs_attr_get(ctx, UVERBS_UHW_OUT); 235 235 236 236 if (!IS_ERR(uhw_in)) { 237 - udata->inbuf = uhw_in->ptr_attr.ptr; 238 237 udata->inlen = uhw_in->ptr_attr.len; 238 + if (uverbs_attr_ptr_is_inline(uhw_in)) 239 + udata->inbuf = &uhw_in->uattr->data; 240 + else 241 + udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data); 239 242 } else { 240 243 udata->inbuf = NULL; 241 244 udata->inlen = 0; 242 245 } 243 246 244 247 if (!IS_ERR(uhw_out)) { 245 - udata->outbuf = uhw_out->ptr_attr.ptr; 248 + udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data); 246 249 udata->outlen = uhw_out->ptr_attr.len; 247 250 } else { 248 251 udata->outbuf = NULL; ··· 326 323 cq->res.type = RDMA_RESTRACK_CQ; 327 324 rdma_restrack_add(&cq->res); 328 325 329 - ret = uverbs_copy_to(attrs, CREATE_CQ_RESP_CQE, &cq->cqe); 326 + ret = uverbs_copy_to(attrs, CREATE_CQ_RESP_CQE, &cq->cqe, 327 + sizeof(cq->cqe)); 330 328 if (ret) 331 329 goto err_cq; 332 330 ··· 379 375 resp.comp_events_reported = obj->comp_events_reported; 380 376 resp.async_events_reported = obj->async_events_reported; 381 377 382 - return uverbs_copy_to(attrs, DESTROY_CQ_RESP, &resp); 378 + return uverbs_copy_to(attrs, DESTROY_CQ_RESP, &resp, sizeof(resp)); 383 379 } 384 380 385 381 static DECLARE_UVERBS_METHOD(
+1 -2
drivers/infiniband/core/verbs.c
··· 887 887 if (qp_init_attr->cap.max_rdma_ctxs) 888 888 rdma_rw_init_qp(device, qp_init_attr); 889 889 890 - qp = _ib_create_qp(device, pd, qp_init_attr, NULL); 890 + qp = _ib_create_qp(device, pd, qp_init_attr, NULL, NULL); 891 891 if (IS_ERR(qp)) 892 892 return qp; 893 893 ··· 898 898 } 899 899 900 900 qp->real_qp = qp; 901 - qp->uobject = NULL; 902 901 qp->qp_type = qp_init_attr->qp_type; 903 902 qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl; 904 903
+1 -1
drivers/infiniband/hw/bnxt_re/bnxt_re.h
··· 120 120 #define BNXT_RE_FLAG_HAVE_L2_REF 3 121 121 #define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4 122 122 #define BNXT_RE_FLAG_QOS_WORK_REG 5 123 - #define BNXT_RE_FLAG_TASK_IN_PROG 6 124 123 #define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29 125 124 struct net_device *netdev; 126 125 unsigned int version, major, minor; ··· 157 158 atomic_t srq_count; 158 159 atomic_t mr_count; 159 160 atomic_t mw_count; 161 + atomic_t sched_count; 160 162 /* Max of 2 lossless traffic class supported per port */ 161 163 u16 cosq[2]; 162 164
+46 -8
drivers/infiniband/hw/bnxt_re/ib_verbs.c
··· 174 174 ib_attr->max_pd = dev_attr->max_pd; 175 175 ib_attr->max_qp_rd_atom = dev_attr->max_qp_rd_atom; 176 176 ib_attr->max_qp_init_rd_atom = dev_attr->max_qp_init_rd_atom; 177 - if (dev_attr->is_atomic) { 178 - ib_attr->atomic_cap = IB_ATOMIC_HCA; 179 - ib_attr->masked_atomic_cap = IB_ATOMIC_HCA; 180 - } 177 + ib_attr->atomic_cap = IB_ATOMIC_NONE; 178 + ib_attr->masked_atomic_cap = IB_ATOMIC_NONE; 181 179 182 180 ib_attr->max_ee_rd_atom = 0; 183 181 ib_attr->max_res_rd_atom = 0; ··· 785 787 return 0; 786 788 } 787 789 790 + static unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp) 791 + __acquires(&qp->scq->cq_lock) __acquires(&qp->rcq->cq_lock) 792 + { 793 + unsigned long flags; 794 + 795 + spin_lock_irqsave(&qp->scq->cq_lock, flags); 796 + if (qp->rcq != qp->scq) 797 + spin_lock(&qp->rcq->cq_lock); 798 + else 799 + __acquire(&qp->rcq->cq_lock); 800 + 801 + return flags; 802 + } 803 + 804 + static void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, 805 + unsigned long flags) 806 + __releases(&qp->scq->cq_lock) __releases(&qp->rcq->cq_lock) 807 + { 808 + if (qp->rcq != qp->scq) 809 + spin_unlock(&qp->rcq->cq_lock); 810 + else 811 + __release(&qp->rcq->cq_lock); 812 + spin_unlock_irqrestore(&qp->scq->cq_lock, flags); 813 + } 814 + 788 815 /* Queue Pairs */ 789 816 int bnxt_re_destroy_qp(struct ib_qp *ib_qp) 790 817 { 791 818 struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp); 792 819 struct bnxt_re_dev *rdev = qp->rdev; 793 820 int rc; 821 + unsigned int flags; 794 822 795 823 bnxt_qplib_flush_cqn_wq(&qp->qplib_qp); 796 - bnxt_qplib_del_flush_qp(&qp->qplib_qp); 797 824 rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp); 798 825 if (rc) { 799 826 dev_err(rdev_to_dev(rdev), "Failed to destroy HW QP"); 800 827 return rc; 801 828 } 829 + 830 + flags = bnxt_re_lock_cqs(qp); 831 + bnxt_qplib_clean_qp(&qp->qplib_qp); 832 + bnxt_re_unlock_cqs(qp, flags); 833 + bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp); 834 + 802 835 if (ib_qp->qp_type == IB_QPT_GSI && rdev->qp1_sqp) { 803 836 rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, 804 837 &rdev->sqp_ah->qplib_ah); ··· 839 810 return rc; 840 811 } 841 812 842 - bnxt_qplib_del_flush_qp(&qp->qplib_qp); 813 + bnxt_qplib_clean_qp(&qp->qplib_qp); 843 814 rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, 844 815 &rdev->qp1_sqp->qplib_qp); 845 816 if (rc) { ··· 1098 1069 goto fail; 1099 1070 } 1100 1071 qp->qplib_qp.scq = &cq->qplib_cq; 1072 + qp->scq = cq; 1101 1073 } 1102 1074 1103 1075 if (qp_init_attr->recv_cq) { ··· 1110 1080 goto fail; 1111 1081 } 1112 1082 qp->qplib_qp.rcq = &cq->qplib_cq; 1083 + qp->rcq = cq; 1113 1084 } 1114 1085 1115 1086 if (qp_init_attr->srq) { ··· 1216 1185 rc = bnxt_qplib_create_qp(&rdev->qplib_res, &qp->qplib_qp); 1217 1186 if (rc) { 1218 1187 dev_err(rdev_to_dev(rdev), "Failed to create HW QP"); 1219 - goto fail; 1188 + goto free_umem; 1220 1189 } 1221 1190 } 1222 1191 ··· 1244 1213 return &qp->ib_qp; 1245 1214 qp_destroy: 1246 1215 bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp); 1216 + free_umem: 1217 + if (udata) { 1218 + if (qp->rumem) 1219 + ib_umem_release(qp->rumem); 1220 + if (qp->sumem) 1221 + ib_umem_release(qp->sumem); 1222 + } 1247 1223 fail: 1248 1224 kfree(qp); 1249 1225 return ERR_PTR(rc); ··· 1641 1603 dev_dbg(rdev_to_dev(rdev), 1642 1604 "Move QP = %p out of flush list\n", 1643 1605 qp); 1644 - bnxt_qplib_del_flush_qp(&qp->qplib_qp); 1606 + bnxt_qplib_clean_qp(&qp->qplib_qp); 1645 1607 } 1646 1608 } 1647 1609 if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) {
+2
drivers/infiniband/hw/bnxt_re/ib_verbs.h
··· 89 89 /* QP1 */ 90 90 u32 send_psn; 91 91 struct ib_ud_header qp1_hdr; 92 + struct bnxt_re_cq *scq; 93 + struct bnxt_re_cq *rcq; 92 94 }; 93 95 94 96 struct bnxt_re_cq {
+8 -4
drivers/infiniband/hw/bnxt_re/main.c
··· 656 656 mutex_unlock(&bnxt_re_dev_lock); 657 657 658 658 synchronize_rcu(); 659 - flush_workqueue(bnxt_re_wq); 660 659 661 660 ib_dealloc_device(&rdev->ibdev); 662 661 /* rdev is gone */ ··· 1440 1441 break; 1441 1442 } 1442 1443 smp_mb__before_atomic(); 1443 - clear_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags); 1444 + atomic_dec(&rdev->sched_count); 1444 1445 kfree(re_work); 1445 1446 } 1446 1447 ··· 1502 1503 /* netdev notifier will call NETDEV_UNREGISTER again later since 1503 1504 * we are still holding the reference to the netdev 1504 1505 */ 1505 - if (test_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags)) 1506 + if (atomic_read(&rdev->sched_count) > 0) 1506 1507 goto exit; 1507 1508 bnxt_re_ib_unreg(rdev, false); 1508 1509 bnxt_re_remove_one(rdev); ··· 1522 1523 re_work->vlan_dev = (real_dev == netdev ? 1523 1524 NULL : netdev); 1524 1525 INIT_WORK(&re_work->work, bnxt_re_task); 1525 - set_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags); 1526 + atomic_inc(&rdev->sched_count); 1526 1527 queue_work(bnxt_re_wq, &re_work->work); 1527 1528 } 1528 1529 } ··· 1577 1578 */ 1578 1579 list_for_each_entry_safe_reverse(rdev, next, &to_be_deleted, list) { 1579 1580 dev_info(rdev_to_dev(rdev), "Unregistering Device"); 1581 + /* 1582 + * Flush out any scheduled tasks before destroying the 1583 + * resources 1584 + */ 1585 + flush_workqueue(bnxt_re_wq); 1580 1586 bnxt_re_dev_stop(rdev); 1581 1587 bnxt_re_ib_unreg(rdev, true); 1582 1588 bnxt_re_remove_one(rdev);
+6 -15
drivers/infiniband/hw/bnxt_re/qplib_fp.c
··· 173 173 } 174 174 } 175 175 176 - void bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp) 176 + void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp) 177 177 { 178 178 unsigned long flags; 179 179 ··· 1419 1419 struct bnxt_qplib_rcfw *rcfw = res->rcfw; 1420 1420 struct cmdq_destroy_qp req; 1421 1421 struct creq_destroy_qp_resp resp; 1422 - unsigned long flags; 1423 1422 u16 cmd_flags = 0; 1424 1423 int rc; 1425 1424 ··· 1436 1437 return rc; 1437 1438 } 1438 1439 1439 - /* Must walk the associated CQs to nullified the QP ptr */ 1440 - spin_lock_irqsave(&qp->scq->hwq.lock, flags); 1440 + return 0; 1441 + } 1441 1442 1442 - __clean_cq(qp->scq, (u64)(unsigned long)qp); 1443 - 1444 - if (qp->rcq && qp->rcq != qp->scq) { 1445 - spin_lock(&qp->rcq->hwq.lock); 1446 - __clean_cq(qp->rcq, (u64)(unsigned long)qp); 1447 - spin_unlock(&qp->rcq->hwq.lock); 1448 - } 1449 - 1450 - spin_unlock_irqrestore(&qp->scq->hwq.lock, flags); 1451 - 1443 + void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res, 1444 + struct bnxt_qplib_qp *qp) 1445 + { 1452 1446 bnxt_qplib_free_qp_hdr_buf(res, qp); 1453 1447 bnxt_qplib_free_hwq(res->pdev, &qp->sq.hwq); 1454 1448 kfree(qp->sq.swq); ··· 1454 1462 if (qp->orrq.max_elements) 1455 1463 bnxt_qplib_free_hwq(res->pdev, &qp->orrq); 1456 1464 1457 - return 0; 1458 1465 } 1459 1466 1460 1467 void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp,
+3 -1
drivers/infiniband/hw/bnxt_re/qplib_fp.h
··· 478 478 int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); 479 479 int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); 480 480 int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp); 481 + void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp); 482 + void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res, 483 + struct bnxt_qplib_qp *qp); 481 484 void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp, 482 485 struct bnxt_qplib_sge *sge); 483 486 void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp, ··· 503 500 void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq); 504 501 int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq); 505 502 void bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp); 506 - void bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp); 507 503 void bnxt_qplib_acquire_cq_locks(struct bnxt_qplib_qp *qp, 508 504 unsigned long *flags); 509 505 void bnxt_qplib_release_cq_locks(struct bnxt_qplib_qp *qp,
+1 -13
drivers/infiniband/hw/bnxt_re/qplib_sp.c
··· 52 52 53 53 /* Device */ 54 54 55 - static bool bnxt_qplib_is_atomic_cap(struct bnxt_qplib_rcfw *rcfw) 56 - { 57 - int rc; 58 - u16 pcie_ctl2; 59 - 60 - rc = pcie_capability_read_word(rcfw->pdev, PCI_EXP_DEVCTL2, 61 - &pcie_ctl2); 62 - if (rc) 63 - return false; 64 - return !!(pcie_ctl2 & PCI_EXP_DEVCTL2_ATOMIC_REQ); 65 - } 66 - 67 55 static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, 68 56 char *fw_ver) 69 57 { ··· 153 165 attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); 154 166 } 155 167 156 - attr->is_atomic = bnxt_qplib_is_atomic_cap(rcfw); 168 + attr->is_atomic = 0; 157 169 bail: 158 170 bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf); 159 171 return rc;
+3 -1
drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c
··· 114 114 union pvrdma_cmd_resp rsp; 115 115 struct pvrdma_cmd_create_cq *cmd = &req.create_cq; 116 116 struct pvrdma_cmd_create_cq_resp *resp = &rsp.create_cq_resp; 117 + struct pvrdma_create_cq_resp cq_resp = {0}; 117 118 struct pvrdma_create_cq ucmd; 118 119 119 120 BUILD_BUG_ON(sizeof(struct pvrdma_cqe) != 64); ··· 198 197 199 198 cq->ibcq.cqe = resp->cqe; 200 199 cq->cq_handle = resp->cq_handle; 200 + cq_resp.cqn = resp->cq_handle; 201 201 spin_lock_irqsave(&dev->cq_tbl_lock, flags); 202 202 dev->cq_tbl[cq->cq_handle % dev->dsr->caps.max_cq] = cq; 203 203 spin_unlock_irqrestore(&dev->cq_tbl_lock, flags); ··· 207 205 cq->uar = &(to_vucontext(context)->uar); 208 206 209 207 /* Copy udata back. */ 210 - if (ib_copy_to_udata(udata, &cq->cq_handle, sizeof(__u32))) { 208 + if (ib_copy_to_udata(udata, &cq_resp, sizeof(cq_resp))) { 211 209 dev_warn(&dev->pdev->dev, 212 210 "failed to copy back udata\n"); 213 211 pvrdma_destroy_cq(&cq->ibcq);
+3 -1
drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c
··· 113 113 union pvrdma_cmd_resp rsp; 114 114 struct pvrdma_cmd_create_srq *cmd = &req.create_srq; 115 115 struct pvrdma_cmd_create_srq_resp *resp = &rsp.create_srq_resp; 116 + struct pvrdma_create_srq_resp srq_resp = {0}; 116 117 struct pvrdma_create_srq ucmd; 117 118 unsigned long flags; 118 119 int ret; ··· 205 204 } 206 205 207 206 srq->srq_handle = resp->srqn; 207 + srq_resp.srqn = resp->srqn; 208 208 spin_lock_irqsave(&dev->srq_tbl_lock, flags); 209 209 dev->srq_tbl[srq->srq_handle % dev->dsr->caps.max_srq] = srq; 210 210 spin_unlock_irqrestore(&dev->srq_tbl_lock, flags); 211 211 212 212 /* Copy udata back. */ 213 - if (ib_copy_to_udata(udata, &srq->srq_handle, sizeof(__u32))) { 213 + if (ib_copy_to_udata(udata, &srq_resp, sizeof(srq_resp))) { 214 214 dev_warn(&dev->pdev->dev, "failed to copy back udata\n"); 215 215 pvrdma_destroy_srq(&srq->ibsrq); 216 216 return ERR_PTR(-EINVAL);
+3 -1
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
··· 447 447 union pvrdma_cmd_resp rsp; 448 448 struct pvrdma_cmd_create_pd *cmd = &req.create_pd; 449 449 struct pvrdma_cmd_create_pd_resp *resp = &rsp.create_pd_resp; 450 + struct pvrdma_alloc_pd_resp pd_resp = {0}; 450 451 int ret; 451 452 void *ptr; 452 453 ··· 476 475 pd->privileged = !context; 477 476 pd->pd_handle = resp->pd_handle; 478 477 pd->pdn = resp->pd_handle; 478 + pd_resp.pdn = resp->pd_handle; 479 479 480 480 if (context) { 481 - if (ib_copy_to_udata(udata, &pd->pdn, sizeof(__u32))) { 481 + if (ib_copy_to_udata(udata, &pd_resp, sizeof(pd_resp))) { 482 482 dev_warn(&dev->pdev->dev, 483 483 "failed to copy back protection domain\n"); 484 484 pvrdma_dealloc_pd(&pd->ibpd);
-2
drivers/infiniband/ulp/ipoib/ipoib_fs.c
··· 281 281 { 282 282 struct ipoib_dev_priv *priv = ipoib_priv(dev); 283 283 284 - WARN_ONCE(!priv->mcg_dentry, "null mcg debug file\n"); 285 - WARN_ONCE(!priv->path_dentry, "null path debug file\n"); 286 284 debugfs_remove(priv->mcg_dentry); 287 285 debugfs_remove(priv->path_dentry); 288 286 priv->mcg_dentry = priv->path_dentry = NULL;
-4
include/rdma/restrack.h
··· 29 29 */ 30 30 RDMA_RESTRACK_QP, 31 31 /** 32 - * @RDMA_RESTRACK_XRCD: XRC domain (XRCD) 33 - */ 34 - RDMA_RESTRACK_XRCD, 35 - /** 36 32 * @RDMA_RESTRACK_MAX: Last entry, used for array dclarations 37 33 */ 38 34 RDMA_RESTRACK_MAX
+31 -12
include/rdma/uverbs_ioctl.h
··· 276 276 */ 277 277 278 278 struct uverbs_ptr_attr { 279 - union { 280 - u64 data; 281 - void __user *ptr; 282 - }; 279 + u64 data; 283 280 u16 len; 284 281 /* Combination of bits from enum UVERBS_ATTR_F_XXXX */ 285 282 u16 flags; ··· 348 351 } 349 352 350 353 static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, 351 - size_t idx, const void *from) 354 + size_t idx, const void *from, size_t size) 352 355 { 353 356 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx); 354 357 u16 flags; 358 + size_t min_size; 355 359 356 360 if (IS_ERR(attr)) 357 361 return PTR_ERR(attr); 358 362 363 + min_size = min_t(size_t, attr->ptr_attr.len, size); 364 + if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) 365 + return -EFAULT; 366 + 359 367 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT; 360 - return (!copy_to_user(attr->ptr_attr.ptr, from, attr->ptr_attr.len) && 361 - !put_user(flags, &attr->uattr->flags)) ? 0 : -EFAULT; 368 + if (put_user(flags, &attr->uattr->flags)) 369 + return -EFAULT; 370 + 371 + return 0; 362 372 } 363 373 364 - static inline int _uverbs_copy_from(void *to, size_t to_size, 374 + static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr) 375 + { 376 + return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data); 377 + } 378 + 379 + static inline int _uverbs_copy_from(void *to, 365 380 const struct uverbs_attr_bundle *attrs_bundle, 366 - size_t idx) 381 + size_t idx, 382 + size_t size) 367 383 { 368 384 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx); 369 385 370 386 if (IS_ERR(attr)) 371 387 return PTR_ERR(attr); 372 388 373 - if (to_size <= sizeof(((struct ib_uverbs_attr *)0)->data)) 389 + /* 390 + * Validation ensures attr->ptr_attr.len >= size. If the caller is 391 + * using UVERBS_ATTR_SPEC_F_MIN_SZ then it must call copy_from with 392 + * the right size. 393 + */ 394 + if (unlikely(size < attr->ptr_attr.len)) 395 + return -EINVAL; 396 + 397 + if (uverbs_attr_ptr_is_inline(attr)) 374 398 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len); 375 - else if (copy_from_user(to, attr->ptr_attr.ptr, attr->ptr_attr.len)) 399 + else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data), 400 + attr->ptr_attr.len)) 376 401 return -EFAULT; 377 402 378 403 return 0; 379 404 } 380 405 381 406 #define uverbs_copy_from(to, attrs_bundle, idx) \ 382 - _uverbs_copy_from(to, sizeof(*(to)), attrs_bundle, idx) 407 + _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to)) 383 408 384 409 /* ================================================= 385 410 * Definitions -> Specs infrastructure
+2 -2
include/uapi/rdma/rdma_user_ioctl.h
··· 65 65 __u16 len; /* only for pointers */ 66 66 __u16 flags; /* combination of UVERBS_ATTR_F_XXXX */ 67 67 __u16 reserved; 68 - __u64 data; /* ptr to command, inline data or idr/fd */ 68 + __aligned_u64 data; /* ptr to command, inline data or idr/fd */ 69 69 }; 70 70 71 71 struct ib_uverbs_ioctl_hdr { ··· 73 73 __u16 object_id; 74 74 __u16 method_id; 75 75 __u16 num_attrs; 76 - __u64 reserved; 76 + __aligned_u64 reserved; 77 77 struct ib_uverbs_attr attrs[0]; 78 78 }; 79 79