Torsten Duwe d02d7f
From c690c7f6312ce69b426af08ae1da2b9e48a0246f Mon Sep 17 00:00:00 2001
Torsten Duwe d02d7f
From: Marco Chiappero <marco.chiappero@intel.com>
Torsten Duwe d02d7f
Date: Thu, 7 Apr 2022 17:54:51 +0100
Torsten Duwe d02d7f
Subject: [PATCH] crypto: qat - rework the VF2PF interrupt handling logic
Torsten Duwe d02d7f
Git-commit: c690c7f6312ce69b426af08ae1da2b9e48a0246f
Torsten Duwe d02d7f
Patch-mainline: v5.19-rc1
Torsten Duwe d02d7f
References: jsc#PED-1073
Torsten Duwe d02d7f
Torsten Duwe d02d7f
Change the VF2PF interrupt handler in the PF ISR and the definition of
Torsten Duwe d02d7f
the internal PFVF API to correct the current implementation, which can
Torsten Duwe d02d7f
result in missed interrupts.
Torsten Duwe d02d7f
Torsten Duwe d02d7f
More specifically, current HW generations consider a write to the mask
Torsten Duwe d02d7f
register, regardless of the value, as an acknowledge of any pending
Torsten Duwe d02d7f
VF2PF interrupt. Therefore, if there is an interrupt between the source
Torsten Duwe d02d7f
register read and the mask register write, such interrupt will not be
Torsten Duwe d02d7f
delivered and silently acknowledged, resulting in a lost VF2PF message.
Torsten Duwe d02d7f
Torsten Duwe d02d7f
To work around the problem, rather than disabling specific interrupts,
Torsten Duwe d02d7f
disable all the interrupts and re-enable only the ones that we are not
Torsten Duwe d02d7f
serving (excluding the already disabled ones too). This will force any
Torsten Duwe d02d7f
other pending interrupt to be triggered and be serviced by a subsequent
Torsten Duwe d02d7f
ISR.
Torsten Duwe d02d7f
Torsten Duwe d02d7f
This new approach requires, however, changes to the interrupt related
Torsten Duwe d02d7f
pfvf_ops functions. In particular, get_vf2pf_sources() has now been
Torsten Duwe d02d7f
removed in favor of disable_pending_vf2pf_interrupts(), which not only
Torsten Duwe d02d7f
retrieves and returns the pending (and enabled) sources, but also
Torsten Duwe d02d7f
disables them.
Torsten Duwe d02d7f
As a consequence, introduce the adf_disable_pending_vf2pf_interrupts()
Torsten Duwe d02d7f
utility in place of adf_disable_vf2pf_interrupts_irq(), which is no
Torsten Duwe d02d7f
longer needed.
Torsten Duwe d02d7f
Torsten Duwe d02d7f
Cc: stable@vger.kernel.org
Torsten Duwe d02d7f
Fixes: 993161d ("crypto: qat - fix handling of VF to PF interrupts")
Torsten Duwe d02d7f
Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Torsten Duwe d02d7f
Co-developed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe d02d7f
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe d02d7f
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Torsten Duwe d02d7f
Signed-off-by: Torsten Duwe <duwe@suse.de>
Torsten Duwe d02d7f
Torsten Duwe d02d7f
---
Torsten Duwe d02d7f
 .../crypto/qat/qat_common/adf_accel_devices.h |  2 +-
Torsten Duwe d02d7f
 drivers/crypto/qat/qat_common/adf_gen2_pfvf.c | 58 +++++++++-----
Torsten Duwe d02d7f
 drivers/crypto/qat/qat_common/adf_gen4_pfvf.c | 44 ++++++++---
Torsten Duwe d02d7f
 drivers/crypto/qat/qat_common/adf_isr.c       | 17 ++---
Torsten Duwe d02d7f
 .../qat/qat_dh895xcc/adf_dh895xcc_hw_data.c   | 76 +++++++++++++------
Torsten Duwe d02d7f
 5 files changed, 132 insertions(+), 65 deletions(-)
Torsten Duwe d02d7f
Torsten Duwe d02d7f
diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe d02d7f
index a03c6cf723312..dfa7ee41c5e9c 100644
Torsten Duwe d02d7f
--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe d02d7f
+++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe d02d7f
@@ -152,9 +152,9 @@ struct adf_pfvf_ops {
Torsten Duwe d02d7f
 	int (*enable_comms)(struct adf_accel_dev *accel_dev);
Torsten Duwe d02d7f
 	u32 (*get_pf2vf_offset)(u32 i);
Torsten Duwe d02d7f
 	u32 (*get_vf2pf_offset)(u32 i);
Torsten Duwe d02d7f
-	u32 (*get_vf2pf_sources)(void __iomem *pmisc_addr);
Torsten Duwe d02d7f
 	void (*enable_vf2pf_interrupts)(void __iomem *pmisc_addr, u32 vf_mask);
Torsten Duwe d02d7f
 	void (*disable_vf2pf_interrupts)(void __iomem *pmisc_addr, u32 vf_mask);
Torsten Duwe d02d7f
+	u32 (*disable_pending_vf2pf_interrupts)(void __iomem *pmisc_addr);
Torsten Duwe d02d7f
 	int (*send_msg)(struct adf_accel_dev *accel_dev, struct pfvf_message msg,
Torsten Duwe d02d7f
 			u32 pfvf_offset, struct mutex *csr_lock);
Torsten Duwe d02d7f
 	struct pfvf_message (*recv_msg)(struct adf_accel_dev *accel_dev,
Torsten Duwe d02d7f
diff --git a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
Torsten Duwe d02d7f
index 1a9072aac2ca9..def4cc8e1039a 100644
Torsten Duwe d02d7f
--- a/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
Torsten Duwe d02d7f
+++ b/drivers/crypto/qat/qat_common/adf_gen2_pfvf.c
Torsten Duwe d02d7f
@@ -13,6 +13,7 @@
Torsten Duwe d02d7f
 #include "adf_pfvf_utils.h"
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
  /* VF2PF interrupts */
Torsten Duwe d02d7f
+#define ADF_GEN2_VF_MSK			0xFFFF
Torsten Duwe d02d7f
 #define ADF_GEN2_ERR_REG_VF2PF(vf_src)	(((vf_src) & 0x01FFFE00) >> 9)
Torsten Duwe d02d7f
 #define ADF_GEN2_ERR_MSK_VF2PF(vf_mask)	(((vf_mask) & 0xFFFF) << 9)
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
@@ -50,23 +51,6 @@ static u32 adf_gen2_vf_get_pfvf_offset(u32 i)
Torsten Duwe d02d7f
 	return ADF_GEN2_VF_PF2VF_OFFSET;
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-static u32 adf_gen2_get_vf2pf_sources(void __iomem *pmisc_addr)
Torsten Duwe d02d7f
-{
Torsten Duwe d02d7f
-	u32 errsou3, errmsk3, vf_int_mask;
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
-	errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3);
Torsten Duwe d02d7f
-	vf_int_mask = ADF_GEN2_ERR_REG_VF2PF(errsou3);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	/* To avoid adding duplicate entries to work queue, clear
Torsten Duwe d02d7f
-	 * vf_int_mask_sets bits that are already masked in ERRMSK register.
Torsten Duwe d02d7f
-	 */
Torsten Duwe d02d7f
-	errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3);
Torsten Duwe d02d7f
-	vf_int_mask &= ~ADF_GEN2_ERR_REG_VF2PF(errmsk3);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	return vf_int_mask;
Torsten Duwe d02d7f
-}
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
 static void adf_gen2_enable_vf2pf_interrupts(void __iomem *pmisc_addr,
Torsten Duwe d02d7f
 					     u32 vf_mask)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
@@ -89,6 +73,44 @@ static void adf_gen2_disable_vf2pf_interrupts(void __iomem *pmisc_addr,
Torsten Duwe d02d7f
 	}
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
+static u32 adf_gen2_disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr)
Torsten Duwe d02d7f
+{
Torsten Duwe d02d7f
+	u32 sources, disabled, pending;
Torsten Duwe d02d7f
+	u32 errsou3, errmsk3;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
+	errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3);
Torsten Duwe d02d7f
+	sources = ADF_GEN2_ERR_REG_VF2PF(errsou3);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	if (!sources)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the already disabled interrupts */
Torsten Duwe d02d7f
+	errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3);
Torsten Duwe d02d7f
+	disabled = ADF_GEN2_ERR_REG_VF2PF(errmsk3);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	pending = sources & ~disabled;
Torsten Duwe d02d7f
+	if (!pending)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Due to HW limitations, when disabling the interrupts, we can't
Torsten Duwe d02d7f
+	 * just disable the requested sources, as this would lead to missed
Torsten Duwe d02d7f
+	 * interrupts if ERRSOU3 changes just before writing to ERRMSK3.
Torsten Duwe d02d7f
+	 * To work around it, disable all and re-enable only the sources that
Torsten Duwe d02d7f
+	 * are not in vf_mask and were not already disabled. Re-enabling will
Torsten Duwe d02d7f
+	 * trigger a new interrupt for the sources that have changed in the
Torsten Duwe d02d7f
+	 * meantime, if any.
Torsten Duwe d02d7f
+	 */
Torsten Duwe d02d7f
+	errmsk3 |= ADF_GEN2_ERR_MSK_VF2PF(ADF_GEN2_VF_MSK);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	errmsk3 &= ADF_GEN2_ERR_MSK_VF2PF(sources | disabled);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Return the sources of the (new) interrupt(s) */
Torsten Duwe d02d7f
+	return pending;
Torsten Duwe d02d7f
+}
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
 static u32 gen2_csr_get_int_bit(enum gen2_csr_pos offset)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
 	return ADF_PFVF_INT << offset;
Torsten Duwe d02d7f
@@ -362,9 +384,9 @@ void adf_gen2_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops)
Torsten Duwe d02d7f
 	pfvf_ops->enable_comms = adf_enable_pf2vf_comms;
Torsten Duwe d02d7f
 	pfvf_ops->get_pf2vf_offset = adf_gen2_pf_get_pfvf_offset;
Torsten Duwe d02d7f
 	pfvf_ops->get_vf2pf_offset = adf_gen2_pf_get_pfvf_offset;
Torsten Duwe d02d7f
-	pfvf_ops->get_vf2pf_sources = adf_gen2_get_vf2pf_sources;
Torsten Duwe d02d7f
 	pfvf_ops->enable_vf2pf_interrupts = adf_gen2_enable_vf2pf_interrupts;
Torsten Duwe d02d7f
 	pfvf_ops->disable_vf2pf_interrupts = adf_gen2_disable_vf2pf_interrupts;
Torsten Duwe d02d7f
+	pfvf_ops->disable_pending_vf2pf_interrupts = adf_gen2_disable_pending_vf2pf_interrupts;
Torsten Duwe d02d7f
 	pfvf_ops->send_msg = adf_gen2_pf2vf_send;
Torsten Duwe d02d7f
 	pfvf_ops->recv_msg = adf_gen2_vf2pf_recv;
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
diff --git a/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c b/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c
Torsten Duwe d02d7f
index f7860bf612da9..4061725b926df 100644
Torsten Duwe d02d7f
--- a/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c
Torsten Duwe d02d7f
+++ b/drivers/crypto/qat/qat_common/adf_gen4_pfvf.c
Torsten Duwe d02d7f
@@ -15,6 +15,7 @@
Torsten Duwe d02d7f
 /* VF2PF interrupt source registers */
Torsten Duwe d02d7f
 #define ADF_4XXX_VM2PF_SOU		0x41A180
Torsten Duwe d02d7f
 #define ADF_4XXX_VM2PF_MSK		0x41A1C0
Torsten Duwe d02d7f
+#define ADF_GEN4_VF_MSK			0xFFFF
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
 #define ADF_PFVF_GEN4_MSGTYPE_SHIFT	2
Torsten Duwe d02d7f
 #define ADF_PFVF_GEN4_MSGTYPE_MASK	0x3F
Torsten Duwe d02d7f
@@ -36,16 +37,6 @@ static u32 adf_gen4_pf_get_vf2pf_offset(u32 i)
Torsten Duwe d02d7f
 	return ADF_4XXX_VM2PF_OFFSET(i);
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-static u32 adf_gen4_get_vf2pf_sources(void __iomem *pmisc_addr)
Torsten Duwe d02d7f
-{
Torsten Duwe d02d7f
-	u32 sou, mask;
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	sou = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU);
Torsten Duwe d02d7f
-	mask = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	return sou & ~mask;
Torsten Duwe d02d7f
-}
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
 static void adf_gen4_enable_vf2pf_interrupts(void __iomem *pmisc_addr,
Torsten Duwe d02d7f
 					     u32 vf_mask)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
@@ -64,6 +55,37 @@ static void adf_gen4_disable_vf2pf_interrupts(void __iomem *pmisc_addr,
Torsten Duwe d02d7f
 	ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, val);
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
+static u32 adf_gen4_disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr)
Torsten Duwe d02d7f
+{
Torsten Duwe d02d7f
+	u32 sources, disabled, pending;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
+	sources = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_SOU);
Torsten Duwe d02d7f
+	if (!sources)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the already disabled interrupts */
Torsten Duwe d02d7f
+	disabled = ADF_CSR_RD(pmisc_addr, ADF_4XXX_VM2PF_MSK);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	pending = sources & ~disabled;
Torsten Duwe d02d7f
+	if (!pending)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Due to HW limitations, when disabling the interrupts, we can't
Torsten Duwe d02d7f
+	 * just disable the requested sources, as this would lead to missed
Torsten Duwe d02d7f
+	 * interrupts if VM2PF_SOU changes just before writing to VM2PF_MSK.
Torsten Duwe d02d7f
+	 * To work around it, disable all and re-enable only the sources that
Torsten Duwe d02d7f
+	 * are not in vf_mask and were not already disabled. Re-enabling will
Torsten Duwe d02d7f
+	 * trigger a new interrupt for the sources that have changed in the
Torsten Duwe d02d7f
+	 * meantime, if any.
Torsten Duwe d02d7f
+	 */
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, ADF_GEN4_VF_MSK);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_4XXX_VM2PF_MSK, disabled | sources);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Return the sources of the (new) interrupt(s) */
Torsten Duwe d02d7f
+	return pending;
Torsten Duwe d02d7f
+}
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
 static int adf_gen4_pfvf_send(struct adf_accel_dev *accel_dev,
Torsten Duwe d02d7f
 			      struct pfvf_message msg, u32 pfvf_offset,
Torsten Duwe d02d7f
 			      struct mutex *csr_lock)
Torsten Duwe d02d7f
@@ -121,9 +143,9 @@ void adf_gen4_init_pf_pfvf_ops(struct adf_pfvf_ops *pfvf_ops)
Torsten Duwe d02d7f
 	pfvf_ops->enable_comms = adf_enable_pf2vf_comms;
Torsten Duwe d02d7f
 	pfvf_ops->get_pf2vf_offset = adf_gen4_pf_get_pf2vf_offset;
Torsten Duwe d02d7f
 	pfvf_ops->get_vf2pf_offset = adf_gen4_pf_get_vf2pf_offset;
Torsten Duwe d02d7f
-	pfvf_ops->get_vf2pf_sources = adf_gen4_get_vf2pf_sources;
Torsten Duwe d02d7f
 	pfvf_ops->enable_vf2pf_interrupts = adf_gen4_enable_vf2pf_interrupts;
Torsten Duwe d02d7f
 	pfvf_ops->disable_vf2pf_interrupts = adf_gen4_disable_vf2pf_interrupts;
Torsten Duwe d02d7f
+	pfvf_ops->disable_pending_vf2pf_interrupts = adf_gen4_disable_pending_vf2pf_interrupts;
Torsten Duwe d02d7f
 	pfvf_ops->send_msg = adf_gen4_pfvf_send;
Torsten Duwe d02d7f
 	pfvf_ops->recv_msg = adf_gen4_pfvf_recv;
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
diff --git a/drivers/crypto/qat/qat_common/adf_isr.c b/drivers/crypto/qat/qat_common/adf_isr.c
Torsten Duwe d02d7f
index a35149f8bf1ee..23f7fff32c642 100644
Torsten Duwe d02d7f
--- a/drivers/crypto/qat/qat_common/adf_isr.c
Torsten Duwe d02d7f
+++ b/drivers/crypto/qat/qat_common/adf_isr.c
Torsten Duwe d02d7f
@@ -76,32 +76,29 @@ void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
Torsten Duwe d02d7f
 	spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-static void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev,
Torsten Duwe d02d7f
-					     u32 vf_mask)
Torsten Duwe d02d7f
+static u32 adf_disable_pending_vf2pf_interrupts(struct adf_accel_dev *accel_dev)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
 	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
Torsten Duwe d02d7f
+	u32 pending;
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
 	spin_lock(&accel_dev->pf.vf2pf_ints_lock);
Torsten Duwe d02d7f
-	GET_PFVF_OPS(accel_dev)->disable_vf2pf_interrupts(pmisc_addr, vf_mask);
Torsten Duwe d02d7f
+	pending = GET_PFVF_OPS(accel_dev)->disable_pending_vf2pf_interrupts(pmisc_addr);
Torsten Duwe d02d7f
 	spin_unlock(&accel_dev->pf.vf2pf_ints_lock);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	return pending;
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
 static bool adf_handle_vf2pf_int(struct adf_accel_dev *accel_dev)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
-	void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
Torsten Duwe d02d7f
 	bool irq_handled = false;
Torsten Duwe d02d7f
 	unsigned long vf_mask;
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
-	vf_mask = GET_PFVF_OPS(accel_dev)->get_vf2pf_sources(pmisc_addr);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
+	/* Get the interrupt sources triggered by VFs, except for those already disabled */
Torsten Duwe d02d7f
+	vf_mask = adf_disable_pending_vf2pf_interrupts(accel_dev);
Torsten Duwe d02d7f
 	if (vf_mask) {
Torsten Duwe d02d7f
 		struct adf_accel_vf_info *vf_info;
Torsten Duwe d02d7f
 		int i;
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-		/* Disable VF2PF interrupts for VFs with pending ints */
Torsten Duwe d02d7f
-		adf_disable_vf2pf_interrupts_irq(accel_dev, vf_mask);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
 		/*
Torsten Duwe d02d7f
 		 * Handle VF2PF interrupt unless the VF is malicious and
Torsten Duwe d02d7f
 		 * is attempting to flood the host OS with VF2PF interrupts.
Torsten Duwe d02d7f
diff --git a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
Torsten Duwe d02d7f
index 7375436ac1b83..86187671893c4 100644
Torsten Duwe d02d7f
--- a/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
Torsten Duwe d02d7f
+++ b/drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
Torsten Duwe d02d7f
@@ -7,6 +7,8 @@
Torsten Duwe d02d7f
 #include "adf_dh895xcc_hw_data.h"
Torsten Duwe d02d7f
 #include "icp_qat_hw.h"
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
+#define ADF_DH895XCC_VF_MSK	0xFFFFFFFF
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
 /* Worker thread to service arbiter mappings */
Torsten Duwe d02d7f
 static const u32 thrd_to_arb_map[ADF_DH895XCC_MAX_ACCELENGINES] = {
Torsten Duwe d02d7f
 	0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
Torsten Duwe d02d7f
@@ -107,29 +109,6 @@ static const u32 *adf_get_arbiter_mapping(void)
Torsten Duwe d02d7f
 	return thrd_to_arb_map;
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-static u32 get_vf2pf_sources(void __iomem *pmisc_bar)
Torsten Duwe d02d7f
-{
Torsten Duwe d02d7f
-	u32 errsou3, errmsk3, errsou5, errmsk5, vf_int_mask;
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
-	errsou3 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRSOU3);
Torsten Duwe d02d7f
-	vf_int_mask = ADF_DH895XCC_ERR_REG_VF2PF_L(errsou3);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	/* To avoid adding duplicate entries to work queue, clear
Torsten Duwe d02d7f
-	 * vf_int_mask_sets bits that are already masked in ERRMSK register.
Torsten Duwe d02d7f
-	 */
Torsten Duwe d02d7f
-	errmsk3 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRMSK3);
Torsten Duwe d02d7f
-	vf_int_mask &= ~ADF_DH895XCC_ERR_REG_VF2PF_L(errmsk3);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	/* Do the same for ERRSOU5 */
Torsten Duwe d02d7f
-	errsou5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRSOU5);
Torsten Duwe d02d7f
-	errmsk5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRMSK5);
Torsten Duwe d02d7f
-	vf_int_mask |= ADF_DH895XCC_ERR_REG_VF2PF_U(errsou5);
Torsten Duwe d02d7f
-	vf_int_mask &= ~ADF_DH895XCC_ERR_REG_VF2PF_U(errmsk5);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
-	return vf_int_mask;
Torsten Duwe d02d7f
-}
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
 static void enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
 	/* Enable VF2PF Messaging Ints - VFs 0 through 15 per vf_mask[15:0] */
Torsten Duwe d02d7f
@@ -143,7 +122,6 @@ static void enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
Torsten Duwe d02d7f
 	if (vf_mask >> 16) {
Torsten Duwe d02d7f
 		u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5)
Torsten Duwe d02d7f
 			  & ~ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask);
Torsten Duwe d02d7f
-
Torsten Duwe d02d7f
 		ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val);
Torsten Duwe d02d7f
 	}
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
@@ -166,6 +144,54 @@ static void disable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
Torsten Duwe d02d7f
 	}
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
+static u32 disable_pending_vf2pf_interrupts(void __iomem *pmisc_addr)
Torsten Duwe d02d7f
+{
Torsten Duwe d02d7f
+	u32 sources, pending, disabled;
Torsten Duwe d02d7f
+	u32 errsou3, errmsk3;
Torsten Duwe d02d7f
+	u32 errsou5, errmsk5;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the interrupt sources triggered by VFs */
Torsten Duwe d02d7f
+	errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3);
Torsten Duwe d02d7f
+	errsou5 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU5);
Torsten Duwe d02d7f
+	sources = ADF_DH895XCC_ERR_REG_VF2PF_L(errsou3)
Torsten Duwe d02d7f
+		  | ADF_DH895XCC_ERR_REG_VF2PF_U(errsou5);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	if (!sources)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Get the already disabled interrupts */
Torsten Duwe d02d7f
+	errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3);
Torsten Duwe d02d7f
+	errmsk5 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5);
Torsten Duwe d02d7f
+	disabled = ADF_DH895XCC_ERR_REG_VF2PF_L(errmsk3)
Torsten Duwe d02d7f
+		   | ADF_DH895XCC_ERR_REG_VF2PF_U(errmsk5);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	pending = sources & ~disabled;
Torsten Duwe d02d7f
+	if (!pending)
Torsten Duwe d02d7f
+		return 0;
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Due to HW limitations, when disabling the interrupts, we can't
Torsten Duwe d02d7f
+	 * just disable the requested sources, as this would lead to missed
Torsten Duwe d02d7f
+	 * interrupts if sources changes just before writing to ERRMSK3 and
Torsten Duwe d02d7f
+	 * ERRMSK5.
Torsten Duwe d02d7f
+	 * To work around it, disable all and re-enable only the sources that
Torsten Duwe d02d7f
+	 * are not in vf_mask and were not already disabled. Re-enabling will
Torsten Duwe d02d7f
+	 * trigger a new interrupt for the sources that have changed in the
Torsten Duwe d02d7f
+	 * meantime, if any.
Torsten Duwe d02d7f
+	 */
Torsten Duwe d02d7f
+	errmsk3 |= ADF_DH895XCC_ERR_MSK_VF2PF_L(ADF_DH895XCC_VF_MSK);
Torsten Duwe d02d7f
+	errmsk5 |= ADF_DH895XCC_ERR_MSK_VF2PF_U(ADF_DH895XCC_VF_MSK);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, errmsk5);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	errmsk3 &= ADF_DH895XCC_ERR_MSK_VF2PF_L(sources | disabled);
Torsten Duwe d02d7f
+	errmsk5 &= ADF_DH895XCC_ERR_MSK_VF2PF_U(sources | disabled);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, errmsk3);
Torsten Duwe d02d7f
+	ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, errmsk5);
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
+	/* Return the sources of the (new) interrupt(s) */
Torsten Duwe d02d7f
+	return pending;
Torsten Duwe d02d7f
+}
Torsten Duwe d02d7f
+
Torsten Duwe d02d7f
 static void configure_iov_threads(struct adf_accel_dev *accel_dev, bool enable)
Torsten Duwe d02d7f
 {
Torsten Duwe d02d7f
 	adf_gen2_cfg_iov_thds(accel_dev, enable,
Torsten Duwe d02d7f
@@ -213,9 +239,9 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
Torsten Duwe d02d7f
 	hw_data->disable_iov = adf_disable_sriov;
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
 	adf_gen2_init_pf_pfvf_ops(&hw_data->pfvf_ops);
Torsten Duwe d02d7f
-	hw_data->pfvf_ops.get_vf2pf_sources = get_vf2pf_sources;
Torsten Duwe d02d7f
 	hw_data->pfvf_ops.enable_vf2pf_interrupts = enable_vf2pf_interrupts;
Torsten Duwe d02d7f
 	hw_data->pfvf_ops.disable_vf2pf_interrupts = disable_vf2pf_interrupts;
Torsten Duwe d02d7f
+	hw_data->pfvf_ops.disable_pending_vf2pf_interrupts = disable_pending_vf2pf_interrupts;
Torsten Duwe d02d7f
 	adf_gen2_init_hw_csr_ops(&hw_data->csr_ops);
Torsten Duwe d02d7f
 }
Torsten Duwe d02d7f
 
Torsten Duwe d02d7f
-- 
Torsten Duwe d02d7f
2.35.3
Torsten Duwe d02d7f