git: cca34aa1d005 - main - tpm: crb: factor out idle/ready state transitions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 15 Nov 2025 02:22:46 UTC
The branch main has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=cca34aa1d005ffc859704331a3221b8c506d2f06
commit cca34aa1d005ffc859704331a3221b8c506d2f06
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-11-15 02:22:10 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-11-15 02:22:10 +0000
tpm: crb: factor out idle/ready state transitions
Some TPM implementations have a different start method that requires
an additional notification for some state changes; for instance, the
"Pluton" start method. Just factor these transitions out for now, and
the coming commits will introduce points that the start method can hook
in at.
Reviewed by: obrien
Differential Revision: https://reviews.freebsd.org/D53682
---
sys/dev/tpm/tpm_crb.c | 61 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 50 insertions(+), 11 deletions(-)
diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c
index 017ebd45c7ea..28b4f21eccfb 100644
--- a/sys/dev/tpm/tpm_crb.c
+++ b/sys/dev/tpm/tpm_crb.c
@@ -301,6 +301,48 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc)
return (true);
}
+static bool
+tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait)
+{
+ struct tpm_sc *sc;
+ int mask, timeout;
+
+ timeout = wait ? TPM_TIMEOUT_C : 0;
+
+ sc = &crb_sc->base;
+ OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
+
+ if (timeout > 0) {
+ mask = TPM_CRB_CTRL_STS_IDLE_BIT;
+ if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, mask,
+ timeout))
+ return (false);
+ }
+
+ return (true);
+}
+
+static bool
+tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait)
+{
+ struct tpm_sc *sc;
+ int mask, timeout;
+
+ timeout = wait ? TPM_TIMEOUT_C : 0;
+
+ sc = &crb_sc->base;
+ OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
+
+ if (timeout > 0) {
+ mask = TPM_CRB_CTRL_REQ_GO_READY;
+ if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, !mask,
+ timeout))
+ return (false);
+ }
+
+ return (true);
+}
+
int
tpmcrb_transmit(device_t dev, size_t length)
{
@@ -335,22 +377,15 @@ tpmcrb_transmit(device_t dev, size_t length)
/* Switch device to idle state if necessary */
if (!(TPM_READ_4(dev, TPM_CRB_CTRL_STS) & TPM_CRB_CTRL_STS_IDLE_BIT)) {
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
-
- mask = TPM_CRB_CTRL_STS_IDLE_BIT;
- if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
- mask, mask, TPM_TIMEOUT_C)) {
+ if (!tpmcrb_state_idle(crb_sc, true)) {
device_printf(dev,
"Failed to transition to idle state\n");
return (EIO);
}
}
- /* Switch to ready state */
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY);
- mask = TPM_CRB_CTRL_REQ_GO_READY;
- if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS,
- mask, !mask, TPM_TIMEOUT_C)) {
+ /* Switch to ready state */
+ if (!tpmcrb_state_ready(crb_sc, true)) {
device_printf(dev,
"Failed to transition to ready state\n");
return (EIO);
@@ -394,7 +429,11 @@ tpmcrb_transmit(device_t dev, size_t length)
bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE,
&sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE);
- OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE);
+ if (!tpmcrb_state_idle(crb_sc, false)) {
+ device_printf(dev,
+ "Failed to transition to idle state post-send\n");
+ return (EIO);
+ }
tpmcrb_relinquish_locality(sc);
sc->pending_data_length = bytes_available;