mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
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: 6f1b523634 ("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>
This commit is contained in:
parent
4ad7c1bd5f
commit
4921634ac0
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user