]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
crypto: qat - fix state restore for banks with exceptions
authorSvyatoslav Pankratov <svyatoslav.pankratov@intel.com>
Wed, 4 Jun 2025 15:59:56 +0000 (16:59 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 13 Jun 2025 09:26:17 +0000 (17:26 +0800)
Change the logic in the restore function to properly handle bank
exceptions.

The check for exceptions in the saved state should be performed before
conducting any other ringstat register checks.
If a bank was saved with an exception, the ringstat will have the
appropriate rp_halt/rp_exception bits set, causing the driver to exit
the restore process with an error. Instead, the restore routine should
first check the ringexpstat register, and if any exception was raised,
it should stop further checks and return without any error. In other
words, if a ring pair is in an exception state at the source, it should
be restored the same way at the destination but without raising an error.

Even though this approach might lead to losing the exception state
during migration, the driver will log the exception from the saved state
during the restore process.

Signed-off-by: Svyatoslav Pankratov <svyatoslav.pankratov@intel.com>
Fixes: bbfdde7d195f ("crypto: qat - add bank save and restore flows")
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c

index 0406cb09c5bbb91c69498b0b077804a09558f1cf..14d0fdd66a4b2f64e1e6918c17285819c4535629 100644 (file)
@@ -581,6 +581,28 @@ static int bank_state_restore(struct adf_hw_csr_ops *ops, void __iomem *base,
        ops->write_csr_int_srcsel_w_val(base, bank, state->iaintflagsrcsel0);
        ops->write_csr_exp_int_en(base, bank, state->ringexpintenable);
        ops->write_csr_int_col_ctl(base, bank, state->iaintcolctl);
+
+       /*
+        * Verify whether any exceptions were raised during the bank save process.
+        * If exceptions occurred, the status and exception registers cannot
+        * be directly restored. Consequently, further restoration is not
+        * feasible, and the current state of the ring should be maintained.
+        */
+       val = state->ringexpstat;
+       if (val) {
+               pr_info("QAT: Bank %u state not fully restored due to exception in saved state (%#x)\n",
+                       bank, val);
+               return 0;
+       }
+
+       /* Ensure that the restoration process completed without exceptions */
+       tmp_val = ops->read_csr_exp_stat(base, bank);
+       if (tmp_val) {
+               pr_err("QAT: Bank %u restored with exception: %#x\n",
+                      bank, tmp_val);
+               return -EFAULT;
+       }
+
        ops->write_csr_ring_srv_arb_en(base, bank, state->ringsrvarben);
 
        /* Check that all ring statuses match the saved state. */
@@ -614,13 +636,6 @@ static int bank_state_restore(struct adf_hw_csr_ops *ops, void __iomem *base,
        if (ret)
                return ret;
 
-       tmp_val = ops->read_csr_exp_stat(base, bank);
-       val = state->ringexpstat;
-       if (tmp_val && !val) {
-               pr_err("QAT: Bank was restored with exception: 0x%x\n", val);
-               return -EINVAL;
-       }
-
        return 0;
 }