diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 99 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 2 |
2 files changed, 57 insertions, 44 deletions
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 6fcfbeb24a23..abb87140f29f 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -891,68 +891,81 @@ out: | |||
891 | return ret ? ret : in_len; | 891 | return ret ? ret : in_len; |
892 | } | 892 | } |
893 | 893 | ||
894 | static int copy_wc_to_user(void __user *dest, struct ib_wc *wc) | ||
895 | { | ||
896 | struct ib_uverbs_wc tmp; | ||
897 | |||
898 | tmp.wr_id = wc->wr_id; | ||
899 | tmp.status = wc->status; | ||
900 | tmp.opcode = wc->opcode; | ||
901 | tmp.vendor_err = wc->vendor_err; | ||
902 | tmp.byte_len = wc->byte_len; | ||
903 | tmp.ex.imm_data = (__u32 __force) wc->ex.imm_data; | ||
904 | tmp.qp_num = wc->qp->qp_num; | ||
905 | tmp.src_qp = wc->src_qp; | ||
906 | tmp.wc_flags = wc->wc_flags; | ||
907 | tmp.pkey_index = wc->pkey_index; | ||
908 | tmp.slid = wc->slid; | ||
909 | tmp.sl = wc->sl; | ||
910 | tmp.dlid_path_bits = wc->dlid_path_bits; | ||
911 | tmp.port_num = wc->port_num; | ||
912 | tmp.reserved = 0; | ||
913 | |||
914 | if (copy_to_user(dest, &tmp, sizeof tmp)) | ||
915 | return -EFAULT; | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | |||
894 | ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | 920 | ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, |
895 | const char __user *buf, int in_len, | 921 | const char __user *buf, int in_len, |
896 | int out_len) | 922 | int out_len) |
897 | { | 923 | { |
898 | struct ib_uverbs_poll_cq cmd; | 924 | struct ib_uverbs_poll_cq cmd; |
899 | struct ib_uverbs_poll_cq_resp *resp; | 925 | struct ib_uverbs_poll_cq_resp resp; |
926 | u8 __user *header_ptr; | ||
927 | u8 __user *data_ptr; | ||
900 | struct ib_cq *cq; | 928 | struct ib_cq *cq; |
901 | struct ib_wc *wc; | 929 | struct ib_wc wc; |
902 | int ret = 0; | 930 | int ret; |
903 | int i; | ||
904 | int rsize; | ||
905 | 931 | ||
906 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 932 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
907 | return -EFAULT; | 933 | return -EFAULT; |
908 | 934 | ||
909 | wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL); | ||
910 | if (!wc) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc); | ||
914 | resp = kmalloc(rsize, GFP_KERNEL); | ||
915 | if (!resp) { | ||
916 | ret = -ENOMEM; | ||
917 | goto out_wc; | ||
918 | } | ||
919 | |||
920 | cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); | 935 | cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); |
921 | if (!cq) { | 936 | if (!cq) |
922 | ret = -EINVAL; | 937 | return -EINVAL; |
923 | goto out; | ||
924 | } | ||
925 | 938 | ||
926 | resp->count = ib_poll_cq(cq, cmd.ne, wc); | 939 | /* we copy a struct ib_uverbs_poll_cq_resp to user space */ |
940 | header_ptr = (void __user *)(unsigned long) cmd.response; | ||
941 | data_ptr = header_ptr + sizeof resp; | ||
927 | 942 | ||
928 | put_cq_read(cq); | 943 | memset(&resp, 0, sizeof resp); |
944 | while (resp.count < cmd.ne) { | ||
945 | ret = ib_poll_cq(cq, 1, &wc); | ||
946 | if (ret < 0) | ||
947 | goto out_put; | ||
948 | if (!ret) | ||
949 | break; | ||
950 | |||
951 | ret = copy_wc_to_user(data_ptr, &wc); | ||
952 | if (ret) | ||
953 | goto out_put; | ||
929 | 954 | ||
930 | for (i = 0; i < resp->count; i++) { | 955 | data_ptr += sizeof(struct ib_uverbs_wc); |
931 | resp->wc[i].wr_id = wc[i].wr_id; | 956 | ++resp.count; |
932 | resp->wc[i].status = wc[i].status; | ||
933 | resp->wc[i].opcode = wc[i].opcode; | ||
934 | resp->wc[i].vendor_err = wc[i].vendor_err; | ||
935 | resp->wc[i].byte_len = wc[i].byte_len; | ||
936 | resp->wc[i].ex.imm_data = (__u32 __force) wc[i].ex.imm_data; | ||
937 | resp->wc[i].qp_num = wc[i].qp->qp_num; | ||
938 | resp->wc[i].src_qp = wc[i].src_qp; | ||
939 | resp->wc[i].wc_flags = wc[i].wc_flags; | ||
940 | resp->wc[i].pkey_index = wc[i].pkey_index; | ||
941 | resp->wc[i].slid = wc[i].slid; | ||
942 | resp->wc[i].sl = wc[i].sl; | ||
943 | resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits; | ||
944 | resp->wc[i].port_num = wc[i].port_num; | ||
945 | } | 957 | } |
946 | 958 | ||
947 | if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize)) | 959 | if (copy_to_user(header_ptr, &resp, sizeof resp)) { |
948 | ret = -EFAULT; | 960 | ret = -EFAULT; |
961 | goto out_put; | ||
962 | } | ||
949 | 963 | ||
950 | out: | 964 | ret = in_len; |
951 | kfree(resp); | ||
952 | 965 | ||
953 | out_wc: | 966 | out_put: |
954 | kfree(wc); | 967 | put_cq_read(cq); |
955 | return ret ? ret : in_len; | 968 | return ret; |
956 | } | 969 | } |
957 | 970 | ||
958 | ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, | 971 | ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, |
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 32d352a88d50..081d06110e33 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -383,7 +383,7 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) | |||
383 | 16)) | FW_WR_FLOWID(ep->hwtid)); | 383 | 16)) | FW_WR_FLOWID(ep->hwtid)); |
384 | 384 | ||
385 | flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; | 385 | flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN; |
386 | flowc->mnemval[0].val = cpu_to_be32(0); | 386 | flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8); |
387 | flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; | 387 | flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH; |
388 | flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); | 388 | flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan); |
389 | flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; | 389 | flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT; |