Merge branch 'for-linus' of git://git.selinuxproject.org/~jmorris/linux-security
[pandora-kernel.git] / drivers / infiniband / core / uverbs_main.c
index 56898b6..8796367 100644 (file)
@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
 DEFINE_IDR(ib_uverbs_srq_idr);
+DEFINE_IDR(ib_uverbs_xrcd_idr);
 
 static DEFINE_SPINLOCK(map_lock);
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
        [IB_USER_VERBS_CMD_MODIFY_SRQ]          = ib_uverbs_modify_srq,
        [IB_USER_VERBS_CMD_QUERY_SRQ]           = ib_uverbs_query_srq,
        [IB_USER_VERBS_CMD_DESTROY_SRQ]         = ib_uverbs_destroy_srq,
+       [IB_USER_VERBS_CMD_OPEN_XRCD]           = ib_uverbs_open_xrcd,
+       [IB_USER_VERBS_CMD_CLOSE_XRCD]          = ib_uverbs_close_xrcd,
+       [IB_USER_VERBS_CMD_CREATE_XSRQ]         = ib_uverbs_create_xsrq,
+       [IB_USER_VERBS_CMD_OPEN_QP]             = ib_uverbs_open_qp
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                        container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
                idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
-               ib_uverbs_detach_umcast(qp, uqp);
-               ib_destroy_qp(qp);
+               if (qp != qp->real_qp) {
+                       ib_close_qp(qp);
+               } else {
+                       ib_uverbs_detach_umcast(qp, uqp);
+                       ib_destroy_qp(qp);
+               }
                ib_uverbs_release_uevent(file, &uqp->uevent);
                kfree(uqp);
        }
@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                kfree(uobj);
        }
 
+       mutex_lock(&file->device->xrcd_tree_mutex);
+       list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
+               struct ib_xrcd *xrcd = uobj->object;
+               struct ib_uxrcd_object *uxrcd =
+                       container_of(uobj, struct ib_uxrcd_object, uobject);
+
+               idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
+               ib_uverbs_dealloc_xrcd(file->device, xrcd);
+               kfree(uxrcd);
+       }
+       mutex_unlock(&file->device->xrcd_tree_mutex);
+
        list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
                struct ib_pd *pd = uobj->object;
 
@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        if (hdr.in_words * 4 != count)
                return -EINVAL;
 
-       if (hdr.command < 0                             ||
-           hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+       if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
            !uverbs_cmd_table[hdr.command])
                return -EINVAL;
 
@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
 
        kref_init(&uverbs_dev->ref);
        init_completion(&uverbs_dev->comp);
+       uverbs_dev->xrcd_tree = RB_ROOT;
+       mutex_init(&uverbs_dev->xrcd_tree_mutex);
 
        spin_lock(&map_lock);
        devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);