crypto: qat - fix unregistration of crypto algorithms
authorGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Thu, 14 Sep 2023 09:55:48 +0000 (10:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:59:19 +0000 (11:59 +0100)
[ Upstream commit 9b2f33a1bfcda90b857431a764c9c8f9a412bbe5 ]

The function adf_dev_init(), through the subsystem qat_crypto, populates
the list of list of crypto instances accel_dev->crypto_list.
If the list of instances is not empty, the function adf_dev_start() will
then call qat_algs_registers() and qat_asym_algs_register() to register
the crypto algorithms into the crypto framework.

If any of the functions in adf_dev_start() fail, the caller of such
function, in the error path calls adf_dev_down() which in turn call
adf_dev_stop() and adf_dev_shutdown(), see for example the function
state_store in adf_sriov.c.
However, if the registration of crypto algorithms is not done,
adf_dev_stop() will try to unregister the algorithms regardless.
This might cause the counter active_devs in qat_algs.c and
qat_asym_algs.c to get to a negative value.

Add a new state, ADF_STATUS_CRYPTO_ALGS_REGISTERED, which tracks if the
crypto algorithms are registered into the crypto framework. Then use
this to unregister the algorithms if such flag is set. This ensures that
the crypto algorithms are only unregistered if previously registered.

Fixes: d8cba25d2c68 ("crypto: qat - Intel(R) QAT driver framework")
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Adam Guerin <adam.guerin@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/crypto/intel/qat/qat_common/adf_common_drv.h
drivers/crypto/intel/qat/qat_common/adf_init.c

index 673b5044c62a508c185712d7eab539d0d9958549..ed640cb37616b96fbaaf4d79a5d879d0048b4a63 100644 (file)
@@ -25,6 +25,7 @@
 #define ADF_STATUS_AE_STARTED 6
 #define ADF_STATUS_PF_RUNNING 7
 #define ADF_STATUS_IRQ_ALLOCATED 8
+#define ADF_STATUS_CRYPTO_ALGS_REGISTERED 9
 
 enum adf_dev_reset_mode {
        ADF_DEV_RESET_ASYNC = 0,
index 35aef5e8fc386aa1253414f8dd954842c2ee9681..ef8623f81fa33708858f50fb8d6d8c7f1b58d12e 100644 (file)
@@ -231,6 +231,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
                clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
                return -EFAULT;
        }
+       set_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status);
 
        if (!list_empty(&accel_dev->compression_list) && qat_comp_algs_register()) {
                dev_err(&GET_DEV(accel_dev),
@@ -272,10 +273,12 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
        clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
        clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
 
-       if (!list_empty(&accel_dev->crypto_list)) {
+       if (!list_empty(&accel_dev->crypto_list) &&
+           test_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status)) {
                qat_algs_unregister();
                qat_asym_algs_unregister();
        }
+       clear_bit(ADF_STATUS_CRYPTO_ALGS_REGISTERED, &accel_dev->status);
 
        if (!list_empty(&accel_dev->compression_list))
                qat_comp_algs_unregister();