Merge branch 'upstream'
[pandora-kernel.git] / drivers / infiniband / core / uverbs_main.c
index 0eb38f4..903f85a 100644 (file)
@@ -66,7 +66,7 @@ enum {
 
 static struct class *uverbs_class;
 
-DECLARE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_MUTEX(ib_uverbs_idr_mutex);
 DEFINE_IDR(ib_uverbs_pd_idr);
 DEFINE_IDR(ib_uverbs_mr_idr);
 DEFINE_IDR(ib_uverbs_mw_idr);
@@ -160,6 +160,18 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
        spin_unlock_irq(&file->async_file->lock);
 }
 
+static void ib_uverbs_detach_umcast(struct ib_qp *qp,
+                                   struct ib_uqp_object *uobj)
+{
+       struct ib_uverbs_mcast_entry *mcast, *tmp;
+
+       list_for_each_entry_safe(mcast, tmp, &uobj->mcast_list, list) {
+               ib_detach_mcast(qp, &mcast->gid, mcast->lid);
+               list_del(&mcast->list);
+               kfree(mcast);
+       }
+}
+
 static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                                      struct ib_ucontext *context)
 {
@@ -168,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        if (!context)
                return 0;
 
-       down(&ib_uverbs_idr_mutex);
+       mutex_lock(&ib_uverbs_idr_mutex);
 
        list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
                struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
@@ -180,13 +192,14 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 
        list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
                struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
-               struct ib_uevent_object *uevent =
-                       container_of(uobj, struct ib_uevent_object, uobject);
+               struct ib_uqp_object *uqp =
+                       container_of(uobj, struct ib_uqp_object, uevent.uobject);
                idr_remove(&ib_uverbs_qp_idr, uobj->id);
+               ib_uverbs_detach_umcast(qp, uqp);
                ib_destroy_qp(qp);
                list_del(&uobj->list);
-               ib_uverbs_release_uevent(file, uevent);
-               kfree(uevent);
+               ib_uverbs_release_uevent(file, &uqp->uevent);
+               kfree(uqp);
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -237,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                kfree(uobj);
        }
 
-       up(&ib_uverbs_idr_mutex);
+       mutex_unlock(&ib_uverbs_idr_mutex);
 
        return context->device->dealloc_ucontext(context);
 }
@@ -442,13 +455,10 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
 
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
 {
-       struct ib_uverbs_event_file *ev_file = context_ptr;
-       struct ib_ucq_object *uobj;
+       struct ib_ucq_object *uobj = container_of(event->element.cq->uobject,
+                                                 struct ib_ucq_object, uobject);
 
-       uobj = container_of(event->element.cq->uobject,
-                           struct ib_ucq_object, uobject);
-
-       ib_uverbs_async_handler(ev_file->uverbs_file, uobj->uobject.user_handle,
+       ib_uverbs_async_handler(uobj->uverbs_file, uobj->uobject.user_handle,
                                event->event, &uobj->async_list,
                                &uobj->async_events_reported);
                                
@@ -643,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        file->ucontext   = NULL;
        file->async_file = NULL;
        kref_init(&file->ref);
-       init_MUTEX(&file->mutex);
+       mutex_init(&file->mutex);
 
        filp->private_data = file;
 
@@ -728,12 +738,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
        if (!device->alloc_ucontext)
                return;
 
-       uverbs_dev = kmalloc(sizeof *uverbs_dev, GFP_KERNEL);
+       uverbs_dev = kzalloc(sizeof *uverbs_dev, GFP_KERNEL);
        if (!uverbs_dev)
                return;
 
-       memset(uverbs_dev, 0, sizeof *uverbs_dev);
-
        kref_init(&uverbs_dev->ref);
 
        spin_lock(&map_lock);
@@ -894,6 +902,7 @@ static void __exit ib_uverbs_cleanup(void)
        unregister_filesystem(&uverbs_event_fs);
        class_destroy(uverbs_class);
        unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+       flush_scheduled_work();
        idr_destroy(&ib_uverbs_pd_idr);
        idr_destroy(&ib_uverbs_mr_idr);
        idr_destroy(&ib_uverbs_mw_idr);