crypto: qat - fix handling of VF to PF interrupts
authorMarco Chiappero <marco.chiappero@intel.com>
Tue, 28 Sep 2021 11:44:32 +0000 (12:44 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 8 Oct 2021 12:02:40 +0000 (20:02 +0800)
Currently, VF to PF interrupt handling is based on the DH895XCC device
behavior, which is not entirely common to all devices.

In order to make interrupt detection and handling correct for all of the
supported devices, make the interrupt handling device specific by:
 - introducing get_vf2pf_sources() for getting a 32 bits long value
   where each bit represents a vf2pf interrupt;
 - adding the device [enable|disable]_vf2pf_interrupts to hw_data;
 - defining [enable|disable]_vf2pf_interrupts for all the devices that
   are currently supported, using only their required and specific
   ERRSOU|ERRMASK registers (DH895XCC has 32 interrupts spread across
   ERRSOU3 and ERRSOU5, C62X/C3XXX has 16 in ERRSOU3 only, etc).
Code has been shared by different devices wherever possible.

This patch is based on earlier work done by Salvatore Benedetto.

Signed-off-by: Marco Chiappero <marco.chiappero@intel.com>
Co-developed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/qat/qat_c3xxx/adf_c3xxx_hw_data.c
drivers/crypto/qat/qat_c62x/adf_c62x_hw_data.c
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/adf_gen2_hw_data.c
drivers/crypto/qat/qat_common/adf_gen2_hw_data.h
drivers/crypto/qat/qat_common/adf_isr.c
drivers/crypto/qat/qat_common/adf_pf2vf_msg.c
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c
drivers/crypto/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h

index 3027c01bc89e2717d033c4a09168e80cdb3ee141..b9bd52eaa1848ce75209b797f2034dcb42dae2a7 100644 (file)
@@ -206,6 +206,9 @@ void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data)
        hw_data->reset_device = adf_reset_flr;
        hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer;
        hw_data->get_pf2vf_offset = get_pf2vf_offset;
+       hw_data->get_vf2pf_sources = adf_gen2_get_vf2pf_sources;
+       hw_data->enable_vf2pf_interrupts = adf_gen2_enable_vf2pf_interrupts;
+       hw_data->disable_vf2pf_interrupts = adf_gen2_disable_vf2pf_interrupts;
        hw_data->enable_pfvf_comms = adf_enable_pf2vf_comms;
        hw_data->disable_iov = adf_disable_sriov;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPAT_THIS_VERSION;
index b023c80873bb5336c63e5fd46b1740d91880e207..f28dae0982bc1b5ff0a6fdd842fa5fd7c9adb7c3 100644 (file)
@@ -208,6 +208,9 @@ void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data)
        hw_data->reset_device = adf_reset_flr;
        hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer;
        hw_data->get_pf2vf_offset = get_pf2vf_offset;
+       hw_data->get_vf2pf_sources = adf_gen2_get_vf2pf_sources;
+       hw_data->enable_vf2pf_interrupts = adf_gen2_enable_vf2pf_interrupts;
+       hw_data->disable_vf2pf_interrupts = adf_gen2_disable_vf2pf_interrupts;
        hw_data->enable_pfvf_comms = adf_enable_pf2vf_comms;
        hw_data->disable_iov = adf_disable_sriov;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPAT_THIS_VERSION;
index ca8e23f0bcc47e90fd488664f1f5eb2ae2ab0823..57d9ca08e61153583e0377a9b6fb7cc9360b9b39 100644 (file)
@@ -177,6 +177,11 @@ struct adf_hw_device_data {
        void (*enable_ints)(struct adf_accel_dev *accel_dev);
        void (*set_ssm_wdtimer)(struct adf_accel_dev *accel_dev);
        int (*enable_pfvf_comms)(struct adf_accel_dev *accel_dev);
+       u32 (*get_vf2pf_sources)(void __iomem *pmisc_addr);
+       void (*enable_vf2pf_interrupts)(void __iomem *pmisc_bar_addr,
+                                       u32 vf_mask);
+       void (*disable_vf2pf_interrupts)(void __iomem *pmisc_bar_addr,
+                                        u32 vf_mask);
        void (*reset_device)(struct adf_accel_dev *accel_dev);
        void (*set_msix_rttable)(struct adf_accel_dev *accel_dev);
        char *(*uof_get_name)(u32 obj_num);
index 9e560c7d416307aaef29f65c64b89c9f58fc50ca..56691801277823de7fe2ef9eae9cc6013bd7e420 100644 (file)
@@ -4,6 +4,46 @@
 #include "icp_qat_hw.h"
 #include <linux/pci.h>
 
+u32 adf_gen2_get_vf2pf_sources(void __iomem *pmisc_addr)
+{
+       u32 errsou3, errmsk3, vf_int_mask;
+
+       /* Get the interrupt sources triggered by VFs */
+       errsou3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRSOU3);
+       vf_int_mask = ADF_GEN2_ERR_REG_VF2PF(errsou3);
+
+       /* To avoid adding duplicate entries to work queue, clear
+        * vf_int_mask_sets bits that are already masked in ERRMSK register.
+        */
+       errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3);
+       vf_int_mask &= ~ADF_GEN2_ERR_REG_VF2PF(errmsk3);
+
+       return vf_int_mask;
+}
+EXPORT_SYMBOL_GPL(adf_gen2_get_vf2pf_sources);
+
+void adf_gen2_enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
+{
+       /* Enable VF2PF Messaging Ints - VFs 0 through 15 per vf_mask[15:0] */
+       if (vf_mask & 0xFFFF) {
+               u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3)
+                         & ~ADF_GEN2_ERR_MSK_VF2PF(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val);
+       }
+}
+EXPORT_SYMBOL_GPL(adf_gen2_enable_vf2pf_interrupts);
+
+void adf_gen2_disable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
+{
+       /* Disable VF2PF interrupts for VFs 0 through 15 per vf_mask[15:0] */
+       if (vf_mask & 0xFFFF) {
+               u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK3)
+                         | ADF_GEN2_ERR_MSK_VF2PF(vf_mask);
+               ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK3, val);
+       }
+}
+EXPORT_SYMBOL_GPL(adf_gen2_disable_vf2pf_interrupts);
+
 void adf_gen2_cfg_iov_thds(struct adf_accel_dev *accel_dev, bool enable,
                           int num_a_regs, int num_b_regs)
 {
index 756b0ddfac5e16661ff1f7724ca06afa877a764d..3486e51aad75b933c5eb6d7d9a2abc65f5858865 100644 (file)
@@ -125,6 +125,18 @@ do { \
 #define ADF_SSMWDT(i)          (ADF_SSMWDT_OFFSET + ((i) * 0x4000))
 #define ADF_SSMWDTPKE(i)       (ADF_SSMWDTPKE_OFFSET + ((i) * 0x4000))
 
+ /* VF2PF interrupts */
+#define ADF_GEN2_ERRSOU3 (0x3A000 + 0x0C)
+#define ADF_GEN2_ERRSOU5 (0x3A000 + 0xD8)
+#define ADF_GEN2_ERRMSK3 (0x3A000 + 0x1C)
+#define ADF_GEN2_ERRMSK5 (0x3A000 + 0xDC)
+#define ADF_GEN2_ERR_REG_VF2PF(vf_src) (((vf_src) & 0x01FFFE00) >> 9)
+#define ADF_GEN2_ERR_MSK_VF2PF(vf_mask)        (((vf_mask) & 0xFFFF) << 9)
+
+u32 adf_gen2_get_vf2pf_sources(void __iomem *pmisc_bar);
+void adf_gen2_enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask);
+void adf_gen2_disable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask);
+
 void adf_gen2_cfg_iov_thds(struct adf_accel_dev *accel_dev, bool enable,
                           int num_a_regs, int num_b_regs);
 void adf_gen2_init_hw_csr_ops(struct adf_hw_csr_ops *csr_ops);
index c55a9f14b0d23b66a6b282700444ca9b0dd74f17..40593c9449a20a29bc0ec98657a0376fb4be6696 100644 (file)
 #include "adf_transport_internal.h"
 
 #define ADF_MAX_NUM_VFS        32
-#define ADF_ERRSOU3    (0x3A000 + 0x0C)
-#define ADF_ERRSOU5    (0x3A000 + 0xD8)
-#define ADF_ERRMSK3    (0x3A000 + 0x1C)
-#define ADF_ERRMSK5    (0x3A000 + 0xDC)
-#define ADF_ERR_REG_VF2PF_L(vf_src)    (((vf_src) & 0x01FFFE00) >> 9)
-#define ADF_ERR_REG_VF2PF_U(vf_src)    (((vf_src) & 0x0000FFFF) << 16)
 
 static int adf_enable_msix(struct adf_accel_dev *accel_dev)
 {
@@ -71,22 +65,10 @@ static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
                struct adf_bar *pmisc =
                        &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
                void __iomem *pmisc_addr = pmisc->virt_addr;
-               u32 errsou3, errsou5, errmsk3, errmsk5;
                unsigned long vf_mask;
 
                /* Get the interrupt sources triggered by VFs */
-               errsou3 = ADF_CSR_RD(pmisc_addr, ADF_ERRSOU3);
-               errsou5 = ADF_CSR_RD(pmisc_addr, ADF_ERRSOU5);
-               vf_mask = ADF_ERR_REG_VF2PF_L(errsou3);
-               vf_mask |= ADF_ERR_REG_VF2PF_U(errsou5);
-
-               /* To avoid adding duplicate entries to work queue, clear
-                * vf_int_mask_sets bits that are already masked in ERRMSK register.
-                */
-               errmsk3 = ADF_CSR_RD(pmisc_addr, ADF_ERRMSK3);
-               errmsk5 = ADF_CSR_RD(pmisc_addr, ADF_ERRMSK5);
-               vf_mask &= ~ADF_ERR_REG_VF2PF_L(errmsk3);
-               vf_mask &= ~ADF_ERR_REG_VF2PF_U(errmsk5);
+               vf_mask = hw_data->get_vf2pf_sources(pmisc_addr);
 
                if (vf_mask) {
                        struct adf_accel_vf_info *vf_info;
index d3f6ff68d45d9339d3785e406fc0410b81692e11..cdef6c34524e4791c2b441ddaf744ea9d8a97363 100644 (file)
@@ -5,82 +5,42 @@
 #include "adf_common_drv.h"
 #include "adf_pf2vf_msg.h"
 
-#define ADF_DH895XCC_EP_OFFSET 0x3A000
-#define ADF_DH895XCC_ERRMSK3   (ADF_DH895XCC_EP_OFFSET + 0x1C)
-#define ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask) ((vf_mask & 0xFFFF) << 9)
-#define ADF_DH895XCC_ERRMSK5   (ADF_DH895XCC_EP_OFFSET + 0xDC)
-#define ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask) (vf_mask >> 16)
-
-static void __adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
-                                         u32 vf_mask)
+void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
 {
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       struct adf_bar *pmisc =
-                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
+       struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
        void __iomem *pmisc_addr = pmisc->virt_addr;
-       u32 reg;
-
-       /* Enable VF2PF Messaging Ints - VFs 1 through 16 per vf_mask[15:0] */
-       if (vf_mask & 0xFFFF) {
-               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3);
-               reg &= ~ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
-               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
-       }
-
-       /* Enable VF2PF Messaging Ints - VFs 17 through 32 per vf_mask[31:16] */
-       if (vf_mask >> 16) {
-               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5);
-               reg &= ~ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
-               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
-       }
-}
-
-void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
-{
        unsigned long flags;
 
        spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
-       __adf_enable_vf2pf_interrupts(accel_dev, vf_mask);
+       hw_data->enable_vf2pf_interrupts(pmisc_addr, vf_mask);
        spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
 }
 
-static void __adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
-                                          u32 vf_mask)
+void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
 {
        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
-       struct adf_bar *pmisc =
-                       &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
+       u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
+       struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
        void __iomem *pmisc_addr = pmisc->virt_addr;
-       u32 reg;
-
-       /* Disable VF2PF interrupts for VFs 1 through 16 per vf_mask[15:0] */
-       if (vf_mask & 0xFFFF) {
-               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3) |
-                       ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
-               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
-       }
-
-       /* Disable VF2PF interrupts for VFs 17 through 32 per vf_mask[31:16] */
-       if (vf_mask >> 16) {
-               reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5) |
-                       ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
-               ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
-       }
-}
-
-void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
-{
        unsigned long flags;
 
        spin_lock_irqsave(&accel_dev->pf.vf2pf_ints_lock, flags);
-       __adf_disable_vf2pf_interrupts(accel_dev, vf_mask);
+       hw_data->disable_vf2pf_interrupts(pmisc_addr, vf_mask);
        spin_unlock_irqrestore(&accel_dev->pf.vf2pf_ints_lock, flags);
 }
 
-void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev, u32 vf_mask)
+void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev,
+                                     u32 vf_mask)
 {
+       struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+       u32 misc_bar_id = hw_data->get_misc_bar_id(hw_data);
+       struct adf_bar *pmisc = &GET_BARS(accel_dev)[misc_bar_id];
+       void __iomem *pmisc_addr = pmisc->virt_addr;
+
        spin_lock(&accel_dev->pf.vf2pf_ints_lock);
-       __adf_disable_vf2pf_interrupts(accel_dev, vf_mask);
+       hw_data->disable_vf2pf_interrupts(pmisc_addr, vf_mask);
        spin_unlock(&accel_dev->pf.vf2pf_ints_lock);
 }
 
index 0a9ce365a544e4f3cf5d365a09611bd3a3f45895..b496032c992b54be6a4154df468700cb967a101c 100644 (file)
@@ -175,6 +175,52 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev)
                   ADF_DH895XCC_SMIA1_MASK);
 }
 
+static u32 get_vf2pf_sources(void __iomem *pmisc_bar)
+{
+       u32 errsou5, errmsk5, vf_int_mask;
+
+       vf_int_mask = adf_gen2_get_vf2pf_sources(pmisc_bar);
+
+       /* Get the interrupt sources triggered by VFs, but to avoid duplicates
+        * in the work queue, clear vf_int_mask_sets bits that are already
+        * masked in ERRMSK register.
+        */
+       errsou5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRSOU5);
+       errmsk5 = ADF_CSR_RD(pmisc_bar, ADF_GEN2_ERRMSK5);
+       vf_int_mask |= ADF_DH895XCC_ERR_REG_VF2PF_U(errsou5);
+       vf_int_mask &= ~ADF_DH895XCC_ERR_REG_VF2PF_U(errmsk5);
+
+       return vf_int_mask;
+}
+
+static void enable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
+{
+       /* Enable VF2PF Messaging Ints - VFs 0 through 15 per vf_mask[15:0] */
+       adf_gen2_enable_vf2pf_interrupts(pmisc_addr, vf_mask);
+
+       /* Enable VF2PF Messaging Ints - VFs 16 through 31 per vf_mask[31:16] */
+       if (vf_mask >> 16) {
+               u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5)
+                         & ~ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask);
+
+               ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val);
+       }
+}
+
+static void disable_vf2pf_interrupts(void __iomem *pmisc_addr, u32 vf_mask)
+{
+       /* Disable VF2PF interrupts for VFs 0 through 15 per vf_mask[15:0] */
+       adf_gen2_disable_vf2pf_interrupts(pmisc_addr, vf_mask);
+
+       /* Disable VF2PF interrupts for VFs 16 through 31 per vf_mask[31:16] */
+       if (vf_mask >> 16) {
+               u32 val = ADF_CSR_RD(pmisc_addr, ADF_GEN2_ERRMSK5)
+                         | ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask);
+
+               ADF_CSR_WR(pmisc_addr, ADF_GEN2_ERRMSK5, val);
+       }
+}
+
 static int adf_enable_pf2vf_comms(struct adf_accel_dev *accel_dev)
 {
        spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);
@@ -226,6 +272,9 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
        hw_data->enable_ints = adf_enable_ints;
        hw_data->reset_device = adf_reset_sbr;
        hw_data->get_pf2vf_offset = get_pf2vf_offset;
+       hw_data->get_vf2pf_sources = get_vf2pf_sources;
+       hw_data->enable_vf2pf_interrupts = enable_vf2pf_interrupts;
+       hw_data->disable_vf2pf_interrupts = disable_vf2pf_interrupts;
        hw_data->enable_pfvf_comms = adf_enable_pf2vf_comms;
        hw_data->disable_iov = adf_disable_sriov;
        hw_data->min_iov_compat_ver = ADF_PFVF_COMPAT_THIS_VERSION;
index f99319cd45432ae8e24549523d18fcdd3be4d231..0f9f24b44663810a33f25168080b4ecea542d89d 100644 (file)
 #define ADF_DH895XCC_CERRSSMSH(i) (i * 0x4000 + 0x10)
 #define ADF_DH895XCC_ERRSSMSH_EN BIT(3)
 
-#define ADF_DH895XCC_PF2VF_OFFSET(i)   (0x3A000 + 0x280 + ((i) * 0x04))
+/* Masks for VF2PF interrupts */
+#define ADF_DH895XCC_ERR_REG_VF2PF_U(vf_src)   (((vf_src) & 0x0000FFFF) << 16)
+#define ADF_DH895XCC_ERR_MSK_VF2PF_U(vf_mask)  ((vf_mask) >> 16)
+#define ADF_DH895XCC_PF2VF_OFFSET(i)           (0x3A000 + 0x280 + ((i) * 0x04))
 
 /* AE to function mapping */
 #define ADF_DH895XCC_AE2FUNC_MAP_GRP_A_NUM_REGS 96