diff options
author | Bharat Potnuri <bharat@chelsio.com> | 2018-04-27 16:41:16 +0530 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2018-04-27 14:38:44 -0400 |
commit | 2df19e19ae90d94fd8724083f161f368a2797537 (patch) | |
tree | b2f6622d07fb37ddb5501cddd377aeacdab72c6f /drivers/infiniband/hw/cxgb4/cq.c | |
parent | 54e7e48b13c85d9a730b989fe7dc5250199a4f81 (diff) | |
download | op-kernel-dev-2df19e19ae90d94fd8724083f161f368a2797537.zip op-kernel-dev-2df19e19ae90d94fd8724083f161f368a2797537.tar.gz |
iw_cxgb4: Atomically flush per QP HW CQEs
When a CQ is shared by multiple QPs, c4iw_flush_hw_cq() needs to acquire
corresponding QP lock before moving the CQEs into its corresponding SW
queue and accessing the SQ contents for completing a WR.
Ignore CQEs if corresponding QP is already flushed.
Cc: stable@vger.kernel.org
Signed-off-by: Potnuri Bharat Teja <bharat@chelsio.com>
Reviewed-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/cq.c')
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cq.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 6f2b261..2be2e1a 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -315,7 +315,7 @@ static void advance_oldest_read(struct t4_wq *wq) * Deal with out-of-order and/or completions that complete * prior unsignalled WRs. */ -void c4iw_flush_hw_cq(struct c4iw_cq *chp) +void c4iw_flush_hw_cq(struct c4iw_cq *chp, struct c4iw_qp *flush_qhp) { struct t4_cqe *hw_cqe, *swcqe, read_cqe; struct c4iw_qp *qhp; @@ -339,6 +339,13 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp) if (qhp == NULL) goto next_cqe; + if (flush_qhp != qhp) { + spin_lock(&qhp->lock); + + if (qhp->wq.flushed == 1) + goto next_cqe; + } + if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) goto next_cqe; @@ -390,6 +397,8 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp) next_cqe: t4_hwcq_consume(&chp->cq); ret = t4_next_hw_cqe(&chp->cq, &hw_cqe); + if (qhp && flush_qhp != qhp) + spin_unlock(&qhp->lock); } } |