Linux Integrity Measurement development
 help / color / mirror / Atom feed
* [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

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