Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[cascardo/linux.git] / drivers / infiniband / hw / ehca / ehca_cq.c
index 9291a86..67f0670 100644 (file)
@@ -113,7 +113,7 @@ struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
        return ret;
 }
 
-struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
+struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
                             struct ib_ucontext *context,
                             struct ib_udata *udata)
 {
@@ -134,19 +134,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
        if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
                return ERR_PTR(-EINVAL);
 
-       my_cq = kmem_cache_alloc(cq_cache, GFP_KERNEL);
+       my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
        if (!my_cq) {
                ehca_err(device, "Out of memory for ehca_cq struct device=%p",
                         device);
                return ERR_PTR(-ENOMEM);
        }
 
-       memset(my_cq, 0, sizeof(struct ehca_cq));
        memset(&param, 0, sizeof(struct ehca_alloc_cq_parms));
 
        spin_lock_init(&my_cq->spinlock);
        spin_lock_init(&my_cq->cb_lock);
        spin_lock_init(&my_cq->task_lock);
+       init_waitqueue_head(&my_cq->wait_completion);
        my_cq->ownpid = current->tgid;
 
        cq = &my_cq->ib_cq;
@@ -303,6 +303,16 @@ create_cq_exit1:
        return cq;
 }
 
+static int get_cq_nr_events(struct ehca_cq *my_cq)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+       ret = my_cq->nr_events;
+       spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       return ret;
+}
+
 int ehca_destroy_cq(struct ib_cq *cq)
 {
        u64 h_ret;
@@ -330,10 +340,11 @@ int ehca_destroy_cq(struct ib_cq *cq)
        }
 
        spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-       while (my_cq->nr_callbacks) {
+       while (my_cq->nr_events) {
                spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-               yield();
+               wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
                spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+               /* recheck nr_events to assure no cqe has just arrived */
        }
 
        idr_remove(&ehca_cq_idr, my_cq->token);