git: 943686575d81 - main - tpm: Do not use timed tsleep() while polling during cold boot

From: Joseph Mingrone <jrm_at_FreeBSD.org>
Date: Sun, 27 Sep 2026 16:45:01 UTC
The branch main has been updated by jrm:

URL: https://cgit.FreeBSD.org/src/commit/?id=943686575d818c5cd3aaf2dfb912fabfb7dd7872

commit 943686575d818c5cd3aaf2dfb912fabfb7dd7872
Author:     Joseph Mingrone <jrm@FreeBSD.org>
AuthorDate: 2026-09-26 19:12:47 +0000
Commit:     Joseph Mingrone <jrm@FreeBSD.org>
CommitDate: 2026-09-27 16:20:34 +0000

    tpm: Do not use timed tsleep() while polling during cold boot
    
    Commit 4e0f283fb97a made tpm_tis12_init() wait for TPM_STS_CMD_READY
    after aborting any command.  The wait is implemented by the driver's
    existing tpm_waitfor_poll() loop, which sleeps with a one-tick tsleep()
    between status reads.  Until now, that loop only ran from the resume and
    command paths after boot.  From tpm_attach() it can panic with "timed
    sleep before timers are working" when the TPM is attached from ACPI
    during cold boot and the chip does not report ready on the first status
    read.
    
    Before 4e0f283fb97a, tpm_tis12_init() wrote TPM_STS_CMD_READY and
    returned without waiting, so the polling loops only ran after boot.
    tpm_request_locality() had the same latent hazard but its fast path
    returns before sleeping whenever locality is already active.
    
    Nothing calls wakeup() on the channels used by these polling loops, so
    the sleeps are pure delays.  Use pause_sig(), which falls back to
    DELAY() while the kernel is cold and returns EWOULDBLOCK, a value these
    loops already tolerate.
    
    The c argument to tpm_waitfor_poll() is now unused.  It is left in place
    to keep this change minimal for MFC and can be removed in a follow-up.
    
    Reviewed by:    kbowling
    Fixes:          4e0f283fb97a ("tpm: Bound TPM 1.2 locality ownership")
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D60050
---
 sys/dev/tpm/tpm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/dev/tpm/tpm.c b/sys/dev/tpm/tpm.c
index ee886e6ae7f8..109d01af220e 100644
--- a/sys/dev/tpm/tpm.c
+++ b/sys/dev/tpm/tpm.c
@@ -561,7 +561,7 @@ tpm_request_locality(struct tpm_softc *sc, int l)
 	while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
 	    (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
-		rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
+		rv = pause_sig("tpm_locality", 1);
 		if (rv &&  rv != EWOULDBLOCK) {
 #ifdef TPM_DEBUG
 			printf("tpm_request_locality: interrupted %d\n", rv);
@@ -638,7 +638,7 @@ tpm_getburst(struct tpm_softc *sc)
 		if (burst)
 			return burst;
 
-		rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
+		rv = pause_sig("tpm_getburst", 1);
 		if (rv && rv != EWOULDBLOCK) {
 			return 0;
 		}
@@ -807,7 +807,7 @@ tpm_waitfor_poll(struct tpm_softc *sc, u_int8_t mask, int tmo, void *c)
 	 * met.
 	 */
 	while (((sc->sc_stat = tpm_status(sc)) & mask) != mask && tmo--) {
-		rv = tsleep(c, PRIBIO | PCATCH, "tpm_poll", 1);
+		rv = pause_sig("tpm_poll", 1);
 		if (rv && rv != EWOULDBLOCK) {
 #ifdef TPM_DEBUG
 			printf("tpm_waitfor_poll: interrupted %d\n", rv);