diff mbox

[for-next,1/2] iw_cxgb4: serialize CQ event upcalls with CQ destruction

Message ID 1418805663-15333-2-git-send-email-hariprasad@chelsio.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Hariprasad S Dec. 17, 2014, 8:41 a.m. UTC
A race exists where the application can be destroying the CQ concurrently
with a HW interrupt indicating a completion has been inserted into the CQ.
This can case an event notification upcall to the application after the
CQ has been destroyed.

The solution is to serialize looking up the CQ in the IDR table and
referencing the CQ in c4iw_ev_handler(), with removing the CQID from the
IDR table and blocking until the refcnt reaches 0 in c4iw_destroy_cq().

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
 drivers/infiniband/hw/cxgb4/ev.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
diff mbox

Patch

diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
index c9df054..4498a89 100644
--- a/drivers/infiniband/hw/cxgb4/ev.c
+++ b/drivers/infiniband/hw/cxgb4/ev.c
@@ -225,13 +225,20 @@  int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
 	struct c4iw_cq *chp;
 	unsigned long flag;
 
+	spin_lock_irqsave(&dev->lock, flag);
 	chp = get_chp(dev, qid);
 	if (chp) {
+		atomic_inc(&chp->refcnt);
+		spin_unlock_irqrestore(&dev->lock, flag);
 		t4_clear_cq_armed(&chp->cq);
 		spin_lock_irqsave(&chp->comp_handler_lock, flag);
 		(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 		spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
-	} else
+		if (atomic_dec_and_test(&chp->refcnt))
+			wake_up(&chp->wait);
+	} else {
 		PDBG("%s unknown cqid 0x%x\n", __func__, qid);
+		spin_unlock_irqrestore(&dev->lock, flag);
+	}
 	return 0;
 }