From 02966cd5857839d0b7feadf0a1a1dbd6ea3c9abc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Trivi=C3=B1o?= Date: Tue, 7 Jun 2016 16:24:20 +0200 Subject: [PATCH] sif: sif_r3: fix sif_r3_recreate_flush_qp soft lockup. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This commit fixes Orabug: #23540257. It prevents the situation where the flush_retry_qp is used before the sdev->flush_lock has been initialized. This occurs when IB_EVENT_LID_CHANGE event is received before the flush_retry_qp is created by the driver. Signed-off-by: Triviño Reviewed-by: Knut Omang --- drivers/infiniband/hw/sif/sif_main.c | 4 ++++ drivers/infiniband/hw/sif/sif_r3.c | 8 ++++++-- drivers/infiniband/hw/sif/sif_r3.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/sif/sif_main.c b/drivers/infiniband/hw/sif/sif_main.c index b6e0e0e37b63..3e33f40d9e16 100644 --- a/drivers/infiniband/hw/sif/sif_main.c +++ b/drivers/infiniband/hw/sif/sif_main.c @@ -313,6 +313,10 @@ static int sif_probe(struct pci_dev *pdev, if (err) goto pfail_bar; + /* This must be done before events reception - see Orabug: 23540257 */ + if (PSIF_REVISION(sdev) <= 3) + sif_r3_pre_init(sdev); + if (xen_pv_domain()) { /* The Xen PV domain may return huge pages that are misaligned * in DMA space, see Orabug: 21690736. diff --git a/drivers/infiniband/hw/sif/sif_r3.c b/drivers/infiniband/hw/sif/sif_r3.c index 679cc7b9cf25..4b4205de0539 100644 --- a/drivers/infiniband/hw/sif/sif_r3.c +++ b/drivers/infiniband/hw/sif/sif_r3.c @@ -31,6 +31,12 @@ static int outstanding_wqes(struct sif_dev *sdev, struct sif_qp *qp, u16 *head); static u16 cq_walk_wa4074(struct sif_dev *sdev, struct sif_qp *qp, bool *last_seq_set); static u16 walk_and_update_cqes(struct sif_dev *sdev, struct sif_qp *qp, u16 head, u16 end); +void sif_r3_pre_init(struct sif_dev *sdev) +{ + /* Init the flush_retry qp lock */ + mutex_init(&sdev->flush_lock); +} + int sif_r3_init(struct sif_dev *sdev) { int ret; @@ -46,8 +52,6 @@ int sif_r3_init(struct sif_dev *sdev) dne_qp_alloc = true; } - /* Init the flush_retry qp lock */ - mutex_init(&sdev->flush_lock); ret = sif_hw_allocate_flush_qp(sdev); if (ret) goto flush_retry_failed; diff --git a/drivers/infiniband/hw/sif/sif_r3.h b/drivers/infiniband/hw/sif/sif_r3.h index 6fffc755952f..7086483ac2f8 100644 --- a/drivers/infiniband/hw/sif/sif_r3.h +++ b/drivers/infiniband/hw/sif/sif_r3.h @@ -14,6 +14,7 @@ #ifndef _SIF_R3_H #define _SIF_R3_H +void sif_r3_pre_init(struct sif_dev *sdev); int sif_r3_init(struct sif_dev *sdev); void sif_r3_deinit(struct sif_dev *sdev); -- 2.50.1