diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-04-04 12:19:25 -0700 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-04 12:19:25 -0700 |
commit | 7d2e417e240eb0a341a5a573b0748ef0cbd4f678 (patch) | |
tree | 5084e70d6c7459ae1900b97bcce53aa38a8a4e65 | |
parent | c5b8f850f8618613165c30a805b961b60474529f (diff) | |
download | libmthca-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.c | 9 | ||||
-rw-r--r-- | src/mthca.h | 4 | ||||
-rw-r--r-- | src/verbs.c | 23 |
3 files changed, 18 insertions, 18 deletions
@@ -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, |