Torsten Duwe 59ae09
From 8af4a436e665201872348aa2ba6e7033d4c17823 Mon Sep 17 00:00:00 2001
Torsten Duwe 59ae09
From: Ahsan Atta <ahsan.atta@intel.com>
Torsten Duwe 59ae09
Date: Thu, 12 Aug 2021 21:21:27 +0100
Torsten Duwe 59ae09
Subject: [PATCH] crypto: qat - flush vf workqueue at driver removal
Torsten Duwe 59ae09
Git-commit: 8af4a436e665201872348aa2ba6e7033d4c17823
Torsten Duwe 59ae09
Patch-mainline: v5.15-rc1
Torsten Duwe 59ae09
References: jsc#PED-1073
Torsten Duwe 59ae09
Torsten Duwe 59ae09
There is a race condition during shutdown in adf_disable_sriov() where
Torsten Duwe 59ae09
both the PF and the VF drivers are loaded on the host system.
Torsten Duwe 59ae09
The PF notifies a VF with a "RESTARTING" message due to which the VF
Torsten Duwe 59ae09
starts an asynchronous worker to stop and shutdown itself.
Torsten Duwe 59ae09
At the same time the PF calls pci_disable_sriov() which invokes the
Torsten Duwe 59ae09
remove() routine on the VF device driver triggering the shutdown flow
Torsten Duwe 59ae09
again.
Torsten Duwe 59ae09
Torsten Duwe 59ae09
This change fixes the problem by ensuring that the VF flushes the worker
Torsten Duwe 59ae09
that performs stop()/shutdown() before these two functions are called in
Torsten Duwe 59ae09
the remove(). To make sure that no additional PV/VF messages are
Torsten Duwe 59ae09
processed by the VF, interrupts are disabled before flushing the
Torsten Duwe 59ae09
workqueue.
Torsten Duwe 59ae09
Torsten Duwe 59ae09
Signed-off-by: Ahsan Atta <ahsan.atta@intel.com>
Torsten Duwe 59ae09
Co-developed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe 59ae09
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe 59ae09
Reviewed-by: Fiona Trahe <fiona.trahe@intel.com>
Torsten Duwe 59ae09
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Torsten Duwe 59ae09
Signed-off-by: Torsten Duwe <duwe@suse.de>
Torsten Duwe 59ae09
Torsten Duwe 59ae09
---
Torsten Duwe 59ae09
 drivers/crypto/qat/qat_c3xxxvf/adf_drv.c      |  1 +
Torsten Duwe 59ae09
 drivers/crypto/qat/qat_c62xvf/adf_drv.c       |  1 +
Torsten Duwe 59ae09
 .../crypto/qat/qat_common/adf_common_drv.h    |  5 ++++
Torsten Duwe 59ae09
 drivers/crypto/qat/qat_common/adf_vf_isr.c    | 25 +++++++++++++++++++
Torsten Duwe 59ae09
 drivers/crypto/qat/qat_dh895xccvf/adf_drv.c   |  1 +
Torsten Duwe 59ae09
 5 files changed, 33 insertions(+)
Torsten Duwe 59ae09
Torsten Duwe 59ae09
diff --git a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
Torsten Duwe 59ae09
index 7ef5a5185d292..1df1b868978d9 100644
Torsten Duwe 59ae09
--- a/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
Torsten Duwe 59ae09
+++ b/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
Torsten Duwe 59ae09
@@ -211,6 +211,7 @@ static void adf_remove(struct pci_dev *pdev)
Torsten Duwe 59ae09
 		pr_err("QAT: Driver removal failed\n");
Torsten Duwe 59ae09
 		return;
Torsten Duwe 59ae09
 	}
Torsten Duwe 59ae09
+	adf_flush_vf_wq(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_stop(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_shutdown(accel_dev);
Torsten Duwe 59ae09
 	adf_cleanup_accel(accel_dev);
Torsten Duwe 59ae09
diff --git a/drivers/crypto/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/qat/qat_c62xvf/adf_drv.c
Torsten Duwe 59ae09
index c91beedd267c5..8103bd81d617a 100644
Torsten Duwe 59ae09
--- a/drivers/crypto/qat/qat_c62xvf/adf_drv.c
Torsten Duwe 59ae09
+++ b/drivers/crypto/qat/qat_c62xvf/adf_drv.c
Torsten Duwe 59ae09
@@ -211,6 +211,7 @@ static void adf_remove(struct pci_dev *pdev)
Torsten Duwe 59ae09
 		pr_err("QAT: Driver removal failed\n");
Torsten Duwe 59ae09
 		return;
Torsten Duwe 59ae09
 	}
Torsten Duwe 59ae09
+	adf_flush_vf_wq(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_stop(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_shutdown(accel_dev);
Torsten Duwe 59ae09
 	adf_cleanup_accel(accel_dev);
Torsten Duwe 59ae09
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe 59ae09
index 4b18843f9845f..4261749fae8d4 100644
Torsten Duwe 59ae09
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe 59ae09
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe 59ae09
@@ -207,6 +207,7 @@ int adf_init_pf_wq(void);
Torsten Duwe 59ae09
 void adf_exit_pf_wq(void);
Torsten Duwe 59ae09
 int adf_init_vf_wq(void);
Torsten Duwe 59ae09
 void adf_exit_vf_wq(void);
Torsten Duwe 59ae09
+void adf_flush_vf_wq(struct adf_accel_dev *accel_dev);
Torsten Duwe 59ae09
 #else
Torsten Duwe 59ae09
 #define adf_sriov_configure NULL
Torsten Duwe 59ae09
 
Torsten Duwe 59ae09
@@ -249,5 +250,9 @@ static inline void adf_exit_vf_wq(void)
Torsten Duwe 59ae09
 {
Torsten Duwe 59ae09
 }
Torsten Duwe 59ae09
 
Torsten Duwe 59ae09
+static inline void adf_flush_vf_wq(struct adf_accel_dev *accel_dev)
Torsten Duwe 59ae09
+{
Torsten Duwe 59ae09
+}
Torsten Duwe 59ae09
+
Torsten Duwe 59ae09
 #endif
Torsten Duwe 59ae09
 #endif
Torsten Duwe 59ae09
diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c
Torsten Duwe 59ae09
index 078f33d583e8c..7828a6573f3e2 100644
Torsten Duwe 59ae09
--- a/drivers/crypto/qat/qat_common/adf_vf_isr.c
Torsten Duwe 59ae09
+++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c
Torsten Duwe 59ae09
@@ -48,6 +48,7 @@ void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev)
Torsten Duwe 59ae09
 
Torsten Duwe 59ae09
 	ADF_CSR_WR(pmisc_bar_addr, ADF_VINTMSK_OFFSET, 0x2);
Torsten Duwe 59ae09
 }
Torsten Duwe 59ae09
+EXPORT_SYMBOL_GPL(adf_disable_pf2vf_interrupts);
Torsten Duwe 59ae09
 
Torsten Duwe 59ae09
 static int adf_enable_msi(struct adf_accel_dev *accel_dev)
Torsten Duwe 59ae09
 {
Torsten Duwe 59ae09
@@ -316,6 +317,30 @@ err_out:
Torsten Duwe 59ae09
 }
Torsten Duwe 59ae09
 EXPORT_SYMBOL_GPL(adf_vf_isr_resource_alloc);
Torsten Duwe 59ae09
 
Torsten Duwe 59ae09
+/**
Torsten Duwe 59ae09
+ * adf_flush_vf_wq() - Flush workqueue for VF
Torsten Duwe 59ae09
+ * @accel_dev:  Pointer to acceleration device.
Torsten Duwe 59ae09
+ *
Torsten Duwe 59ae09
+ * Function disables the PF/VF interrupts on the VF so that no new messages
Torsten Duwe 59ae09
+ * are received and flushes the workqueue 'adf_vf_stop_wq'.
Torsten Duwe 59ae09
+ *
Torsten Duwe 59ae09
+ * Return: void.
Torsten Duwe 59ae09
+ */
Torsten Duwe 59ae09
+void adf_flush_vf_wq(struct adf_accel_dev *accel_dev)
Torsten Duwe 59ae09
+{
Torsten Duwe 59ae09
+	adf_disable_pf2vf_interrupts(accel_dev);
Torsten Duwe 59ae09
+
Torsten Duwe 59ae09
+	flush_workqueue(adf_vf_stop_wq);
Torsten Duwe 59ae09
+}
Torsten Duwe 59ae09
+EXPORT_SYMBOL_GPL(adf_flush_vf_wq);
Torsten Duwe 59ae09
+
Torsten Duwe 59ae09
+/**
Torsten Duwe 59ae09
+ * adf_init_vf_wq() - Init workqueue for VF
Torsten Duwe 59ae09
+ *
Torsten Duwe 59ae09
+ * Function init workqueue 'adf_vf_stop_wq' for VF.
Torsten Duwe 59ae09
+ *
Torsten Duwe 59ae09
+ * Return: 0 on success, error code otherwise.
Torsten Duwe 59ae09
+ */
Torsten Duwe 59ae09
 int __init adf_init_vf_wq(void)
Torsten Duwe 59ae09
 {
Torsten Duwe 59ae09
 	adf_vf_stop_wq = alloc_workqueue("adf_vf_stop_wq", WQ_MEM_RECLAIM, 0);
Torsten Duwe 59ae09
diff --git a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
Torsten Duwe 59ae09
index d332b68795f2c..99d90f3ea2b79 100644
Torsten Duwe 59ae09
--- a/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
Torsten Duwe 59ae09
+++ b/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
Torsten Duwe 59ae09
@@ -211,6 +211,7 @@ static void adf_remove(struct pci_dev *pdev)
Torsten Duwe 59ae09
 		pr_err("QAT: Driver removal failed\n");
Torsten Duwe 59ae09
 		return;
Torsten Duwe 59ae09
 	}
Torsten Duwe 59ae09
+	adf_flush_vf_wq(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_stop(accel_dev);
Torsten Duwe 59ae09
 	adf_dev_shutdown(accel_dev);
Torsten Duwe 59ae09
 	adf_cleanup_accel(accel_dev);
Torsten Duwe 59ae09
-- 
Torsten Duwe 59ae09
2.35.3
Torsten Duwe 59ae09