Commit 07df385e authored by Kanchana Velusamy's avatar Kanchana Velusamy Committed by Herbert Xu
Browse files

crypto: qat - protect interrupt mask CSRs with a spinlock



In the PF interrupt handler, the interrupt is disabled for a set of VFs
by writing to the interrupt source mask register, ERRMSK.
The interrupt is re-enabled in the bottom half handler by writing to the
same CSR. This is done through the functions enable_vf2pf_interrupts()
and disable_vf2pf_interrupts() which perform a read-modify-write
operation on the ERRMSK registers to mask and unmask the source of
interrupt.

There can be a race condition where the top half handler for one VF
interrupt runs just as the bottom half for another VF is about to
re-enable the interrupt. Depending on whether the top or bottom half
updates the CSR first, this would result either in a spurious interrupt
or in the interrupt not being re-enabled.

This patch protects the access of ERRMSK with a spinlock.

The functions adf_enable_vf2pf_interrupts() and
adf_disable_vf2pf_interrupts() have been changed to acquire a spin lock
before accessing and modifying the ERRMSK registers. These functions use
spin_lock_irqsave() to disable IRQs and avoid potential deadlocks.
In addition, the function adf_disable_vf2pf_interrupts_irq() has been
added. This uses spin_lock() and it is meant to be used in the top half
only.

Signed-off-by: default avatarKanchana Velusamy <kanchanax.velusamy@intel.com>
Co-developed-by: default avatarMarco Chiappero <marco.chiappero@intel.com>
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>
Reviewed-by: default avatarFiona Trahe <fiona.trahe@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 9800678f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -161,6 +161,8 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev)

static int adf_pf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
{
	spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);

	return 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ static void adf_enable_ints(struct adf_accel_dev *accel_dev)

static int adf_pf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
{
	spin_lock_init(&accel_dev->pf.vf2pf_ints_lock);

	return 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -246,6 +246,8 @@ struct adf_accel_dev {
	struct adf_accel_pci accel_pci_dev;
	union {
		struct {
			/* protects VF2PF interrupts access */
			spinlock_t vf2pf_ints_lock;
			/* vf_info is non-zero when SR-IOV is init'ed */
			struct adf_accel_vf_info *vf_info;
		} pf;
+2 −0
Original line number Diff line number Diff line
@@ -193,6 +193,8 @@ int adf_sriov_configure(struct pci_dev *pdev, int numvfs);
void adf_disable_sriov(struct adf_accel_dev *accel_dev);
void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
				  u32 vf_mask);
void adf_disable_vf2pf_interrupts_irq(struct adf_accel_dev *accel_dev,
				      u32 vf_mask);
void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
				 u32 vf_mask);
void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ static irqreturn_t adf_msix_isr_ae(int irq, void *dev_ptr)
			int i;

			/* Disable VF2PF interrupts for VFs with pending ints */
			adf_disable_vf2pf_interrupts(accel_dev, vf_mask);
			adf_disable_vf2pf_interrupts_irq(accel_dev, vf_mask);

			/*
			 * Handle VF2PF interrupt unless the VF is malicious and
Loading