summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan McDowell <noodles@meta.com>2025-03-12 07:31:57 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-20 10:15:35 +0200
commit4c8056fbb17d652227b66f53162601b043a06ece (patch)
tree7361d70fd5266f0d6416a6f816e46e1a6b60bee1
parent7266066b9469f04ed1d4c0fdddaea1425835eb55 (diff)
tpm, tpm_tis: Fix timeout handling when waiting for TPM status
commit 7146dffa875cd00e7a7f918e1fce79c7593ac1fa upstream. The change to only use interrupts to handle supported status changes introduced an issue when it is necessary to poll for the status. Rather than checking for the status after sleeping the code now sleeps after the check. This means a correct, but slower, status change on the part of the TPM can be missed, resulting in a spurious timeout error, especially on a more loaded system. Switch back to sleeping *then* checking. An up front check of the status has been done at the start of the function, so this does not cause an additional delay when the status is already what we're looking for. Cc: stable@vger.kernel.org # v6.4+ Fixes: e87fcf0dc2b4 ("tpm, tpm_tis: Only handle supported interrupts") Signed-off-by: Jonathan McDowell <noodles@meta.com> Reviewed-by: Michal Suchánek <msuchanek@suse.de> Reviewed-by: Lino Sanfilippo <l.sanfilippo@kunbus.com> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/char/tpm/tpm_tis_core.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 4cc2ab2d16cc..ed0d3d8449b3 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -114,11 +114,10 @@ again:
return 0;
/* process status changes without irq support */
do {
+ usleep_range(priv->timeout_min, priv->timeout_max);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
- usleep_range(priv->timeout_min,
- priv->timeout_max);
} while (time_before(jiffies, stop));
return -ETIME;
}