revert android-tegra-2.6.36-honeycomb-mr1-9001adc to v2.6.36
[firefly-linux-kernel-4.4.55.git] / drivers / infiniband / core / uverbs_cmd.c
index abb87140f29fdab445e87a897bbef91ef79cc1dc..6fcfbeb24a234a419ec9313c956c7c4ba581bcf6 100644 (file)
@@ -891,81 +891,68 @@ out:
        return ret ? ret : in_len;
 }
 
-static int copy_wc_to_user(void __user *dest, struct ib_wc *wc)
-{
-       struct ib_uverbs_wc tmp;
-
-       tmp.wr_id               = wc->wr_id;
-       tmp.status              = wc->status;
-       tmp.opcode              = wc->opcode;
-       tmp.vendor_err          = wc->vendor_err;
-       tmp.byte_len            = wc->byte_len;
-       tmp.ex.imm_data         = (__u32 __force) wc->ex.imm_data;
-       tmp.qp_num              = wc->qp->qp_num;
-       tmp.src_qp              = wc->src_qp;
-       tmp.wc_flags            = wc->wc_flags;
-       tmp.pkey_index          = wc->pkey_index;
-       tmp.slid                = wc->slid;
-       tmp.sl                  = wc->sl;
-       tmp.dlid_path_bits      = wc->dlid_path_bits;
-       tmp.port_num            = wc->port_num;
-       tmp.reserved            = 0;
-
-       if (copy_to_user(dest, &tmp, sizeof tmp))
-               return -EFAULT;
-
-       return 0;
-}
-
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
 {
        struct ib_uverbs_poll_cq       cmd;
-       struct ib_uverbs_poll_cq_resp  resp;
-       u8 __user                     *header_ptr;
-       u8 __user                     *data_ptr;
+       struct ib_uverbs_poll_cq_resp *resp;
        struct ib_cq                  *cq;
-       struct ib_wc                   wc;
-       int                            ret;
+       struct ib_wc                  *wc;
+       int                            ret = 0;
+       int                            i;
+       int                            rsize;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
-       if (!cq)
-               return -EINVAL;
+       wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);
+       if (!wc)
+               return -ENOMEM;
 
-       /* we copy a struct ib_uverbs_poll_cq_resp to user space */
-       header_ptr = (void __user *)(unsigned long) cmd.response;
-       data_ptr = header_ptr + sizeof resp;
+       rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);
+       resp = kmalloc(rsize, GFP_KERNEL);
+       if (!resp) {
+               ret = -ENOMEM;
+               goto out_wc;
+       }
 
-       memset(&resp, 0, sizeof resp);
-       while (resp.count < cmd.ne) {
-               ret = ib_poll_cq(cq, 1, &wc);
-               if (ret < 0)
-                       goto out_put;
-               if (!ret)
-                       break;
+       cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
+       if (!cq) {
+               ret = -EINVAL;
+               goto out;
+       }
 
-               ret = copy_wc_to_user(data_ptr, &wc);
-               if (ret)
-                       goto out_put;
+       resp->count = ib_poll_cq(cq, cmd.ne, wc);
+
+       put_cq_read(cq);
 
-               data_ptr += sizeof(struct ib_uverbs_wc);
-               ++resp.count;
+       for (i = 0; i < resp->count; i++) {
+               resp->wc[i].wr_id          = wc[i].wr_id;
+               resp->wc[i].status         = wc[i].status;
+               resp->wc[i].opcode         = wc[i].opcode;
+               resp->wc[i].vendor_err     = wc[i].vendor_err;
+               resp->wc[i].byte_len       = wc[i].byte_len;
+               resp->wc[i].ex.imm_data    = (__u32 __force) wc[i].ex.imm_data;
+               resp->wc[i].qp_num         = wc[i].qp->qp_num;
+               resp->wc[i].src_qp         = wc[i].src_qp;
+               resp->wc[i].wc_flags       = wc[i].wc_flags;
+               resp->wc[i].pkey_index     = wc[i].pkey_index;
+               resp->wc[i].slid           = wc[i].slid;
+               resp->wc[i].sl             = wc[i].sl;
+               resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;
+               resp->wc[i].port_num       = wc[i].port_num;
        }
 
-       if (copy_to_user(header_ptr, &resp, sizeof resp)) {
+       if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))
                ret = -EFAULT;
-               goto out_put;
-       }
 
-       ret = in_len;
+out:
+       kfree(resp);
 
-out_put:
-       put_cq_read(cq);
-       return ret;
+out_wc:
+       kfree(wc);
+       return ret ? ret : in_len;
 }
 
 ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,