* [PATCH] tpm: Call cmd_ready/go_idle for each command transmission
@ 2026-08-31 5:37 Mario Limonciello
2026-09-01 13:38 ` Jarkko Sakkinen
0 siblings, 1 reply; 2+ messages in thread
From: Mario Limonciello @ 2026-08-31 5:37 UTC (permalink / raw)
To: peterhuewe, jarkko, jgg; +Cc: Mario Limonciello, linux-integrity
Some TPM implementations, particularly fTPM using the CRB interface,
require the TPM to transition through idle and ready states for each
command rather than once per session.
According to the TCG PC Client Platform TPM Profile (PTP) specification,
the CRB interface includes an idle/ready handshake for power management.
Software should set cmdReady to transition the TPM from idle to ready
state before sending a command, and set goIdle when finished to allow
the TPM to enter a low-power state.
The current implementation calls cmd_ready once during tpm_chip_start()
and go_idle once during tpm_chip_stop(). During the startup sequence,
multiple commands are sent between these calls (self-test, get
capabilities, session init). For fTPM, when subsequent commands are sent
without transitioning to idle after the previous command completes, those
commands timeout as the TPM is waiting for the idle transition.
Fix this by calling cmd_ready before each command transmission and
go_idle after receiving each response in tpm_try_transmit(). For TPM
implementations that don't require per-command transitions, the callbacks
can return immediately (as many already do based on the start method).
This resolves timeout errors during TPM initialization on systems where
BIOS has already performed TPM startup, as the kernel can now properly
communicate with the fTPM during auto-startup.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index f745a098908b3..a98ddca876152 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -113,6 +113,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
return -E2BIG;
}
+ if (chip->ops->cmd_ready) {
+ rc = chip->ops->cmd_ready(chip);
+ if (rc) {
+ dev_err(&chip->dev,
+ "%s: cmd_ready(): error %d\n", __func__, rc);
+ return rc;
+ }
+ }
+
rc = chip->ops->send(chip, buf, bufsiz, count);
if (rc < 0) {
if (rc != -EPIPE)
@@ -181,6 +190,12 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
if (len < TPM_HEADER_SIZE || len != be32_to_cpu(header->length))
rc = -EFAULT;
+ if (chip->ops->go_idle) {
+ int idle_rc = chip->ops->go_idle(chip);
+ if (idle_rc && !rc)
+ rc = idle_rc;
+ }
+
return rc ? rc : len;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] tpm: Call cmd_ready/go_idle for each command transmission
2026-08-31 5:37 [PATCH] tpm: Call cmd_ready/go_idle for each command transmission Mario Limonciello
@ 2026-09-01 13:38 ` Jarkko Sakkinen
0 siblings, 0 replies; 2+ messages in thread
From: Jarkko Sakkinen @ 2026-09-01 13:38 UTC (permalink / raw)
To: Mario Limonciello; +Cc: peterhuewe, jgg, linux-integrity
On Mon, Aug 31, 2026 at 12:37:21AM -0500, Mario Limonciello wrote:
> Some TPM implementations, particularly fTPM using the CRB interface,
> require the TPM to transition through idle and ready states for each
> command rather than once per session.
>
> According to the TCG PC Client Platform TPM Profile (PTP) specification,
> the CRB interface includes an idle/ready handshake for power management.
> Software should set cmdReady to transition the TPM from idle to ready
> state before sending a command, and set goIdle when finished to allow
> the TPM to enter a low-power state.
>
> The current implementation calls cmd_ready once during tpm_chip_start()
> and go_idle once during tpm_chip_stop(). During the startup sequence,
> multiple commands are sent between these calls (self-test, get
> capabilities, session init). For fTPM, when subsequent commands are sent
> without transitioning to idle after the previous command completes, those
> commands timeout as the TPM is waiting for the idle transition.
>
> Fix this by calling cmd_ready before each command transmission and
> go_idle after receiving each response in tpm_try_transmit(). For TPM
> implementations that don't require per-command transitions, the callbacks
> can return immediately (as many already do based on the start method).
>
> This resolves timeout errors during TPM initialization on systems where
> BIOS has already performed TPM startup, as the kernel can now properly
> communicate with the fTPM during auto-startup.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index f745a098908b3..a98ddca876152 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -113,6 +113,15 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
> return -E2BIG;
> }
>
> + if (chip->ops->cmd_ready) {
> + rc = chip->ops->cmd_ready(chip);
> + if (rc) {
> + dev_err(&chip->dev,
> + "%s: cmd_ready(): error %d\n", __func__, rc);
> + return rc;
> + }
> + }
> +
> rc = chip->ops->send(chip, buf, bufsiz, count);
> if (rc < 0) {
> if (rc != -EPIPE)
> @@ -181,6 +190,12 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
> if (len < TPM_HEADER_SIZE || len != be32_to_cpu(header->length))
> rc = -EFAULT;
>
> + if (chip->ops->go_idle) {
> + int idle_rc = chip->ops->go_idle(chip);
> + if (idle_rc && !rc)
> + rc = idle_rc;
> + }
> +
> return rc ? rc : len;
> }
>
> --
> 2.43.0
>
I think this should remove also redundant calls to cmd_ready and
go_idle.
BR, Jarkko
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-01 13:38 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 5:37 [PATCH] tpm: Call cmd_ready/go_idle for each command transmission Mario Limonciello
2026-09-01 13:38 ` Jarkko Sakkinen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox