aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c99
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c2
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
894static 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
894ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, 920ssize_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
950out: 964 ret = in_len;
951 kfree(resp);
952 965
953out_wc: 966out_put:
954 kfree(wc); 967 put_cq_read(cq);
955 return ret ? ret : in_len; 968 return ret;
956} 969}
957 970
958ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, 971ssize_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;