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 branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
IB/uverbs: Handle large number of entries in poll CQ

+59 -46
+59 -46
drivers/infiniband/core/uverbs_cmd.c
··· 893 893 return ret ? ret : in_len; 894 894 } 895 895 896 + static int copy_wc_to_user(void __user *dest, struct ib_wc *wc) 897 + { 898 + struct ib_uverbs_wc tmp; 899 + 900 + tmp.wr_id = wc->wr_id; 901 + tmp.status = wc->status; 902 + tmp.opcode = wc->opcode; 903 + tmp.vendor_err = wc->vendor_err; 904 + tmp.byte_len = wc->byte_len; 905 + tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data; 906 + tmp.qp_num = wc->qp->qp_num; 907 + tmp.src_qp = wc->src_qp; 908 + tmp.wc_flags = wc->wc_flags; 909 + tmp.pkey_index = wc->pkey_index; 910 + tmp.slid = wc->slid; 911 + tmp.sl = wc->sl; 912 + tmp.dlid_path_bits = wc->dlid_path_bits; 913 + tmp.port_num = wc->port_num; 914 + tmp.reserved = 0; 915 + 916 + if (copy_to_user(dest, &tmp, sizeof tmp)) 917 + return -EFAULT; 918 + 919 + return 0; 920 + } 921 + 896 922 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, 897 923 const char __user *buf, int in_len, 898 924 int out_len) 899 925 { 900 926 struct ib_uverbs_poll_cq cmd; 901 - struct ib_uverbs_poll_cq_resp *resp; 927 + struct ib_uverbs_poll_cq_resp resp; 928 + u8 __user *header_ptr; 929 + u8 __user *data_ptr; 902 930 struct ib_cq *cq; 903 - struct ib_wc *wc; 904 - int ret = 0; 905 - int i; 906 - int rsize; 931 + struct ib_wc wc; 932 + int ret; 907 933 908 934 if (copy_from_user(&cmd, buf, sizeof cmd)) 909 935 return -EFAULT; 910 936 911 - wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL); 912 - if (!wc) 913 - return -ENOMEM; 914 - 915 - rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc); 916 - resp = kmalloc(rsize, GFP_KERNEL); 917 - if (!resp) { 918 - ret = -ENOMEM; 919 - goto out_wc; 920 - } 921 - 922 937 cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); 923 - if (!cq) { 924 - ret = -EINVAL; 925 - goto out; 938 + if (!cq) 939 + return -EINVAL; 940 + 941 + /* we copy a struct ib_uverbs_poll_cq_resp to user space */ 942 + header_ptr = (void __user *)(unsigned long) cmd.response; 943 + data_ptr = header_ptr + sizeof resp; 944 + 945 + memset(&resp, 0, sizeof resp); 946 + while (resp.count < cmd.ne) { 947 + ret = ib_poll_cq(cq, 1, &wc); 948 + if (ret < 0) 949 + goto out_put; 950 + if (!ret) 951 + break; 952 + 953 + ret = copy_wc_to_user(data_ptr, &wc); 954 + if (ret) 955 + goto out_put; 956 + 957 + data_ptr += sizeof(struct ib_uverbs_wc); 958 + ++resp.count; 926 959 } 927 960 928 - resp->count = ib_poll_cq(cq, cmd.ne, wc); 929 - 930 - put_cq_read(cq); 931 - 932 - for (i = 0; i < resp->count; i++) { 933 - resp->wc[i].wr_id = wc[i].wr_id; 934 - resp->wc[i].status = wc[i].status; 935 - resp->wc[i].opcode = wc[i].opcode; 936 - resp->wc[i].vendor_err = wc[i].vendor_err; 937 - resp->wc[i].byte_len = wc[i].byte_len; 938 - resp->wc[i].ex.imm_data = (__u32 __force) wc[i].ex.imm_data; 939 - resp->wc[i].qp_num = wc[i].qp->qp_num; 940 - resp->wc[i].src_qp = wc[i].src_qp; 941 - resp->wc[i].wc_flags = wc[i].wc_flags; 942 - resp->wc[i].pkey_index = wc[i].pkey_index; 943 - resp->wc[i].slid = wc[i].slid; 944 - resp->wc[i].sl = wc[i].sl; 945 - resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits; 946 - resp->wc[i].port_num = wc[i].port_num; 947 - } 948 - 949 - if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize)) 961 + if (copy_to_user(header_ptr, &resp, sizeof resp)) { 950 962 ret = -EFAULT; 963 + goto out_put; 964 + } 951 965 952 - out: 953 - kfree(resp); 966 + ret = in_len; 954 967 955 - out_wc: 956 - kfree(wc); 957 - return ret ? ret : in_len; 968 + out_put: 969 + put_cq_read(cq); 970 + return ret; 958 971 } 959 972 960 973 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,