IB: remove in-kernel support for memory windows
[linux-2.6-block.git] / drivers / infiniband / core / uverbs_cmd.c
index 94816aeb95a0a186760fbe98de55edc69266a54c..5428ebee096f04347b5b13b18c19f17d372f509c 100644 (file)
@@ -62,9 +62,11 @@ static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
  * The ib_uobject locking scheme is as follows:
  *
  * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
- *   needs to be held during all idr operations.  When an object is
+ *   needs to be held during all idr write operations.  When an object is
  *   looked up, a reference must be taken on the object's kref before
- *   dropping this lock.
+ *   dropping this lock.  For read operations, the rcu_read_lock()
+ *   and rcu_write_lock() but similarly the kref reference is grabbed
+ *   before the rcu_read_unlock().
  *
  * - Each object also has an rwsem.  This rwsem must be held for
  *   reading while an operation that uses the object is performed.
@@ -96,7 +98,7 @@ static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
 
 static void release_uobj(struct kref *kref)
 {
-       kfree(container_of(kref, struct ib_uobject, ref));
+       kfree_rcu(container_of(kref, struct ib_uobject, ref), rcu);
 }
 
 static void put_uobj(struct ib_uobject *uobj)
@@ -145,7 +147,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
 {
        struct ib_uobject *uobj;
 
-       spin_lock(&ib_uverbs_idr_lock);
+       rcu_read_lock();
        uobj = idr_find(idr, id);
        if (uobj) {
                if (uobj->context == context)
@@ -153,7 +155,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
                else
                        uobj = NULL;
        }
-       spin_unlock(&ib_uverbs_idr_lock);
+       rcu_read_unlock();
 
        return uobj;
 }
@@ -289,9 +291,6 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        struct ib_uverbs_get_context      cmd;
        struct ib_uverbs_get_context_resp resp;
        struct ib_udata                   udata;
-#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
-       struct ib_device_attr             dev_attr;
-#endif
        struct ib_ucontext               *ucontext;
        struct file                      *filp;
        int ret;
@@ -340,10 +339,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        ucontext->odp_mrs_count = 0;
        INIT_LIST_HEAD(&ucontext->no_private_counters);
 
-       ret = ib_query_device(ib_dev, &dev_attr);
-       if (ret)
-               goto err_free;
-       if (!(dev_attr.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
+       if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
                ucontext->invalidate_range = NULL;
 
 #endif
@@ -445,8 +441,6 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_query_device      cmd;
        struct ib_uverbs_query_device_resp resp;
-       struct ib_device_attr              attr;
-       int                                ret;
 
        if (out_len < sizeof resp)
                return -ENOSPC;
@@ -454,12 +448,8 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       ret = ib_query_device(ib_dev, &attr);
-       if (ret)
-               return ret;
-
        memset(&resp, 0, sizeof resp);
-       copy_query_dev_fields(file, ib_dev, &resp, &attr);
+       copy_query_dev_fields(file, ib_dev, &resp, &ib_dev->attrs);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
@@ -984,11 +974,8 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        }
 
        if (cmd.access_flags & IB_ACCESS_ON_DEMAND) {
-               struct ib_device_attr attr;
-
-               ret = ib_query_device(pd->device, &attr);
-               if (ret || !(attr.device_cap_flags &
-                               IB_DEVICE_ON_DEMAND_PAGING)) {
+               if (!(pd->device->attrs.device_cap_flags &
+                     IB_DEVICE_ON_DEMAND_PAGING)) {
                        pr_debug("ODP support not available\n");
                        ret = -EINVAL;
                        goto err_put;
@@ -1256,7 +1243,7 @@ err_copy:
        idr_remove_uobj(&ib_uverbs_mw_idr, uobj);
 
 err_unalloc:
-       ib_dealloc_mw(mw);
+       uverbs_dealloc_mw(mw);
 
 err_put:
        put_pd_read(pd);
@@ -1285,7 +1272,7 @@ ssize_t ib_uverbs_dealloc_mw(struct ib_uverbs_file *file,
 
        mw = uobj->object;
 
-       ret = ib_dealloc_mw(mw);
+       ret = uverbs_dealloc_mw(mw);
        if (!ret)
                uobj->live = 0;
 
@@ -2446,6 +2433,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
        int                             i, sg_ind;
        int                             is_ud;
        ssize_t                         ret = -EINVAL;
+       size_t                          next_size;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
@@ -2490,7 +2478,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                                goto out_put;
                        }
 
-                       ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
+                       next_size = sizeof(*ud);
+                       ud = alloc_wr(next_size, user_wr->num_sge);
                        if (!ud) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2511,7 +2500,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                           user_wr->opcode == IB_WR_RDMA_READ) {
                        struct ib_rdma_wr *rdma;
 
-                       rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
+                       next_size = sizeof(*rdma);
+                       rdma = alloc_wr(next_size, user_wr->num_sge);
                        if (!rdma) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2525,7 +2515,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                           user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
                        struct ib_atomic_wr *atomic;
 
-                       atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
+                       next_size = sizeof(*atomic);
+                       atomic = alloc_wr(next_size, user_wr->num_sge);
                        if (!atomic) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2540,7 +2531,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                } else if (user_wr->opcode == IB_WR_SEND ||
                           user_wr->opcode == IB_WR_SEND_WITH_IMM ||
                           user_wr->opcode == IB_WR_SEND_WITH_INV) {
-                       next = alloc_wr(sizeof(*next), user_wr->num_sge);
+                       next_size = sizeof(*next);
+                       next = alloc_wr(next_size, user_wr->num_sge);
                        if (!next) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2572,7 +2564,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
 
                if (next->num_sge) {
                        next->sg_list = (void *) next +
-                               ALIGN(sizeof *next, sizeof (struct ib_sge));
+                               ALIGN(next_size, sizeof(struct ib_sge));
                        if (copy_from_user(next->sg_list,
                                           buf + sizeof cmd +
                                           cmd.wr_count * cmd.wqe_size +