Commit 993161d3 authored by Marco Chiappero's avatar Marco Chiappero Committed by Herbert Xu
Browse files

crypto: qat - fix handling of VF to PF interrupts



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: default avatarMarco Chiappero <marco.chiappero@intel.com>
Co-developed-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent e17f49bb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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);
+40 −0
Original line number Diff line number Diff line
@@ -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)
{
+12 −0
Original line number Diff line number Diff line
@@ -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);
Loading