Merge branch 'core/topology' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
[pandora-kernel.git] / drivers / infiniband / core / uverbs_cmd.c
index 4fd75af..56feab6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
- * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ * Copyright (c) 2005, 2006, 2007 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 PathScale, Inc.  All rights reserved.
  * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.
  *
@@ -31,8 +31,6 @@
  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
- *
- * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
  */
 
 #include <linux/file.h>
@@ -147,8 +145,12 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
 
        spin_lock(&ib_uverbs_idr_lock);
        uobj = idr_find(idr, id);
-       if (uobj)
-               kref_get(&uobj->ref);
+       if (uobj) {
+               if (uobj->context == context)
+                       kref_get(&uobj->ref);
+               else
+                       uobj = NULL;
+       }
        spin_unlock(&ib_uverbs_idr_lock);
 
        return uobj;
@@ -295,6 +297,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        INIT_LIST_HEAD(&ucontext->qp_list);
        INIT_LIST_HEAD(&ucontext->srq_list);
        INIT_LIST_HEAD(&ucontext->ah_list);
+       ucontext->closing = 0;
 
        resp.num_comp_vectors = file->device->num_comp_vectors;
 
@@ -573,7 +576,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        struct ib_uverbs_reg_mr      cmd;
        struct ib_uverbs_reg_mr_resp resp;
        struct ib_udata              udata;
-       struct ib_umem_object       *obj;
+       struct ib_uobject           *uobj;
        struct ib_pd                *pd;
        struct ib_mr                *mr;
        int                          ret;
@@ -599,35 +602,21 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
            !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
                return -EINVAL;
 
-       obj = kmalloc(sizeof *obj, GFP_KERNEL);
-       if (!obj)
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
                return -ENOMEM;
 
-       init_uobj(&obj->uobject, 0, file->ucontext, &mr_lock_key);
-       down_write(&obj->uobject.mutex);
-
-       /*
-        * We ask for writable memory if any access flags other than
-        * "remote read" are set.  "Local write" and "remote write"
-        * obviously require write access.  "Remote atomic" can do
-        * things like fetch and add, which will modify memory, and
-        * "MW bind" can change permissions by binding a window.
-        */
-       ret = ib_umem_get(file->device->ib_dev, &obj->umem,
-                         (void *) (unsigned long) cmd.start, cmd.length,
-                         !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ));
-       if (ret)
-               goto err_free;
-
-       obj->umem.virt_base = cmd.hca_va;
+       init_uobj(uobj, 0, file->ucontext, &mr_lock_key);
+       down_write(&uobj->mutex);
 
        pd = idr_read_pd(cmd.pd_handle, file->ucontext);
        if (!pd) {
                ret = -EINVAL;
-               goto err_release;
+               goto err_free;
        }
 
-       mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
+       mr = pd->device->reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va,
+                                    cmd.access_flags, &udata);
        if (IS_ERR(mr)) {
                ret = PTR_ERR(mr);
                goto err_put;
@@ -635,19 +624,19 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 
        mr->device  = pd->device;
        mr->pd      = pd;
-       mr->uobject = &obj->uobject;
+       mr->uobject = uobj;
        atomic_inc(&pd->usecnt);
        atomic_set(&mr->usecnt, 0);
 
-       obj->uobject.object = mr;
-       ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject);
+       uobj->object = mr;
+       ret = idr_add_uobj(&ib_uverbs_mr_idr, uobj);
        if (ret)
                goto err_unreg;
 
        memset(&resp, 0, sizeof resp);
        resp.lkey      = mr->lkey;
        resp.rkey      = mr->rkey;
-       resp.mr_handle = obj->uobject.id;
+       resp.mr_handle = uobj->id;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -658,17 +647,17 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        put_pd_read(pd);
 
        mutex_lock(&file->mutex);
-       list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
+       list_add_tail(&uobj->list, &file->ucontext->mr_list);
        mutex_unlock(&file->mutex);
 
-       obj->uobject.live = 1;
+       uobj->live = 1;
 
-       up_write(&obj->uobject.mutex);
+       up_write(&uobj->mutex);
 
        return in_len;
 
 err_copy:
-       idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject);
+       idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
 
 err_unreg:
        ib_dereg_mr(mr);
@@ -676,11 +665,8 @@ err_unreg:
 err_put:
        put_pd_read(pd);
 
-err_release:
-       ib_umem_release(file->device->ib_dev, &obj->umem);
-
 err_free:
-       put_uobj_write(&obj->uobject);
+       put_uobj_write(uobj);
        return ret;
 }
 
@@ -691,7 +677,6 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
        struct ib_uverbs_dereg_mr cmd;
        struct ib_mr             *mr;
        struct ib_uobject        *uobj;
-       struct ib_umem_object    *memobj;
        int                       ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -701,8 +686,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
        if (!uobj)
                return -EINVAL;
 
-       memobj = container_of(uobj, struct ib_umem_object, uobject);
-       mr     = uobj->object;
+       mr = uobj->object;
 
        ret = ib_dereg_mr(mr);
        if (!ret)
@@ -719,8 +703,6 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
        list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       ib_umem_release(file->device->ib_dev, &memobj->umem);
-
        put_uobj(uobj);
 
        return in_len;
@@ -802,6 +784,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        INIT_LIST_HEAD(&obj->async_list);
 
        cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
+                                            cmd.comp_vector,
                                             file->ucontext, &udata);
        if (IS_ERR(cq)) {
                ret = PTR_ERR(cq);
@@ -934,7 +917,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                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].imm_data       = (__u32 __force) wc[i].imm_data;
+               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;
@@ -1080,6 +1063,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        attr.srq           = srq;
        attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
        attr.qp_type       = cmd.qp_type;
+       attr.create_flags  = 0;
 
        attr.cap.max_send_wr     = cmd.max_send_wr;
        attr.cap.max_recv_wr     = cmd.max_recv_wr;
@@ -1477,7 +1461,6 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                next->num_sge    = user_wr->num_sge;
                next->opcode     = user_wr->opcode;
                next->send_flags = user_wr->send_flags;
-               next->imm_data   = (__be32 __force) user_wr->imm_data;
 
                if (is_ud) {
                        next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
@@ -1490,14 +1473,24 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                        next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
                } else {
                        switch (next->opcode) {
-                       case IB_WR_RDMA_WRITE:
                        case IB_WR_RDMA_WRITE_WITH_IMM:
+                               next->ex.imm_data =
+                                       (__be32 __force) user_wr->ex.imm_data;
+                       case IB_WR_RDMA_WRITE:
                        case IB_WR_RDMA_READ:
                                next->wr.rdma.remote_addr =
                                        user_wr->wr.rdma.remote_addr;
                                next->wr.rdma.rkey        =
                                        user_wr->wr.rdma.rkey;
                                break;
+                       case IB_WR_SEND_WITH_IMM:
+                               next->ex.imm_data =
+                                       (__be32 __force) user_wr->ex.imm_data;
+                               break;
+                       case IB_WR_SEND_WITH_INV:
+                               next->ex.invalidate_rkey =
+                                       user_wr->ex.invalidate_rkey;
+                               break;
                        case IB_WR_ATOMIC_CMP_AND_SWP:
                        case IB_WR_ATOMIC_FETCH_AND_ADD:
                                next->wr.atomic.remote_addr =