aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ehca/ehca_cq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_cq.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c50
1 files changed, 21 insertions, 29 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 67f0670fe3b1..01d4a148bd71 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -56,11 +56,11 @@ int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
56{ 56{
57 unsigned int qp_num = qp->real_qp_num; 57 unsigned int qp_num = qp->real_qp_num;
58 unsigned int key = qp_num & (QP_HASHTAB_LEN-1); 58 unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
59 unsigned long spl_flags; 59 unsigned long flags;
60 60
61 spin_lock_irqsave(&cq->spinlock, spl_flags); 61 spin_lock_irqsave(&cq->spinlock, flags);
62 hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]); 62 hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
63 spin_unlock_irqrestore(&cq->spinlock, spl_flags); 63 spin_unlock_irqrestore(&cq->spinlock, flags);
64 64
65 ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x", 65 ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
66 cq->cq_number, qp_num); 66 cq->cq_number, qp_num);
@@ -74,9 +74,9 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
74 unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); 74 unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
75 struct hlist_node *iter; 75 struct hlist_node *iter;
76 struct ehca_qp *qp; 76 struct ehca_qp *qp;
77 unsigned long spl_flags; 77 unsigned long flags;
78 78
79 spin_lock_irqsave(&cq->spinlock, spl_flags); 79 spin_lock_irqsave(&cq->spinlock, flags);
80 hlist_for_each(iter, &cq->qp_hashtab[key]) { 80 hlist_for_each(iter, &cq->qp_hashtab[key]) {
81 qp = hlist_entry(iter, struct ehca_qp, list_entries); 81 qp = hlist_entry(iter, struct ehca_qp, list_entries);
82 if (qp->real_qp_num == real_qp_num) { 82 if (qp->real_qp_num == real_qp_num) {
@@ -88,7 +88,7 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
88 break; 88 break;
89 } 89 }
90 } 90 }
91 spin_unlock_irqrestore(&cq->spinlock, spl_flags); 91 spin_unlock_irqrestore(&cq->spinlock, flags);
92 if (ret) 92 if (ret)
93 ehca_err(cq->ib_cq.device, 93 ehca_err(cq->ib_cq.device,
94 "qp not found cq_num=%x real_qp_num=%x", 94 "qp not found cq_num=%x real_qp_num=%x",
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
146 spin_lock_init(&my_cq->spinlock); 146 spin_lock_init(&my_cq->spinlock);
147 spin_lock_init(&my_cq->cb_lock); 147 spin_lock_init(&my_cq->cb_lock);
148 spin_lock_init(&my_cq->task_lock); 148 spin_lock_init(&my_cq->task_lock);
149 atomic_set(&my_cq->nr_events, 0);
149 init_waitqueue_head(&my_cq->wait_completion); 150 init_waitqueue_head(&my_cq->wait_completion);
150 my_cq->ownpid = current->tgid; 151 my_cq->ownpid = current->tgid;
151 152
@@ -162,9 +163,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
162 goto create_cq_exit1; 163 goto create_cq_exit1;
163 } 164 }
164 165
165 spin_lock_irqsave(&ehca_cq_idr_lock, flags); 166 write_lock_irqsave(&ehca_cq_idr_lock, flags);
166 ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token); 167 ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
167 spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 168 write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
168 169
169 } while (ret == -EAGAIN); 170 } while (ret == -EAGAIN);
170 171
@@ -293,9 +294,9 @@ create_cq_exit3:
293 "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret); 294 "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
294 295
295create_cq_exit2: 296create_cq_exit2:
296 spin_lock_irqsave(&ehca_cq_idr_lock, flags); 297 write_lock_irqsave(&ehca_cq_idr_lock, flags);
297 idr_remove(&ehca_cq_idr, my_cq->token); 298 idr_remove(&ehca_cq_idr, my_cq->token);
298 spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 299 write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
299 300
300create_cq_exit1: 301create_cq_exit1:
301 kmem_cache_free(cq_cache, my_cq); 302 kmem_cache_free(cq_cache, my_cq);
@@ -303,16 +304,6 @@ create_cq_exit1:
303 return cq; 304 return cq;
304} 305}
305 306
306static int get_cq_nr_events(struct ehca_cq *my_cq)
307{
308 int ret;
309 unsigned long flags;
310 spin_lock_irqsave(&ehca_cq_idr_lock, flags);
311 ret = my_cq->nr_events;
312 spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
313 return ret;
314}
315
316int ehca_destroy_cq(struct ib_cq *cq) 307int ehca_destroy_cq(struct ib_cq *cq)
317{ 308{
318 u64 h_ret; 309 u64 h_ret;
@@ -339,17 +330,18 @@ int ehca_destroy_cq(struct ib_cq *cq)
339 } 330 }
340 } 331 }
341 332
342 spin_lock_irqsave(&ehca_cq_idr_lock, flags); 333 /*
343 while (my_cq->nr_events) { 334 * remove the CQ from the idr first to make sure
344 spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 335 * no more interrupt tasklets will touch this CQ
345 wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq)); 336 */
346 spin_lock_irqsave(&ehca_cq_idr_lock, flags); 337 write_lock_irqsave(&ehca_cq_idr_lock, flags);
347 /* recheck nr_events to assure no cqe has just arrived */
348 }
349
350 idr_remove(&ehca_cq_idr, my_cq->token); 338 idr_remove(&ehca_cq_idr, my_cq->token);
351 spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); 339 write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
340
341 /* now wait until all pending events have completed */
342 wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
352 343
344 /* nobody's using our CQ any longer -- we can destroy it */
353 h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); 345 h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
354 if (h_ret == H_R_STATE) { 346 if (h_ret == H_R_STATE) {
355 /* cq in err: read err data and destroy it forcibly */ 347 /* cq in err: read err data and destroy it forcibly */