diff options
author | Roland Dreier <rolandd@cisco.com> | 2008-04-04 12:14:57 -0700 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-04 12:18:48 -0700 |
commit | 5936553a34198878d9c898b1563315c92a72d83b (patch) | |
tree | bb32909411f239757be207681d320013d6d50a0e | |
parent | 563b4f6cb350cbce4cb83c8dffa5b617888d411d (diff) | |
download | libmlx4-5936553a34198878d9c898b1563315c92a72d83b.tar.gz |
Fix CQ cleanup when QP is destroyed
The current code is mlx4_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/mlx4.h | 4 | ||||
-rw-r--r-- | src/verbs.c | 23 |
3 files changed, 18 insertions, 18 deletions
@@ -381,15 +381,13 @@ void mlx4_cq_event(struct ibv_cq *cq) to_mcq(cq)->arm_sn++; } -void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) +void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) { struct mlx4_cqe *cqe, *dest; uint32_t prod_index; uint8_t owner_bit; int 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 @@ -429,7 +427,12 @@ void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) wmb(); update_cons_index(cq); } +} +void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq) +{ + pthread_spin_lock(&cq->lock); + __mlx4_cq_clean(cq, qpn, srq); pthread_spin_unlock(&cq->lock); } @@ -312,8 +312,8 @@ int mlx4_destroy_cq(struct ibv_cq *cq); int mlx4_poll_cq(struct ibv_cq *cq, int ne, struct ibv_wc *wc); int mlx4_arm_cq(struct ibv_cq *cq, int solicited); void mlx4_cq_event(struct ibv_cq *cq); -void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, - struct mlx4_srq *srq); +void __mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq); +void mlx4_cq_clean(struct mlx4_cq *cq, uint32_t qpn, struct mlx4_srq *srq); void mlx4_cq_resize_copy_cqes(struct mlx4_cq *cq, void *buf, int new_cqe); struct ibv_srq *mlx4_create_srq(struct ibv_pd *pd, diff --git a/src/verbs.c b/src/verbs.c index 50e0947..26174f8 100644 --- a/src/verbs.c +++ b/src/verbs.c @@ -532,23 +532,20 @@ int mlx4_destroy_qp(struct ibv_qp *ibqp) struct mlx4_qp *qp = to_mqp(ibqp); int ret; - mlx4_cq_clean(to_mcq(ibqp->recv_cq), ibqp->qp_num, - ibqp->srq ? to_msrq(ibqp->srq) : NULL); - if (ibqp->send_cq != ibqp->recv_cq) - mlx4_cq_clean(to_mcq(ibqp->send_cq), ibqp->qp_num, NULL); + ret = ibv_cmd_destroy_qp(ibqp); + if (ret) + return ret; mlx4_lock_cqs(ibqp); - mlx4_clear_qp(to_mctx(ibqp->context), ibqp->qp_num); - mlx4_unlock_cqs(ibqp); - ret = ibv_cmd_destroy_qp(ibqp); - if (ret) { - mlx4_lock_cqs(ibqp); - mlx4_store_qp(to_mctx(ibqp->context), ibqp->qp_num, qp); - mlx4_unlock_cqs(ibqp); + __mlx4_cq_clean(to_mcq(ibqp->recv_cq), ibqp->qp_num, + ibqp->srq ? to_msrq(ibqp->srq) : NULL); + if (ibqp->send_cq != ibqp->recv_cq) + __mlx4_cq_clean(to_mcq(ibqp->send_cq), ibqp->qp_num, NULL); - return ret; - } + mlx4_clear_qp(to_mctx(ibqp->context), ibqp->qp_num); + + mlx4_unlock_cqs(ibqp); if (!ibqp->srq) mlx4_free_db(to_mctx(ibqp->context), MLX4_DB_TYPE_RQ, qp->db); |