include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / infiniband / core / uverbs_cmd.c
index bdf5d50..6fcfbeb 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.
  *
  * 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>
 #include <linux/fs.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 
 #include "uverbs.h"
 
+static struct lock_class_key pd_lock_key;
+static struct lock_class_key mr_lock_key;
+static struct lock_class_key cq_lock_key;
+static struct lock_class_key qp_lock_key;
+static struct lock_class_key ah_lock_key;
+static struct lock_class_key srq_lock_key;
+
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
        do {                                                            \
                (udata)->inbuf  = (void __user *) (ibuf);               \
  */
 
 static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
-                     struct ib_ucontext *context)
+                     struct ib_ucontext *context, struct lock_class_key *key)
 {
        uobj->user_handle = user_handle;
        uobj->context     = context;
        kref_init(&uobj->ref);
        init_rwsem(&uobj->mutex);
+       lockdep_set_class(&uobj->mutex, key);
        uobj->live        = 0;
 }
 
@@ -139,15 +146,19 @@ 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;
 }
 
 static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
-                                       struct ib_ucontext *context)
+                                       struct ib_ucontext *context, int nested)
 {
        struct ib_uobject *uobj;
 
@@ -155,7 +166,10 @@ static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
        if (!uobj)
                return NULL;
 
-       down_read(&uobj->mutex);
+       if (nested)
+               down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING);
+       else
+               down_read(&uobj->mutex);
        if (!uobj->live) {
                put_uobj_read(uobj);
                return NULL;
@@ -182,17 +196,18 @@ static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
        return uobj;
 }
 
-static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context)
+static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context,
+                         int nested)
 {
        struct ib_uobject *uobj;
 
-       uobj = idr_read_uobj(idr, id, context);
+       uobj = idr_read_uobj(idr, id, context, nested);
        return uobj ? uobj->object : NULL;
 }
 
 static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
 {
-       return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context);
+       return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0);
 }
 
 static void put_pd_read(struct ib_pd *pd)
@@ -200,9 +215,9 @@ static void put_pd_read(struct ib_pd *pd)
        put_uobj_read(pd->uobject);
 }
 
-static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context)
+static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested)
 {
-       return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context);
+       return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested);
 }
 
 static void put_cq_read(struct ib_cq *cq)
@@ -212,7 +227,7 @@ static void put_cq_read(struct ib_cq *cq)
 
 static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
 {
-       return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context);
+       return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0);
 }
 
 static void put_ah_read(struct ib_ah *ah)
@@ -222,7 +237,7 @@ static void put_ah_read(struct ib_ah *ah)
 
 static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
 {
-       return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context);
+       return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
 }
 
 static void put_qp_read(struct ib_qp *qp)
@@ -232,7 +247,7 @@ static void put_qp_read(struct ib_qp *qp)
 
 static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
 {
-       return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context);
+       return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
 }
 
 static void put_srq_read(struct ib_srq *srq)
@@ -271,7 +286,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 
        ucontext = ibdev->alloc_ucontext(ibdev, &udata);
        if (IS_ERR(ucontext)) {
-               ret = PTR_ERR(file->ucontext);
+               ret = PTR_ERR(ucontext);
                goto err;
        }
 
@@ -283,13 +298,19 @@ 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;
 
-       filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
+       ret = get_unused_fd();
+       if (ret < 0)
+               goto err_free;
+       resp.async_fd = ret;
+
+       filp = ib_uverbs_alloc_event_file(file, 1);
        if (IS_ERR(filp)) {
                ret = PTR_ERR(filp);
-               goto err_free;
+               goto err_fd;
        }
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -317,9 +338,11 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        return in_len;
 
 err_file:
-       put_unused_fd(resp.async_fd);
        fput(filp);
 
+err_fd:
+       put_unused_fd(resp.async_fd);
+
 err_free:
        ibdev->dealloc_ucontext(ucontext);
 
@@ -470,7 +493,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
        if (!uobj)
                return -ENOMEM;
 
-       init_uobj(uobj, 0, file->ucontext);
+       init_uobj(uobj, 0, file->ucontext, &pd_lock_key);
        down_write(&uobj->mutex);
 
        pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
@@ -561,7 +584,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;
@@ -587,33 +610,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);
-       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)
-               goto err_release;
+       if (!pd) {
+               ret = -EINVAL;
+               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;
@@ -621,19 +632,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)) {
@@ -644,17 +655,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);
@@ -662,11 +673,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;
 }
 
@@ -677,7 +685,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))
@@ -687,8 +694,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)
@@ -705,8 +711,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;
@@ -719,6 +723,7 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
        struct ib_uverbs_create_comp_channel       cmd;
        struct ib_uverbs_create_comp_channel_resp  resp;
        struct file                               *filp;
+       int ret;
 
        if (out_len < sizeof resp)
                return -ENOSPC;
@@ -726,9 +731,16 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
-       if (IS_ERR(filp))
+       ret = get_unused_fd();
+       if (ret < 0)
+               return ret;
+       resp.fd = ret;
+
+       filp = ib_uverbs_alloc_event_file(file, 0);
+       if (IS_ERR(filp)) {
+               put_unused_fd(resp.fd);
                return PTR_ERR(filp);
+       }
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -770,7 +782,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        if (!obj)
                return -ENOMEM;
 
-       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &cq_lock_key);
        down_write(&obj->uobject.mutex);
 
        if (cmd.comp_channel >= 0) {
@@ -788,6 +800,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);
@@ -829,7 +842,6 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
 err_copy:
        idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
 
-
 err_free:
        ib_destroy_cq(cq);
 
@@ -859,7 +871,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       cq = idr_read_cq(cmd.cq_handle, file->ucontext);
+       cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
        if (!cq)
                return -EINVAL;
 
@@ -867,11 +879,10 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
        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))
+                        &resp, sizeof resp.cqe))
                ret = -EFAULT;
 
 out:
@@ -886,7 +897,6 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_poll_cq       cmd;
        struct ib_uverbs_poll_cq_resp *resp;
-       struct ib_uobject             *uobj;
        struct ib_cq                  *cq;
        struct ib_wc                  *wc;
        int                            ret = 0;
@@ -907,16 +917,15 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                goto out_wc;
        }
 
-       uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
-       if (!uobj) {
+       cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
+       if (!cq) {
                ret = -EINVAL;
                goto out;
        }
-       cq = uobj->object;
 
        resp->count = ib_poll_cq(cq, cmd.ne, wc);
 
-       put_uobj_read(uobj);
+       put_cq_read(cq);
 
        for (i = 0; i < resp->count; i++) {
                resp->wc[i].wr_id          = wc[i].wr_id;
@@ -924,8 +933,8 @@ 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].qp_num         = wc[i].qp_num;
+               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;
@@ -951,21 +960,19 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
                                int out_len)
 {
        struct ib_uverbs_req_notify_cq cmd;
-       struct ib_uobject             *uobj;
        struct ib_cq                  *cq;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
-       if (!uobj)
+       cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
+       if (!cq)
                return -EINVAL;
-       cq = uobj->object;
 
        ib_req_notify_cq(cq, cmd.solicited_only ?
                         IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
 
-       put_uobj_read(uobj);
+       put_cq_read(cq);
 
        return in_len;
 }
@@ -1051,13 +1058,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        if (!obj)
                return -ENOMEM;
 
-       init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext);
+       init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
        down_write(&obj->uevent.uobject.mutex);
 
-       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
-       scq = idr_read_cq(cmd.send_cq_handle, file->ucontext);
-       rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext);
        srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
+       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+       scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
+       rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
+               scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
 
        if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
                ret = -EINVAL;
@@ -1071,6 +1079,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;
@@ -1125,7 +1134,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
 
        put_pd_read(pd);
        put_cq_read(scq);
-       put_cq_read(rcq);
+       if (rcq != scq)
+               put_cq_read(rcq);
        if (srq)
                put_srq_read(srq);
 
@@ -1150,7 +1160,7 @@ err_put:
                put_pd_read(pd);
        if (scq)
                put_cq_read(scq);
-       if (rcq)
+       if (rcq && rcq != scq)
                put_cq_read(rcq);
        if (srq)
                put_srq_read(srq);
@@ -1206,7 +1216,7 @@ ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
        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.sq_draining            = attr->sq_draining;
        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;
@@ -1264,6 +1274,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
                            int out_len)
 {
        struct ib_uverbs_modify_qp cmd;
+       struct ib_udata            udata;
        struct ib_qp              *qp;
        struct ib_qp_attr         *attr;
        int                        ret;
@@ -1271,6 +1282,9 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
+       INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
+                  out_len);
+
        attr = kmalloc(sizeof *attr, GFP_KERNEL);
        if (!attr)
                return -ENOMEM;
@@ -1327,7 +1341,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        attr->alt_ah_attr.ah_flags          = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
        attr->alt_ah_attr.port_num          = cmd.alt_dest.port_num;
 
-       ret = ib_modify_qp(qp, attr, cmd.attr_mask);
+       ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
 
        put_qp_read(qp);
 
@@ -1463,7 +1477,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,
@@ -1476,14 +1489,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 =
@@ -1664,7 +1687,6 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
                                break;
                }
 
-
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
                ret = -EFAULT;
@@ -1714,7 +1736,6 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
                                break;
                }
 
-
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
                ret = -EFAULT;
@@ -1751,7 +1772,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
        if (!uobj)
                return -ENOMEM;
 
-       init_uobj(uobj, cmd.user_handle, file->ucontext);
+       init_uobj(uobj, cmd.user_handle, file->ucontext, &ah_lock_key);
        down_write(&uobj->mutex);
 
        pd = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -1775,7 +1796,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
        ah = ib_create_ah(pd, &attr);
        if (IS_ERR(ah)) {
                ret = PTR_ERR(ah);
-               goto err;
+               goto err_put;
        }
 
        ah->uobject  = uobj;
@@ -1811,6 +1832,9 @@ err_copy:
 err_destroy:
        ib_destroy_ah(ah);
 
+err_put:
+       put_pd_read(pd);
+
 err:
        put_uobj_write(uobj);
        return ret;
@@ -1963,7 +1987,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        if (!obj)
                return -ENOMEM;
 
-       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
        down_write(&obj->uobject.mutex);
 
        pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
@@ -1984,7 +2008,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        srq = pd->device->create_srq(pd, &attr, &udata);
        if (IS_ERR(srq)) {
                ret = PTR_ERR(srq);
-               goto err;
+               goto err_put;
        }
 
        srq->device        = pd->device;
@@ -2029,6 +2053,9 @@ err_copy:
 err_destroy:
        ib_destroy_srq(srq);
 
+err_put:
+       put_pd_read(pd);
+
 err:
        put_uobj_write(&obj->uobject);
        return ret;
@@ -2039,6 +2066,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
                             int out_len)
 {
        struct ib_uverbs_modify_srq cmd;
+       struct ib_udata             udata;
        struct ib_srq              *srq;
        struct ib_srq_attr          attr;
        int                         ret;
@@ -2046,6 +2074,9 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
+       INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
+                  out_len);
+
        srq = idr_read_srq(cmd.srq_handle, file->ucontext);
        if (!srq)
                return -EINVAL;
@@ -2053,7 +2084,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
        attr.max_wr    = cmd.max_wr;
        attr.srq_limit = cmd.srq_limit;
 
-       ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
+       ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata);
 
        put_srq_read(srq);