--- /dev/null
+From 164b323b3bb95757b65087555a33f29c3a792fdc Mon Sep 17 00:00:00 2001
+From: Somnath Kotur <somnath.kotur@broadcom.com>
+Date: Fri, 3 Nov 2017 19:19:01 -0700
+Subject: [PATCH 1/4] RDMA/bnxt_re: Add memory barriers when processing CQ/EQ
+ entries
+
+The code determines if the next ring entry is valid before proceeding
+further to read the rest of the entry. The CPU can re-order and read
+the rest of the entry first, possibly reading a stale entry, if DMA
+of a new entry happens right after reading it.
+
+Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+---
+ drivers/infiniband/hw/bnxt_re/qplib_fp.c | 21 +++++++++++++++++++++
+ drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 4 ++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+index a82044d..31ea9f4 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -292,6 +292,12 @@ static void bnxt_qplib_service_nq(unsigned long data)
+ if (!NQE_CMP_VALID(nqe, raw_cons, hwq->max_elements))
+ break;
+
++ /*
++ * The valid test of the entry must be done first before
++ * reading any further.
++ */
++ dma_rmb();
++
+ type = le16_to_cpu(nqe->info10_type) & NQ_BASE_TYPE_MASK;
+ switch (type) {
+ case NQ_BASE_TYPE_CQ_NOTIFICATION:
+@@ -1113,6 +1119,11 @@ static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp)
+ hw_cqe = &hw_cqe_ptr[CQE_PG(i)][CQE_IDX(i)];
+ if (!CQE_CMP_VALID(hw_cqe, i, cq_hwq->max_elements))
+ continue;
++ /*
++ * The valid test of the entry must be done first before
++ * reading any further.
++ */
++ dma_rmb();
+ switch (hw_cqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK) {
+ case CQ_BASE_CQE_TYPE_REQ:
+ case CQ_BASE_CQE_TYPE_TERMINAL:
+@@ -1896,6 +1907,11 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
+ /* If the next hwcqe is VALID */
+ if (CQE_CMP_VALID(peek_hwcqe, peek_raw_cq_cons,
+ cq->hwq.max_elements)) {
++ /*
++ * The valid test of the entry must be done first before
++ * reading any further.
++ */
++ dma_rmb();
+ /* If the next hwcqe is a REQ */
+ if ((peek_hwcqe->cqe_type_toggle &
+ CQ_BASE_CQE_TYPE_MASK) ==
+@@ -2440,6 +2456,11 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
+ if (!CQE_CMP_VALID(hw_cqe, raw_cons, cq->hwq.max_elements))
+ break;
+
++ /*
++ * The valid test of the entry must be done first before
++ * reading any further.
++ */
++ dma_rmb();
+ /* From the device's respective CQE format to qplib_wc*/
+ switch (hw_cqe->cqe_type_toggle & CQ_BASE_CQE_TYPE_MASK) {
+ case CQ_BASE_CQE_TYPE_REQ:
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+index 6d11614..751170a 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+@@ -357,6 +357,10 @@ static void bnxt_qplib_service_creq(unsigned long data)
+ creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
+ if (!CREQ_CMP_VALID(creqe, raw_cons, creq->max_elements))
+ break;
++ /* The valid test of the entry must be done first before
++ * reading any further.
++ */
++ dma_rmb();
+
+ type = creqe->type & CREQ_BASE_TYPE_MASK;
+ switch (type) {
+--
+2.5.5
+
--- /dev/null
+From 1faffd689e54c314a6b5d5bbe06804c6bf357fc0 Mon Sep 17 00:00:00 2001
+From: Selvin Xavier <selvin.xavier@broadcom.com>
+Date: Fri, 3 Nov 2017 19:28:19 -0700
+Subject: [PATCH 2/4] RDMA/bnxt_re: Set QP state in case of response completion
+ errors
+
+Moves the driver QP state to error in case of response completion
+errors. Handles the scenarios which doesn't generate a terminal CQE.
+
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+---
+ drivers/infiniband/hw/bnxt_re/qplib_fp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+index 31ea9f4..805a612 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -2118,6 +2118,7 @@ static int bnxt_qplib_cq_process_res_rc(struct bnxt_qplib_cq *cq,
+ *pcqe = cqe;
+
+ if (hwcqe->status != CQ_RES_RC_STATUS_OK) {
++ qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
+ /* Add qp to flush list of the CQ */
+ bnxt_qplib_lock_buddy_cq(qp, cq);
+ __bnxt_qplib_add_flush_qp(qp);
+@@ -2181,6 +2182,7 @@ static int bnxt_qplib_cq_process_res_ud(struct bnxt_qplib_cq *cq,
+ *pcqe = cqe;
+
+ if (hwcqe->status != CQ_RES_RC_STATUS_OK) {
++ qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
+ /* Add qp to flush list of the CQ */
+ bnxt_qplib_lock_buddy_cq(qp, cq);
+ __bnxt_qplib_add_flush_qp(qp);
+@@ -2268,6 +2270,7 @@ static int bnxt_qplib_cq_process_res_raweth_qp1(struct bnxt_qplib_cq *cq,
+ *pcqe = cqe;
+
+ if (hwcqe->status != CQ_RES_RC_STATUS_OK) {
++ qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
+ /* Add qp to flush list of the CQ */
+ bnxt_qplib_lock_buddy_cq(qp, cq);
+ __bnxt_qplib_add_flush_qp(qp);
+--
+2.5.5
+
--- /dev/null
+From ddbb03a013b2ab9415456b4bd7b035f0d1d597d2 Mon Sep 17 00:00:00 2001
+From: Selvin Xavier <selvin.xavier@broadcom.com>
+Date: Fri, 3 Nov 2017 19:41:07 -0700
+Subject: [PATCH 3/4] RDMA/bnxt_re: Flush CQ notification Work Queue before
+ destroying QP
+
+Destroy_qp shall wait for any outstanding CQ notification to be
+flushed out before proceeding with QP destroy. Flushing the WQ
+before destroying the QP.
+
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 1 +
+ drivers/infiniband/hw/bnxt_re/qplib_fp.c | 7 +++++++
+ drivers/infiniband/hw/bnxt_re/qplib_fp.h | 1 +
+ 3 files changed, 9 insertions(+)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+index ebcdfb4..96ec797 100644
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -788,6 +788,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
+ struct bnxt_re_dev *rdev = qp->rdev;
+ int rc;
+
++ bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
+ bnxt_qplib_del_flush_qp(&qp->qplib_qp);
+ rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
+ if (rc) {
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+index 805a612..c0f8133 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -2537,3 +2537,10 @@ void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type)
+ atomic_set(&cq->arm_state, 1);
+ spin_unlock_irqrestore(&cq->hwq.lock, flags);
+ }
++
++void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp)
++{
++ flush_workqueue(qp->scq->nq->cqn_wq);
++ if (qp->scq != qp->rcq)
++ flush_workqueue(qp->rcq->nq->cqn_wq);
++}
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+index 8ead70c..c582d4e 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+@@ -478,4 +478,5 @@ void bnxt_qplib_release_cq_locks(struct bnxt_qplib_qp *qp,
+ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
+ struct bnxt_qplib_cqe *cqe,
+ int num_cqes);
++void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
+ #endif /* __BNXT_QPLIB_FP_H__ */
+--
+2.5.5
+
--- /dev/null
+From b53367bb0452d8f92cdb7dadc6ba192cff035c4b Mon Sep 17 00:00:00 2001
+From: Selvin Xavier <selvin.xavier@broadcom.com>
+Date: Sat, 4 Nov 2017 01:27:30 -0700
+Subject: [PATCH 4/4] RDMA/bnxt_re: synchronize poll_cq and req_notify_cq verbs
+
+Synchronize poll_cq and req_notify_cq verbs using cq_lock,
+instead of the lower level qplib->hwq.lock.
+
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+index 96ec797..d5770aa 100644
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -2999,8 +2999,10 @@ int bnxt_re_req_notify_cq(struct ib_cq *ib_cq,
+ enum ib_cq_notify_flags ib_cqn_flags)
+ {
+ struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
+- int type = 0;
++ int type = 0, rc = 0;
++ unsigned long flags;
+
++ spin_lock_irqsave(&cq->cq_lock, flags);
+ /* Trigger on the very next completion */
+ if (ib_cqn_flags & IB_CQ_NEXT_COMP)
+ type = DBR_DBR_TYPE_CQ_ARMALL;
+@@ -3010,12 +3012,15 @@ int bnxt_re_req_notify_cq(struct ib_cq *ib_cq,
+
+ /* Poll to see if there are missed events */
+ if ((ib_cqn_flags & IB_CQ_REPORT_MISSED_EVENTS) &&
+- !(bnxt_qplib_is_cq_empty(&cq->qplib_cq)))
+- return 1;
+-
++ !(bnxt_qplib_is_cq_empty(&cq->qplib_cq))) {
++ rc = 1;
++ goto exit;
++ }
+ bnxt_qplib_req_notify_cq(&cq->qplib_cq, type);
+
+- return 0;
++exit:
++ spin_unlock_irqrestore(&cq->cq_lock, flags);
++ return rc;
+ }
+
+ /* Memory Regions */
+--
+2.5.5
+