Home Home > GIT Browse > SLE12-SP3-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Kirjanov <dkirjanov@suse.com>2019-02-18 14:29:50 +0100
committerDenis Kirjanov <dkirjanov@suse.com>2019-02-19 15:33:54 +0100
commit59d9c365789937ed57354aa8c5aa08e538b4d395 (patch)
treeb7f38d029dd9e58b4b5f2d5a946aa674de699ec4
parentc9b5c90fc8aa7bcc6bb438094e417b2a7e99185a (diff)
RDMA/bnxt_re: Synchronize destroy_qp with poll_cq (bsc#1125446).
-rw-r--r--patches.drivers/RDMA-bnxt_re-Synchronize-destroy_qp-with-poll_cq.patch190
-rw-r--r--series.conf1
2 files changed, 191 insertions, 0 deletions
diff --git a/patches.drivers/RDMA-bnxt_re-Synchronize-destroy_qp-with-poll_cq.patch b/patches.drivers/RDMA-bnxt_re-Synchronize-destroy_qp-with-poll_cq.patch
new file mode 100644
index 0000000000..5e921636f4
--- /dev/null
+++ b/patches.drivers/RDMA-bnxt_re-Synchronize-destroy_qp-with-poll_cq.patch
@@ -0,0 +1,190 @@
+From: Selvin Xavier <selvin.xavier@broadcom.com>
+Date: Thu, 15 Feb 2018 21:20:11 -0800
+Subject: RDMA/bnxt_re: Synchronize destroy_qp with poll_cq
+Patch-mainline: v4.16-rc3
+Git-commit: 3b921e3bc4c20af58a663ed238ad57e87493dde2
+References: bsc#1125446
+
+Avoid system crash when destroy_qp is invoked while
+the driver is processing the poll_cq. Synchronize these
+functions using the cq_lock.
+
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Acked-by: Denis Kirjanov <dkirjanov@suse.com>
+---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 39 +++++++++++++++++++++++++++++---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.h | 2 ++
+ drivers/infiniband/hw/bnxt_re/qplib_fp.c | 21 +++++------------
+ drivers/infiniband/hw/bnxt_re/qplib_fp.h | 4 +++-
+ 4 files changed, 47 insertions(+), 19 deletions(-)
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -803,19 +803,50 @@ int bnxt_re_query_ah(struct ib_ah *ib_ah
+ return 0;
+ }
+
++static unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp)
++ __acquires(&qp->scq->cq_lock) __acquires(&qp->rcq->cq_lock)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&qp->scq->cq_lock, flags);
++ if (qp->rcq != qp->scq)
++ spin_lock(&qp->rcq->cq_lock);
++ else
++ __acquire(&qp->rcq->cq_lock);
++
++ return flags;
++}
++
++static void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp,
++ unsigned long flags)
++ __releases(&qp->scq->cq_lock) __releases(&qp->rcq->cq_lock)
++{
++ if (qp->rcq != qp->scq)
++ spin_unlock(&qp->rcq->cq_lock);
++ else
++ __release(&qp->rcq->cq_lock);
++ spin_unlock_irqrestore(&qp->scq->cq_lock, flags);
++}
++
+ /* Queue Pairs */
+ int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
+ {
+ struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
+ struct bnxt_re_dev *rdev = qp->rdev;
+ int rc;
++ unsigned int flags;
+
+- bnxt_qplib_del_flush_qp(&qp->qplib_qp);
+ rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
+ if (rc) {
+ dev_err(rdev_to_dev(rdev), "Failed to destroy HW QP");
+ return rc;
+ }
++
++ flags = bnxt_re_lock_cqs(qp);
++ bnxt_qplib_clean_qp(&qp->qplib_qp);
++ bnxt_re_unlock_cqs(qp, flags);
++ bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
++
+ if (ib_qp->qp_type == IB_QPT_GSI && rdev->qp1_sqp) {
+ rc = bnxt_qplib_destroy_ah(&rdev->qplib_res,
+ &rdev->sqp_ah->qplib_ah);
+@@ -825,7 +856,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_
+ return rc;
+ }
+
+- bnxt_qplib_del_flush_qp(&qp->qplib_qp);
++ bnxt_qplib_clean_qp(&qp->qplib_qp);
+ rc = bnxt_qplib_destroy_qp(&rdev->qplib_res,
+ &rdev->qp1_sqp->qplib_qp);
+ if (rc) {
+@@ -1085,6 +1116,7 @@ struct ib_qp *bnxt_re_create_qp(struct i
+ goto fail;
+ }
+ qp->qplib_qp.scq = &cq->qplib_cq;
++ qp->scq = cq;
+ }
+
+ if (qp_init_attr->recv_cq) {
+@@ -1096,6 +1128,7 @@ struct ib_qp *bnxt_re_create_qp(struct i
+ goto fail;
+ }
+ qp->qplib_qp.rcq = &cq->qplib_cq;
++ qp->rcq = cq;
+ }
+
+ if (qp_init_attr->srq) {
+@@ -1385,7 +1418,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_q
+ dev_dbg(rdev_to_dev(rdev),
+ "Move QP = %p out of flush list\n",
+ qp);
+- bnxt_qplib_del_flush_qp(&qp->qplib_qp);
++ bnxt_qplib_clean_qp(&qp->qplib_qp);
+ }
+ }
+ if (qp_attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) {
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+@@ -80,6 +80,8 @@ struct bnxt_re_qp {
+ /* QP1 */
+ u32 send_psn;
+ struct ib_ud_header qp1_hdr;
++ struct bnxt_re_cq *scq;
++ struct bnxt_re_cq *rcq;
+ };
+
+ struct bnxt_re_cq {
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -115,7 +115,7 @@ void bnxt_qplib_add_flush_qp(struct bnxt
+ }
+ }
+
+-void bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp)
++void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp)
+ {
+ struct bnxt_qplib_cq *scq, *rcq;
+ unsigned long flags;
+@@ -1096,7 +1096,6 @@ int bnxt_qplib_destroy_qp(struct bnxt_qp
+ struct bnxt_qplib_rcfw *rcfw = res->rcfw;
+ struct cmdq_destroy_qp req;
+ struct creq_destroy_qp_resp resp;
+- unsigned long flags;
+ u16 cmd_flags = 0;
+ int rc;
+
+@@ -1114,18 +1113,13 @@ int bnxt_qplib_destroy_qp(struct bnxt_qp
+ return rc;
+ }
+
+- /* Must walk the associated CQs to nullified the QP ptr */
+- spin_lock_irqsave(&qp->scq->hwq.lock, flags);
++ return 0;
++}
+
+- __clean_cq(qp->scq, (u64)(unsigned long)qp);
+
+- if (qp->rcq && qp->rcq != qp->scq) {
+- spin_lock(&qp->rcq->hwq.lock);
+- __clean_cq(qp->rcq, (u64)(unsigned long)qp);
+- spin_unlock(&qp->rcq->hwq.lock);
+- }
+-
+- spin_unlock_irqrestore(&qp->scq->hwq.lock, flags);
++void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res,
++ struct bnxt_qplib_qp *qp)
++{
+
+ bnxt_qplib_free_qp_hdr_buf(res, qp);
+ bnxt_qplib_free_hwq(res->pdev, &qp->sq.hwq);
+@@ -1139,7 +1133,6 @@ int bnxt_qplib_destroy_qp(struct bnxt_qp
+ if (qp->orrq.max_elements)
+ bnxt_qplib_free_hwq(res->pdev, &qp->orrq);
+
+- return 0;
+ }
+
+ void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp,
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+@@ -449,6 +449,9 @@ int bnxt_qplib_create_qp(struct bnxt_qpl
+ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
+ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
+ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp);
++void bnxt_qplib_clean_qp(struct bnxt_qplib_qp *qp);
++void bnxt_qplib_free_qp_res(struct bnxt_qplib_res *res,
++ struct bnxt_qplib_qp *qp);
+ void *bnxt_qplib_get_qp1_sq_buf(struct bnxt_qplib_qp *qp,
+ struct bnxt_qplib_sge *sge);
+ void *bnxt_qplib_get_qp1_rq_buf(struct bnxt_qplib_qp *qp,
+@@ -470,7 +473,6 @@ void bnxt_qplib_req_notify_cq(struct bnx
+ void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq);
+ int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq);
+ void bnxt_qplib_add_flush_qp(struct bnxt_qplib_qp *qp);
+-void bnxt_qplib_del_flush_qp(struct bnxt_qplib_qp *qp);
+ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
+ struct bnxt_qplib_cqe *cqe,
+ int num_cqes);
diff --git a/series.conf b/series.conf
index d3102e7115..02693b6b6e 100644
--- a/series.conf
+++ b/series.conf
@@ -23236,6 +23236,7 @@
patches.drivers/ibmvnic-Clean-RX-pool-buffers-during-device-close.patch
patches.drivers/PCI-cxgb4-Extend-T3-PCI-quirk-to-T4-devices.patch
patches.drivers/RDMA-uverbs-Protect-from-command-mask-overflow.patch
+ patches.drivers/RDMA-bnxt_re-Synchronize-destroy_qp-with-poll_cq.patch
patches.drivers/scsi-mpt3sas-fix-an-out-of-bound-write
patches.drivers/scsi-qla2xxx-Fix-a-locking-imbalance-in-qlt_24xx_han.patch
patches.drivers/scsi-qla2xxx-Fix-double-free-bug-after-firmware-time.patch