aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca/mthca_cq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mthca/mthca_cq.c')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 312cf90731ea..205854e9c662 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -238,9 +238,9 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
238 spin_lock(&dev->cq_table.lock); 238 spin_lock(&dev->cq_table.lock);
239 239
240 cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1)); 240 cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
241
242 if (cq) 241 if (cq)
243 atomic_inc(&cq->refcount); 242 ++cq->refcount;
243
244 spin_unlock(&dev->cq_table.lock); 244 spin_unlock(&dev->cq_table.lock);
245 245
246 if (!cq) { 246 if (!cq) {
@@ -254,8 +254,10 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
254 if (cq->ibcq.event_handler) 254 if (cq->ibcq.event_handler)
255 cq->ibcq.event_handler(&event, cq->ibcq.cq_context); 255 cq->ibcq.event_handler(&event, cq->ibcq.cq_context);
256 256
257 if (atomic_dec_and_test(&cq->refcount)) 257 spin_lock(&dev->cq_table.lock);
258 if (!--cq->refcount)
258 wake_up(&cq->wait); 259 wake_up(&cq->wait);
260 spin_unlock(&dev->cq_table.lock);
259} 261}
260 262
261static inline int is_recv_cqe(struct mthca_cqe *cqe) 263static inline int is_recv_cqe(struct mthca_cqe *cqe)
@@ -267,23 +269,13 @@ static inline int is_recv_cqe(struct mthca_cqe *cqe)
267 return !(cqe->is_send & 0x80); 269 return !(cqe->is_send & 0x80);
268} 270}
269 271
270void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, 272void mthca_cq_clean(struct mthca_dev *dev, struct mthca_cq *cq, u32 qpn,
271 struct mthca_srq *srq) 273 struct mthca_srq *srq)
272{ 274{
273 struct mthca_cq *cq;
274 struct mthca_cqe *cqe; 275 struct mthca_cqe *cqe;
275 u32 prod_index; 276 u32 prod_index;
276 int nfreed = 0; 277 int nfreed = 0;
277 278
278 spin_lock_irq(&dev->cq_table.lock);
279 cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
280 if (cq)
281 atomic_inc(&cq->refcount);
282 spin_unlock_irq(&dev->cq_table.lock);
283
284 if (!cq)
285 return;
286
287 spin_lock_irq(&cq->lock); 279 spin_lock_irq(&cq->lock);
288 280
289 /* 281 /*
@@ -301,7 +293,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
301 293
302 if (0) 294 if (0)
303 mthca_dbg(dev, "Cleaning QPN %06x from CQN %06x; ci %d, pi %d\n", 295 mthca_dbg(dev, "Cleaning QPN %06x from CQN %06x; ci %d, pi %d\n",
304 qpn, cqn, cq->cons_index, prod_index); 296 qpn, cq->cqn, cq->cons_index, prod_index);
305 297
306 /* 298 /*
307 * Now sweep backwards through the CQ, removing CQ entries 299 * Now sweep backwards through the CQ, removing CQ entries
@@ -325,8 +317,6 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
325 } 317 }
326 318
327 spin_unlock_irq(&cq->lock); 319 spin_unlock_irq(&cq->lock);
328 if (atomic_dec_and_test(&cq->refcount))
329 wake_up(&cq->wait);
330} 320}
331 321
332void mthca_cq_resize_copy_cqes(struct mthca_cq *cq) 322void mthca_cq_resize_copy_cqes(struct mthca_cq *cq)
@@ -821,7 +811,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
821 } 811 }
822 812
823 spin_lock_init(&cq->lock); 813 spin_lock_init(&cq->lock);
824 atomic_set(&cq->refcount, 1); 814 cq->refcount = 1;
825 init_waitqueue_head(&cq->wait); 815 init_waitqueue_head(&cq->wait);
826 816
827 memset(cq_context, 0, sizeof *cq_context); 817 memset(cq_context, 0, sizeof *cq_context);
@@ -896,6 +886,17 @@ err_out:
896 return err; 886 return err;
897} 887}
898 888
889static inline int get_cq_refcount(struct mthca_dev *dev, struct mthca_cq *cq)
890{
891 int c;
892
893 spin_lock_irq(&dev->cq_table.lock);
894 c = cq->refcount;
895 spin_unlock_irq(&dev->cq_table.lock);
896
897 return c;
898}
899
899void mthca_free_cq(struct mthca_dev *dev, 900void mthca_free_cq(struct mthca_dev *dev,
900 struct mthca_cq *cq) 901 struct mthca_cq *cq)
901{ 902{
@@ -929,6 +930,7 @@ void mthca_free_cq(struct mthca_dev *dev,
929 spin_lock_irq(&dev->cq_table.lock); 930 spin_lock_irq(&dev->cq_table.lock);
930 mthca_array_clear(&dev->cq_table.cq, 931 mthca_array_clear(&dev->cq_table.cq,
931 cq->cqn & (dev->limits.num_cqs - 1)); 932 cq->cqn & (dev->limits.num_cqs - 1));
933 --cq->refcount;
932 spin_unlock_irq(&dev->cq_table.lock); 934 spin_unlock_irq(&dev->cq_table.lock);
933 935
934 if (dev->mthca_flags & MTHCA_FLAG_MSI_X) 936 if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
@@ -936,8 +938,7 @@ void mthca_free_cq(struct mthca_dev *dev,
936 else 938 else
937 synchronize_irq(dev->pdev->irq); 939 synchronize_irq(dev->pdev->irq);
938 940
939 atomic_dec(&cq->refcount); 941 wait_event(cq->wait, !get_cq_refcount(dev, cq));
940 wait_event(cq->wait, !atomic_read(&cq->refcount));
941 942
942 if (cq->is_kernel) { 943 if (cq->is_kernel) {
943 mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe); 944 mthca_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);