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