Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
[sfrench/cifs-2.6.git] / drivers / infiniband / core / uverbs_cmd.c
index 407b6284d7d5c502c88595f1f2820bf856aac1c8..9f69bd48eb1bee6ccf488f0e71a7777efd7f5f0d 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
+ * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -675,6 +676,46 @@ err:
        return ret;
 }
 
+ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_resize_cq      cmd;
+       struct ib_uverbs_resize_cq_resp resp;
+       struct ib_udata                 udata;
+       struct ib_cq                    *cq;
+       int                             ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       mutex_lock(&ib_uverbs_idr_mutex);
+
+       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+       if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq)
+               goto out;
+
+       ret = cq->device->resize_cq(cq, cmd.cqe, &udata);
+       if (ret)
+               goto out;
+
+       memset(&resp, 0, sizeof resp);
+       resp.cqe = cq->cqe;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       mutex_unlock(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
 ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                          const char __user *buf, int in_len,
                          int out_len)
@@ -956,6 +997,106 @@ err_up:
        return ret;
 }
 
+ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
+                          const char __user *buf, int in_len,
+                          int out_len)
+{
+       struct ib_uverbs_query_qp      cmd;
+       struct ib_uverbs_query_qp_resp resp;
+       struct ib_qp                   *qp;
+       struct ib_qp_attr              *attr;
+       struct ib_qp_init_attr         *init_attr;
+       int                            ret;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       attr      = kmalloc(sizeof *attr, GFP_KERNEL);
+       init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL);
+       if (!attr || !init_attr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       mutex_lock(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (qp && qp->uobject->context == file->ucontext)
+               ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
+       else
+               ret = -EINVAL;
+
+       mutex_unlock(&ib_uverbs_idr_mutex);
+
+       if (ret)
+               goto out;
+
+       memset(&resp, 0, sizeof resp);
+
+       resp.qp_state               = attr->qp_state;
+       resp.cur_qp_state           = attr->cur_qp_state;
+       resp.path_mtu               = attr->path_mtu;
+       resp.path_mig_state         = attr->path_mig_state;
+       resp.qkey                   = attr->qkey;
+       resp.rq_psn                 = attr->rq_psn;
+       resp.sq_psn                 = attr->sq_psn;
+       resp.dest_qp_num            = attr->dest_qp_num;
+       resp.qp_access_flags        = attr->qp_access_flags;
+       resp.pkey_index             = attr->pkey_index;
+       resp.alt_pkey_index         = attr->alt_pkey_index;
+       resp.en_sqd_async_notify    = attr->en_sqd_async_notify;
+       resp.max_rd_atomic          = attr->max_rd_atomic;
+       resp.max_dest_rd_atomic     = attr->max_dest_rd_atomic;
+       resp.min_rnr_timer          = attr->min_rnr_timer;
+       resp.port_num               = attr->port_num;
+       resp.timeout                = attr->timeout;
+       resp.retry_cnt              = attr->retry_cnt;
+       resp.rnr_retry              = attr->rnr_retry;
+       resp.alt_port_num           = attr->alt_port_num;
+       resp.alt_timeout            = attr->alt_timeout;
+
+       memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
+       resp.dest.flow_label        = attr->ah_attr.grh.flow_label;
+       resp.dest.sgid_index        = attr->ah_attr.grh.sgid_index;
+       resp.dest.hop_limit         = attr->ah_attr.grh.hop_limit;
+       resp.dest.traffic_class     = attr->ah_attr.grh.traffic_class;
+       resp.dest.dlid              = attr->ah_attr.dlid;
+       resp.dest.sl                = attr->ah_attr.sl;
+       resp.dest.src_path_bits     = attr->ah_attr.src_path_bits;
+       resp.dest.static_rate       = attr->ah_attr.static_rate;
+       resp.dest.is_global         = !!(attr->ah_attr.ah_flags & IB_AH_GRH);
+       resp.dest.port_num          = attr->ah_attr.port_num;
+
+       memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
+       resp.alt_dest.flow_label    = attr->alt_ah_attr.grh.flow_label;
+       resp.alt_dest.sgid_index    = attr->alt_ah_attr.grh.sgid_index;
+       resp.alt_dest.hop_limit     = attr->alt_ah_attr.grh.hop_limit;
+       resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
+       resp.alt_dest.dlid          = attr->alt_ah_attr.dlid;
+       resp.alt_dest.sl            = attr->alt_ah_attr.sl;
+       resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
+       resp.alt_dest.static_rate   = attr->alt_ah_attr.static_rate;
+       resp.alt_dest.is_global     = !!(attr->alt_ah_attr.ah_flags & IB_AH_GRH);
+       resp.alt_dest.port_num      = attr->alt_ah_attr.port_num;
+
+       resp.max_send_wr            = init_attr->cap.max_send_wr;
+       resp.max_recv_wr            = init_attr->cap.max_recv_wr;
+       resp.max_send_sge           = init_attr->cap.max_send_sge;
+       resp.max_recv_sge           = init_attr->cap.max_recv_sge;
+       resp.max_inline_data        = init_attr->cap.max_inline_data;
+       resp.sq_sig_all             = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       kfree(attr);
+       kfree(init_attr);
+
+       return ret ? ret : in_len;
+}
+
 ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
                            const char __user *buf, int in_len,
                            int out_len)
@@ -990,7 +1131,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        attr->dest_qp_num         = cmd.dest_qp_num;
        attr->qp_access_flags     = cmd.qp_access_flags;
        attr->pkey_index          = cmd.pkey_index;
-       attr->alt_pkey_index      = cmd.pkey_index;
+       attr->alt_pkey_index      = cmd.alt_pkey_index;
        attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
        attr->max_rd_atomic       = cmd.max_rd_atomic;
        attr->max_dest_rd_atomic  = cmd.max_dest_rd_atomic;
@@ -1094,8 +1235,8 @@ out:
 }
 
 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
-                            const char __user *buf, int in_len,
-                            int out_len)
+                           const char __user *buf, int in_len,
+                           int out_len)
 {
        struct ib_uverbs_post_send      cmd;
        struct ib_uverbs_post_send_resp resp;
@@ -1323,8 +1464,8 @@ err:
 }
 
 ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
-                            const char __user *buf, int in_len,
-                            int out_len)
+                           const char __user *buf, int in_len,
+                           int out_len)
 {
        struct ib_uverbs_post_recv      cmd;
        struct ib_uverbs_post_recv_resp resp;
@@ -1374,8 +1515,8 @@ out:
 }
 
 ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
-                            const char __user *buf, int in_len,
-                            int out_len)
+                               const char __user *buf, int in_len,
+                               int out_len)
 {
        struct ib_uverbs_post_srq_recv      cmd;
        struct ib_uverbs_post_srq_recv_resp resp;
@@ -1723,6 +1864,8 @@ retry:
                goto err_destroy;
 
        resp.srq_handle = uobj->uobject.id;
+       resp.max_wr     = attr.attr.max_wr;
+       resp.max_sge    = attr.attr.max_sge;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -1783,6 +1926,49 @@ out:
        return ret ? ret : in_len;
 }
 
+ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
+                           const char __user *buf,
+                           int in_len, int out_len)
+{
+       struct ib_uverbs_query_srq      cmd;
+       struct ib_uverbs_query_srq_resp resp;
+       struct ib_srq_attr              attr;
+       struct ib_srq                   *srq;
+       int                             ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       mutex_lock(&ib_uverbs_idr_mutex);
+
+       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+       if (srq && srq->uobject->context == file->ucontext)
+               ret = ib_query_srq(srq, &attr);
+       else
+               ret = -EINVAL;
+
+       mutex_unlock(&ib_uverbs_idr_mutex);
+
+       if (ret)
+               goto out;
+
+       memset(&resp, 0, sizeof resp);
+
+       resp.max_wr    = attr.max_wr;
+       resp.max_sge   = attr.max_sge;
+       resp.srq_limit = attr.srq_limit;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
+out:
+       return ret ? ret : in_len;
+}
+
 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
                              const char __user *buf, int in_len,
                              int out_len)