aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2008-04-04 12:19:25 -0700
committerRoland Dreier <rolandd@cisco.com>2008-04-04 12:19:25 -0700
commit7d2e417e240eb0a341a5a573b0748ef0cbd4f678 (patch)
tree5084e70d6c7459ae1900b97bcce53aa38a8a4e65
parentc5b8f850f8618613165c30a805b961b60474529f (diff)
downloadlibmthca-7d2e417e240eb0a341a5a573b0748ef0cbd4f678.tar.gz
Fix CQ cleanup when QP is destroyed
The current code is mthca_destroy_qp() cleans completions from the QP being destroyed out of CQs before calling into the kernel to actually destroy the QP. This leaves a window where new completions could be added and left in the CQ, which leads to problems when that completion is polled. Fix this by cleaning the CQ and removing the QP from the QP table after the QP is really gone. Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--src/cq.c9
-rw-r--r--src/mthca.h4
-rw-r--r--src/verbs.c23
3 files changed, 18 insertions, 18 deletions
diff --git a/src/cq.c b/src/cq.c
index ec582a0..24ff0aa 100644
--- a/src/cq.c
+++ b/src/cq.c
@@ -546,14 +546,12 @@ static inline int is_recv_cqe(struct mthca_cqe *cqe)
return !(cqe->is_send & 0x80);
}
-void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq)
+void __mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq)
{
struct mthca_cqe *cqe;
uint32_t prod_index;
int i, nfreed = 0;
- pthread_spin_lock(&cq->lock);
-
/*
* First we need to find the current producer index, so we
* know where to start cleaning from. It doesn't matter if HW
@@ -590,7 +588,12 @@ void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq)
cq->cons_index += nfreed;
update_cons_index(cq, nfreed);
}
+}
+void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq)
+{
+ pthread_spin_lock(&cq->lock);
+ __mthca_cq_clean(cq, qpn, srq);
pthread_spin_unlock(&cq->lock);
}
diff --git a/src/mthca.h b/src/mthca.h
index 1f31bc3..66751f3 100644
--- a/src/mthca.h
+++ b/src/mthca.h
@@ -321,8 +321,8 @@ int mthca_poll_cq(struct ibv_cq *cq, int ne, struct ibv_wc *wc);
int mthca_tavor_arm_cq(struct ibv_cq *cq, int solicited);
int mthca_arbel_arm_cq(struct ibv_cq *cq, int solicited);
void mthca_arbel_cq_event(struct ibv_cq *cq);
-void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn,
- struct mthca_srq *srq);
+void __mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq);
+void mthca_cq_clean(struct mthca_cq *cq, uint32_t qpn, struct mthca_srq *srq);
void mthca_cq_resize_copy_cqes(struct mthca_cq *cq, void *buf, int new_cqe);
int mthca_alloc_cq_buf(struct mthca_device *dev, struct mthca_buf *buf, int nent);
diff --git a/src/verbs.c b/src/verbs.c
index 84c9491..6c9b53a 100644
--- a/src/verbs.c
+++ b/src/verbs.c
@@ -676,23 +676,20 @@ int mthca_destroy_qp(struct ibv_qp *qp)
{
int ret;
- mthca_cq_clean(to_mcq(qp->recv_cq), qp->qp_num,
- qp->srq ? to_msrq(qp->srq) : NULL);
- if (qp->send_cq != qp->recv_cq)
- mthca_cq_clean(to_mcq(qp->send_cq), qp->qp_num, NULL);
+ ret = ibv_cmd_destroy_qp(qp);
+ if (ret)
+ return ret;
mthca_lock_cqs(qp);
- mthca_clear_qp(to_mctx(qp->context), qp->qp_num);
- mthca_unlock_cqs(qp);
- ret = ibv_cmd_destroy_qp(qp);
- if (ret) {
- mthca_lock_cqs(qp);
- mthca_store_qp(to_mctx(qp->context), qp->qp_num, to_mqp(qp));
- mthca_unlock_cqs(qp);
+ __mthca_cq_clean(to_mcq(qp->recv_cq), qp->qp_num,
+ qp->srq ? to_msrq(qp->srq) : NULL);
+ if (qp->send_cq != qp->recv_cq)
+ __mthca_cq_clean(to_mcq(qp->send_cq), qp->qp_num, NULL);
- return ret;
- }
+ mthca_clear_qp(to_mctx(qp->context), qp->qp_num);
+
+ mthca_unlock_cqs(qp);
if (mthca_is_memfree(qp->context)) {
mthca_free_db(to_mctx(qp->context)->db_tab, MTHCA_DB_TYPE_RQ,