summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAhsan Atta <ahsan.atta@intel.com>2026-10-06 16:06:48 +0100
committerHerbert Xu <herbert@gondor.apana.org.au>2026-10-15 20:37:52 +1100
commit4921634ac0a9a65aaa5e41308aabda3d3f562ee3 (patch)
tree0a1879e5cc2a4cdf5030c73b1c2d4519a6ecb176
parent4ad7c1bd5f3dcd3fd6efbb068d6ee2a68dddfece (diff)
crypto: qat - fix use of destroyed vf2pf_lock on VF restart
adf_dev_stop_async() sends the RESTARTING_COMPLETE message after adf_dev_down() has returned, but adf_dev_down() already destroyed the lock that message takes. Both run in sequence in the same worker, so every PF restart locks a destroyed mutex. With CONFIG_DEBUG_MUTEXES on a dh895xcc with 32 host-bound VFs this trips on the first PF reset: DEBUG_LOCKS_WARN_ON(lock->magic != lock) WARNING: kernel/locking/mutex.c:159 at mutex_lock+0x171/0x1c0 Workqueue: adf_vf_stop_wq adf_dev_stop_async [intel_qat] Call Trace: adf_gen2_pfvf_send+0x210/0x530 [intel_qat] adf_vf2pf_notify_restart_complete+0x55/0x80 [intel_qat] adf_dev_stop_async+0xdb/0x140 [intel_qat] The notification cannot move before adf_dev_down(): the PF waits for it before its own reset and the VF must tear down its rings first. vf2pf_lock protects the VF2PF CSR and is unrelated to the PF2VF bottom half it is initialised alongside. Tie its lifetime to the accel device, next to state_lock in adf_devmgr_add_dev()/adf_devmgr_rm_dev(), so it stays valid for messages sent outside the device up/down cycle. It is only touched for VFs, which set is_vf before adf_devmgr_add_dev() and keep it set until adf_devmgr_rm_dev(). Fixes: 6f1b5236348f ("crypto: qat - fix recovery flow for VFs") Cc: stable@vger.kernel.org Signed-off-by: Ahsan Atta <ahsan.atta@intel.com> Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c8
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_vf_isr.c2
2 files changed, 8 insertions, 2 deletions
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
index 26b40dd59965..4e6d860c9a60 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
@@ -138,6 +138,12 @@ int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev,
mutex_lock(&table_lock);
atomic_set(&accel_dev->ref_count, 0);
mutex_init(&accel_dev->state_lock);
+ /*
+ * The VF2PF lock is used to send messages to the PF outside of the
+ * device up/down cycle, so it must live as long as the accel device.
+ */
+ if (accel_dev->is_vf)
+ mutex_init(&accel_dev->vf.vf2pf_lock);
/* PF on host or VF on guest - optimized to remove redundant is_vf */
if (!accel_dev->is_vf || !pf) {
@@ -257,6 +263,8 @@ void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev,
}
}
unlock:
+ if (accel_dev->is_vf)
+ mutex_destroy(&accel_dev->vf.vf2pf_lock);
mutex_destroy(&accel_dev->state_lock);
list_del(&accel_dev->list);
mutex_unlock(&table_lock);
diff --git a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c
index 9ffaa56def67..1f28655ec051 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_vf_isr.c
@@ -118,7 +118,6 @@ static int adf_setup_pf2vf_bh(struct adf_accel_dev *accel_dev)
tasklet_init(&accel_dev->vf.pf2vf_bh_tasklet,
(void *)adf_pf2vf_bh_handler, (unsigned long)accel_dev);
- mutex_init(&accel_dev->vf.vf2pf_lock);
return 0;
}
@@ -126,7 +125,6 @@ static void adf_cleanup_pf2vf_bh(struct adf_accel_dev *accel_dev)
{
tasklet_disable(&accel_dev->vf.pf2vf_bh_tasklet);
tasklet_kill(&accel_dev->vf.pf2vf_bh_tasklet);
- mutex_destroy(&accel_dev->vf.vf2pf_lock);
}
static irqreturn_t adf_isr(int irq, void *privdata)