* [PATCH v2 0/2] tpm: Stop retrying TPMs that have stopped working
@ 2026-11-12 12:30 Breno Leitao
2026-11-12 12:30 ` [PATCH v2 1/2] tpm: Disable a TPM that stops responding Breno Leitao
2026-11-12 12:30 ` [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE Breno Leitao
0 siblings, 2 replies; 9+ messages in thread
From: Breno Leitao @ 2026-11-12 12:30 UTC (permalink / raw)
To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe
Cc: linux-integrity, linux-kernel, surenkj, noodles, Breno Leitao,
kernel-team
On Meta's datacenter, given the size, TPMs that stop working write about
54 million lines a day to the kernel log, because nothing in the kernel
gives up on them.
Two cases make up nearly all of it.
Some TPMs stop responding. Every command then fails only after the
transport timeout, while the hwrng thread and userspace keep sending
more.
Other TPMs get reset under the running OS, and answer every command with
TPM_RC_INITIALIZE (256) from then on, while the hwrng thread retries
every 10 seconds:
tpm tpm0: A TPM error (256) occurred attempting get random
The goal is to retire TPMs that are not properly working, similarly to
what was done for EFI in commit 4b2c033b5bc971 ("efi/runtime-wrappers:
retire the worker if a wedged call ever returns")
Patch 1 disables the chip once 60 commands in a row have timed out,
instead of keeping it in this desolate state. Patch 2, from Jarkko,
disables it once it answers TPM_RC_INITIALIZE to anything but
TPM2_Startup.
Disabling the chip makes the failure explicit: the log gets one last
line about it, and every later command fails at once instead of timing
out.
A health-check daemon, such as machine checker, can then detect
the broken hardware and send the machine to repair.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Changes in v2:
- Disable the TPM after 60 commands in a row time out, instead of after
ten minutes of timeouts, and make the limit the tpm.max_unanswered
boot parameter (Jarkko)
- Open-code the check in tpm_transmit() and drop the "timeout" field
names (Jarkko)
- Replace the hwrng failure counter with Jarkko's patch, which disables
the TPM on TPM_RC_INITIALIZE
- In that patch, move the check ahead of the RETRY/TESTING break, where
it never ran, and skip TPM2_Startup, which a TPM that is already
started fails with TPM_RC_INITIALIZE
- Fix sashiko findings:
- Two timeouts ten minutes apart no longer disable an idle TPM
- Link to v1: https://patch.msgid.link/20261111-tpm_unresponsive-v1-0-42ac1b965eb9@debian.org
---
Breno Leitao (1):
tpm: Disable a TPM that stops responding
Jarkko Sakkinen (1):
tpm: Disable TPM on TPM_RC_INITIALIZE
drivers/char/tpm/tpm-interface.c | 20 ++++++++++++++++++++
drivers/char/tpm/tpm2-cmd.c | 2 ++
include/linux/tpm.h | 1 +
3 files changed, 23 insertions(+)
---
base-commit: 630059a5a632377b9b7b487baccde92b7ae1dd47
change-id: 20261110-tpm_unresponsive-a5f71c1db026
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 12:30 [PATCH v2 0/2] tpm: Stop retrying TPMs that have stopped working Breno Leitao @ 2026-11-12 12:30 ` Breno Leitao 2026-11-12 14:00 ` Jarkko Sakkinen 2026-11-12 12:30 ` [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE Breno Leitao 1 sibling, 1 reply; 9+ messages in thread From: Breno Leitao @ 2026-11-12 12:30 UTC (permalink / raw) To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe Cc: linux-integrity, linux-kernel, surenkj, noodles, Breno Leitao, kernel-team A TPM that stops responding fails each command only after the transport timeout, and its callers keep sending more: the hwrng thread every 10 seconds forever, and userspace through /dev/tpmrm0. Each attempt holds tpm_mutex for the whole timeout and logs an error: tpm tpm0: invalid TPM_STS.x 0xff, dumping stack for forensics tpm tpm0: tpm_try_transmit: send(): error -62 tpm tpm0: tpm_try_transmit: send(): error -62 ... The core already stops using a TPM it cannot trust: tpm_try_get_ops() fails with -EIO once TPM_CHIP_FLAG_DISABLE is set, which tpm2_load_null() does when it cannot restore the null key. Set the same flag once 60 commands in a row have timed out. A completed command, whatever its TPM return code, resets the count. Some TPMs stall for half a minute, time out a handful of commands, and then recover, so a short streak must not disable them. With only the hwrng retrying every 10 seconds, 60 timeouts take more than ten minutes. A userspace poller gets there sooner, but each of its commands still waits out the transport timeout. The limit is the tpm.max_unanswered boot parameter, so that slow pre-production parts, such as FPGA prototypes, can raise it, or set it to 0 to never disable the TPM. A disabled TPM stays disabled until the driver is rebound or the machine reboots. Signed-off-by: Breno Leitao <leitao@debian.org> --- drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++ include/linux/tpm.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e0385b16616b46..b7865ccb799289 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -40,6 +40,11 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); MODULE_PARM_DESC(suspend_pcr, "PCR to use for dummy writes to facilitate flush on suspend."); +static unsigned int tpm_max_unanswered = 60; +module_param_named(max_unanswered, tpm_max_unanswered, uint, 0444); +MODULE_PARM_DESC(max_unanswered, + "Disable the TPM after this many commands in a row time out (0 = never)."); + /** * tpm_calc_ordinal_duration() - calculate the maximum command duration * @chip: TPM chip to use. @@ -268,6 +273,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) delay_msec *= 2; memcpy(buf, save, save_size); } + + if (ret >= 0) { + /* we are good, reset nr_unanswered */ + chip->nr_unanswered = 0; + } else if (ret == -ETIME && + ++chip->nr_unanswered == tpm_max_unanswered) { + dev_err(&chip->dev, "%u commands in a row timed out, disabling the TPM\n", + chip->nr_unanswered); + chip->flags |= TPM_CHIP_FLAG_DISABLE; + } return ret; } diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 0db277af45c393..e8191585a68e7a 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -131,6 +131,7 @@ struct tpm_chip { struct hwrng hwrng; struct mutex tpm_mutex; /* tpm is processing */ + unsigned int nr_unanswered; /* commands in a row that timed out */ unsigned long timeout_a; /* jiffies */ unsigned long timeout_b; /* jiffies */ -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 12:30 ` [PATCH v2 1/2] tpm: Disable a TPM that stops responding Breno Leitao @ 2026-11-12 14:00 ` Jarkko Sakkinen 2026-11-12 14:03 ` Jarkko Sakkinen 0 siblings, 1 reply; 9+ messages in thread From: Jarkko Sakkinen @ 2026-11-12 14:00 UTC (permalink / raw) To: Breno Leitao Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 04:30:17AM -0800, Breno Leitao wrote: > A TPM that stops responding fails each command only after the transport > timeout, and its callers keep sending more: the hwrng thread every 10 > seconds forever, and userspace through /dev/tpmrm0. Each attempt holds > tpm_mutex for the whole timeout and logs an error: > > tpm tpm0: invalid TPM_STS.x 0xff, dumping stack for forensics > tpm tpm0: tpm_try_transmit: send(): error -62 > tpm tpm0: tpm_try_transmit: send(): error -62 > ... > > The core already stops using a TPM it cannot trust: tpm_try_get_ops() > fails with -EIO once TPM_CHIP_FLAG_DISABLE is set, which > tpm2_load_null() does when it cannot restore the null key. Set the same > flag once 60 commands in a row have timed out. > > A completed command, whatever its TPM return code, resets the count. > Some TPMs stall for half a minute, time out a handful of commands, and > then recover, so a short streak must not disable them. > > With only the hwrng retrying every 10 seconds, 60 timeouts take more > than ten minutes. A userspace poller gets there sooner, but each of its > commands still waits out the transport timeout. > > The limit is the tpm.max_unanswered boot parameter, so that slow > pre-production parts, such as FPGA prototypes, can raise it, or set it > to 0 to never disable the TPM. A disabled TPM stays disabled until the > driver is rebound or the machine reboots. > > Signed-off-by: Breno Leitao <leitao@debian.org> > --- > drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++ > include/linux/tpm.h | 1 + > 2 files changed, 16 insertions(+) > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c > index e0385b16616b46..b7865ccb799289 100644 > --- a/drivers/char/tpm/tpm-interface.c > +++ b/drivers/char/tpm/tpm-interface.c > @@ -40,6 +40,11 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); > MODULE_PARM_DESC(suspend_pcr, > "PCR to use for dummy writes to facilitate flush on suspend."); > > +static unsigned int tpm_max_unanswered = 60; > +module_param_named(max_unanswered, tpm_max_unanswered, uint, 0444); > +MODULE_PARM_DESC(max_unanswered, > + "Disable the TPM after this many commands in a row time out (0 = never)."); Documentation/admin/kernel-parameters.txt update is also needed. tpm_max_missed_responses is what I would suggest, because it is more accurate e.g., on stating what is being counted :-) > + > /** > * tpm_calc_ordinal_duration() - calculate the maximum command duration > * @chip: TPM chip to use. > @@ -268,6 +273,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) > delay_msec *= 2; > memcpy(buf, save, save_size); > } > + > + if (ret >= 0) { > + /* we are good, reset nr_unanswered */ I'm not a huge fan in general of third person plural in the source code comments. Probably a comment here is not needed at all as it does not state anything that would not be obvious (i.e. something nothing non-obvious is documented). > + chip->nr_unanswered = 0; > + } else if (ret == -ETIME && > + ++chip->nr_unanswered == tpm_max_unanswered) { > + dev_err(&chip->dev, "%u commands in a row timed out, disabling the TPM\n", > + chip->nr_unanswered); > + chip->flags |= TPM_CHIP_FLAG_DISABLE; > + } > return ret; > } > > diff --git a/include/linux/tpm.h b/include/linux/tpm.h > index 0db277af45c393..e8191585a68e7a 100644 > --- a/include/linux/tpm.h > +++ b/include/linux/tpm.h > @@ -131,6 +131,7 @@ struct tpm_chip { > struct hwrng hwrng; > > struct mutex tpm_mutex; /* tpm is processing */ > + unsigned int nr_unanswered; /* commands in a row that timed out */ This would be then nr_lost_responses. > > unsigned long timeout_a; /* jiffies */ > unsigned long timeout_b; /* jiffies */ > > -- > 2.53.0-Meta > Br, Jarkko ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 14:00 ` Jarkko Sakkinen @ 2026-11-12 14:03 ` Jarkko Sakkinen 2026-11-12 15:45 ` Breno Leitao 2026-11-12 20:40 ` Breno Leitao 0 siblings, 2 replies; 9+ messages in thread From: Jarkko Sakkinen @ 2026-11-12 14:03 UTC (permalink / raw) To: Breno Leitao Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 04:00:50PM +0200, Jarkko Sakkinen wrote: > On Thu, Nov 12, 2026 at 04:30:17AM -0800, Breno Leitao wrote: > > A TPM that stops responding fails each command only after the transport > > timeout, and its callers keep sending more: the hwrng thread every 10 > > seconds forever, and userspace through /dev/tpmrm0. Each attempt holds > > tpm_mutex for the whole timeout and logs an error: > > > > tpm tpm0: invalid TPM_STS.x 0xff, dumping stack for forensics > > tpm tpm0: tpm_try_transmit: send(): error -62 > > tpm tpm0: tpm_try_transmit: send(): error -62 > > ... > > > > The core already stops using a TPM it cannot trust: tpm_try_get_ops() > > fails with -EIO once TPM_CHIP_FLAG_DISABLE is set, which > > tpm2_load_null() does when it cannot restore the null key. Set the same > > flag once 60 commands in a row have timed out. > > > > A completed command, whatever its TPM return code, resets the count. > > Some TPMs stall for half a minute, time out a handful of commands, and > > then recover, so a short streak must not disable them. > > > > With only the hwrng retrying every 10 seconds, 60 timeouts take more > > than ten minutes. A userspace poller gets there sooner, but each of its > > commands still waits out the transport timeout. > > > > The limit is the tpm.max_unanswered boot parameter, so that slow > > pre-production parts, such as FPGA prototypes, can raise it, or set it > > to 0 to never disable the TPM. A disabled TPM stays disabled until the > > driver is rebound or the machine reboots. > > > > Signed-off-by: Breno Leitao <leitao@debian.org> > > --- > > drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++ > > include/linux/tpm.h | 1 + > > 2 files changed, 16 insertions(+) > > > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c > > index e0385b16616b46..b7865ccb799289 100644 > > --- a/drivers/char/tpm/tpm-interface.c > > +++ b/drivers/char/tpm/tpm-interface.c > > @@ -40,6 +40,11 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); > > MODULE_PARM_DESC(suspend_pcr, > > "PCR to use for dummy writes to facilitate flush on suspend."); > > > > +static unsigned int tpm_max_unanswered = 60; > > +module_param_named(max_unanswered, tpm_max_unanswered, uint, 0444); > > +MODULE_PARM_DESC(max_unanswered, > > + "Disable the TPM after this many commands in a row time out (0 = never)."); > > Documentation/admin/kernel-parameters.txt update is also needed. > > tpm_max_missed_responses is what I would suggest, because it is more > accurate e.g., on stating what is being counted :-) > > > > + > > /** > > * tpm_calc_ordinal_duration() - calculate the maximum command duration > > * @chip: TPM chip to use. > > @@ -268,6 +273,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) > > delay_msec *= 2; > > memcpy(buf, save, save_size); > > } > > + > > + if (ret >= 0) { > > + /* we are good, reset nr_unanswered */ > > I'm not a huge fan in general of third person plural in the source code > comments. Probably a comment here is not needed at all as it does not > state anything that would not be obvious (i.e. something nothing > non-obvious is documented). > > > + chip->nr_unanswered = 0; > > + } else if (ret == -ETIME && > > + ++chip->nr_unanswered == tpm_max_unanswered) { > > + dev_err(&chip->dev, "%u commands in a row timed out, disabling the TPM\n", > > + chip->nr_unanswered); > > + chip->flags |= TPM_CHIP_FLAG_DISABLE; > > + } > > return ret; > > } > > > > diff --git a/include/linux/tpm.h b/include/linux/tpm.h > > index 0db277af45c393..e8191585a68e7a 100644 > > --- a/include/linux/tpm.h > > +++ b/include/linux/tpm.h > > @@ -131,6 +131,7 @@ struct tpm_chip { > > struct hwrng hwrng; > > > > struct mutex tpm_mutex; /* tpm is processing */ > > + unsigned int nr_unanswered; /* commands in a row that timed out */ > > This would be then nr_lost_responses. Oops sorry. I mean nr_missed_responses (and I would prefer "missed" over "lost"). Br, Jarkko ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 14:03 ` Jarkko Sakkinen @ 2026-11-12 15:45 ` Breno Leitao 2026-11-12 20:40 ` Breno Leitao 1 sibling, 0 replies; 9+ messages in thread From: Breno Leitao @ 2026-11-12 15:45 UTC (permalink / raw) To: Jarkko Sakkinen Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 04:03:06PM +0200, Jarkko Sakkinen wrote: > On Thu, Nov 12, 2026 at 04:00:50PM +0200, Jarkko Sakkinen wrote: > > On Thu, Nov 12, 2026 at 04:30:17AM -0800, Breno Leitao wrote: > > > A TPM that stops responding fails each command only after the transport > > > timeout, and its callers keep sending more: the hwrng thread every 10 > > > seconds forever, and userspace through /dev/tpmrm0. Each attempt holds > > > tpm_mutex for the whole timeout and logs an error: > > > > > > tpm tpm0: invalid TPM_STS.x 0xff, dumping stack for forensics > > > tpm tpm0: tpm_try_transmit: send(): error -62 > > > tpm tpm0: tpm_try_transmit: send(): error -62 > > > ... > > > > > > The core already stops using a TPM it cannot trust: tpm_try_get_ops() > > > fails with -EIO once TPM_CHIP_FLAG_DISABLE is set, which > > > tpm2_load_null() does when it cannot restore the null key. Set the same > > > flag once 60 commands in a row have timed out. > > > > > > A completed command, whatever its TPM return code, resets the count. > > > Some TPMs stall for half a minute, time out a handful of commands, and > > > then recover, so a short streak must not disable them. > > > > > > With only the hwrng retrying every 10 seconds, 60 timeouts take more > > > than ten minutes. A userspace poller gets there sooner, but each of its > > > commands still waits out the transport timeout. > > > > > > The limit is the tpm.max_unanswered boot parameter, so that slow > > > pre-production parts, such as FPGA prototypes, can raise it, or set it > > > to 0 to never disable the TPM. A disabled TPM stays disabled until the > > > driver is rebound or the machine reboots. > > > > > > Signed-off-by: Breno Leitao <leitao@debian.org> > > > --- > > > drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++ > > > include/linux/tpm.h | 1 + > > > 2 files changed, 16 insertions(+) > > > > > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c > > > index e0385b16616b46..b7865ccb799289 100644 > > > --- a/drivers/char/tpm/tpm-interface.c > > > +++ b/drivers/char/tpm/tpm-interface.c > > > @@ -40,6 +40,11 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); > > > MODULE_PARM_DESC(suspend_pcr, > > > "PCR to use for dummy writes to facilitate flush on suspend."); > > > > > > +static unsigned int tpm_max_unanswered = 60; > > > +module_param_named(max_unanswered, tpm_max_unanswered, uint, 0444); > > > +MODULE_PARM_DESC(max_unanswered, > > > + "Disable the TPM after this many commands in a row time out (0 = never)."); > > > > Documentation/admin/kernel-parameters.txt update is also needed. > > > > tpm_max_missed_responses is what I would suggest, because it is more > > accurate e.g., on stating what is being counted :-) > > > > > > > + > > > /** > > > * tpm_calc_ordinal_duration() - calculate the maximum command duration > > > * @chip: TPM chip to use. > > > @@ -268,6 +273,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) > > > delay_msec *= 2; > > > memcpy(buf, save, save_size); > > > } > > > + > > > + if (ret >= 0) { > > > + /* we are good, reset nr_unanswered */ > > > > I'm not a huge fan in general of third person plural in the source code > > comments. Probably a comment here is not needed at all as it does not > > state anything that would not be obvious (i.e. something nothing > > non-obvious is documented). > > > > > + chip->nr_unanswered = 0; > > > + } else if (ret == -ETIME && > > > + ++chip->nr_unanswered == tpm_max_unanswered) { > > > + dev_err(&chip->dev, "%u commands in a row timed out, disabling the TPM\n", > > > + chip->nr_unanswered); > > > + chip->flags |= TPM_CHIP_FLAG_DISABLE; > > > + } > > > return ret; > > > } > > > > > > diff --git a/include/linux/tpm.h b/include/linux/tpm.h > > > index 0db277af45c393..e8191585a68e7a 100644 > > > --- a/include/linux/tpm.h > > > +++ b/include/linux/tpm.h > > > @@ -131,6 +131,7 @@ struct tpm_chip { > > > struct hwrng hwrng; > > > > > > struct mutex tpm_mutex; /* tpm is processing */ > > > + unsigned int nr_unanswered; /* commands in a row that timed out */ > > > > This would be then nr_lost_responses. > > Oops sorry. > > I mean nr_missed_responses (and I would prefer "missed" over "lost"). Ack, respining... --breno ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 14:03 ` Jarkko Sakkinen 2026-11-12 15:45 ` Breno Leitao @ 2026-11-12 20:40 ` Breno Leitao 2026-11-12 21:07 ` Jarkko Sakkinen 1 sibling, 1 reply; 9+ messages in thread From: Breno Leitao @ 2026-11-12 20:40 UTC (permalink / raw) To: Jarkko Sakkinen Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 04:03:06PM +0200, Jarkko Sakkinen wrote: > > > > This would be then nr_lost_responses. > > Oops sorry. > > I mean nr_missed_responses (and I would prefer "missed" over "lost"). Would you hate if I go with max_missed_responses? ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] tpm: Disable a TPM that stops responding 2026-11-12 20:40 ` Breno Leitao @ 2026-11-12 21:07 ` Jarkko Sakkinen 0 siblings, 0 replies; 9+ messages in thread From: Jarkko Sakkinen @ 2026-11-12 21:07 UTC (permalink / raw) To: Breno Leitao Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 12:40:45PM -0800, Breno Leitao wrote: > On Thu, Nov 12, 2026 at 04:03:06PM +0200, Jarkko Sakkinen wrote: > > > > > > This would be then nr_lost_responses. > > > > Oops sorry. > > > > I mean nr_missed_responses (and I would prefer "missed" over "lost"). > > Would you hate if I go with max_missed_responses? It's a great question. Here I think asymmetry defines things better, and makes sense also few months from now. So I think this would be most consistent: 1. kernel command-line: tpm_max_missed_responses 2. tpm_chip: nr_missed_responses. The first defines the modulo and second counts up to that. Can't recall (and too lazy to check) how it exactly was in your code change but I would formalize all this along the lines of: if (!(++chip->nr_missed_responses % tpm_max_missed_responses)) { /* chip->flags |= TPM2_CHIP_FLAG_DISABLE etc. and of course bail out. */ } /* continue doing things */ [those comments are not part of the proposal] Br, Jarkko ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE 2026-11-12 12:30 [PATCH v2 0/2] tpm: Stop retrying TPMs that have stopped working Breno Leitao 2026-11-12 12:30 ` [PATCH v2 1/2] tpm: Disable a TPM that stops responding Breno Leitao @ 2026-11-12 12:30 ` Breno Leitao 2026-11-12 13:37 ` Jarkko Sakkinen 1 sibling, 1 reply; 9+ messages in thread From: Breno Leitao @ 2026-11-12 12:30 UTC (permalink / raw) To: Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe Cc: linux-integrity, linux-kernel, surenkj, noodles, Breno Leitao, kernel-team From: Jarkko Sakkinen <jarkko@kernel.org> If the TPM has been spuriously disabled, the game is over. Let's reflect this truth with TPM_CHIP_FLAG_DISABLE. Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> [leitao@debian.org: check rc before the loop breaks out on anything but RETRY/TESTING, skip TPM2_Startup, which a TPM that is already started fails with TPM2_RC_INITIALIZE, and fix the TPM2_RC_INITIALIZE and chip->flags typos] Signed-off-by: Breno Leitao <leitao@debian.org> --- drivers/char/tpm/tpm-interface.c | 5 +++++ drivers/char/tpm/tpm2-cmd.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index b7865ccb799289..144e2dbae66853 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -252,6 +252,11 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) if (ret < 0) break; rc = be32_to_cpu(header->return_code); + /* A TPM that is already started fails TPM2_Startup this way. */ + if (rc == TPM2_RC_INITIALIZE && cc != TPM2_CC_STARTUP) { + chip->flags |= TPM_CHIP_FLAG_DISABLE; + break; + } if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) break; /* diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 4b2bb2ddc321a9..65928ae85b496c 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -724,6 +724,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) goto out; if (rc == TPM2_RC_INITIALIZE) { + chip->flags &= ~TPM_CHIP_FLAG_DISABLE; + rc = tpm2_startup(chip); if (rc) goto out; -- 2.53.0-Meta ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE 2026-11-12 12:30 ` [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE Breno Leitao @ 2026-11-12 13:37 ` Jarkko Sakkinen 0 siblings, 0 replies; 9+ messages in thread From: Jarkko Sakkinen @ 2026-11-12 13:37 UTC (permalink / raw) To: Breno Leitao Cc: Peter Huewe, Jason Gunthorpe, linux-integrity, linux-kernel, surenkj, noodles, kernel-team On Thu, Nov 12, 2026 at 04:30:18AM -0800, Breno Leitao wrote: > From: Jarkko Sakkinen <jarkko@kernel.org> > > If the TPM has been spuriously disabled, the game is over. Let's reflect > this truth with TPM_CHIP_FLAG_DISABLE. > > Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> > [leitao@debian.org: check rc before the loop breaks out on anything but > RETRY/TESTING, skip TPM2_Startup, which a TPM that is already started > fails with TPM2_RC_INITIALIZE, and fix the TPM2_RC_INITIALIZE and > chip->flags typos] > Signed-off-by: Breno Leitao <leitao@debian.org> > --- > drivers/char/tpm/tpm-interface.c | 5 +++++ > drivers/char/tpm/tpm2-cmd.c | 2 ++ > 2 files changed, 7 insertions(+) > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c > index b7865ccb799289..144e2dbae66853 100644 > --- a/drivers/char/tpm/tpm-interface.c > +++ b/drivers/char/tpm/tpm-interface.c > @@ -252,6 +252,11 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz) > if (ret < 0) > break; > rc = be32_to_cpu(header->return_code); > + /* A TPM that is already started fails TPM2_Startup this way. */ > + if (rc == TPM2_RC_INITIALIZE && cc != TPM2_CC_STARTUP) { Good catch! Thanks. > + chip->flags |= TPM_CHIP_FLAG_DISABLE; > + break; > + } > if (rc != TPM2_RC_RETRY && rc != TPM2_RC_TESTING) > break; > /* > diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c > index 4b2bb2ddc321a9..65928ae85b496c 100644 > --- a/drivers/char/tpm/tpm2-cmd.c > +++ b/drivers/char/tpm/tpm2-cmd.c > @@ -724,6 +724,8 @@ int tpm2_auto_startup(struct tpm_chip *chip) > goto out; > > if (rc == TPM2_RC_INITIALIZE) { > + chip->flags &= ~TPM_CHIP_FLAG_DISABLE; > + > rc = tpm2_startup(chip); > if (rc) > goto out; > > -- > 2.53.0-Meta > Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Br, Jarkko ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-11-12 21:07 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-12 12:30 [PATCH v2 0/2] tpm: Stop retrying TPMs that have stopped working Breno Leitao 2026-11-12 12:30 ` [PATCH v2 1/2] tpm: Disable a TPM that stops responding Breno Leitao 2026-11-12 14:00 ` Jarkko Sakkinen 2026-11-12 14:03 ` Jarkko Sakkinen 2026-11-12 15:45 ` Breno Leitao 2026-11-12 20:40 ` Breno Leitao 2026-11-12 21:07 ` Jarkko Sakkinen 2026-11-12 12:30 ` [PATCH v2 2/2] tpm: Disable TPM on TPM_RC_INITIALIZE Breno Leitao 2026-11-12 13:37 ` Jarkko Sakkinen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox