From nobody Thu Sep 03 03:56:10 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hb5P65x2bz6qWFk for ; Thu, 03 Sep 2026 03:56:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hb5P653Jxz3p2Z for ; Thu, 03 Sep 2026 03:56:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788407770; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3w2rdoW4DR+qHljQZlagQwvq0617ETys6/yFVhqydXc=; b=GU58aWGxORaus7LBXoYn8Yr29htUsWey2XhAeCtFtyIZqQxUcJxyLy0y5wCXfjRnbPgGfg KaVIpX4vKVFEzTeYiGyIZSO+Ye3aB9aRHaBnKVVRZJJL1iHOtbnf2hMm8//nwGa24M9jZb PQljzV1CCGSX3/Ztk+IUby02PxgGdp+qpfA786ZBCelJWTlCEHE2A+3+/0tsOP5+pRumFE nzcKwzb6g2W+4Do22RuGDfD7EDahO5eGZFE0nV0PTDBEhO2wGhP9kXwL5zVmgj0O5Mjew/ UtexTWlnNlQ7ZhpFIN5qQ6j6LktOzoKfbWo3lqu1EOgzvX6tXqjP8KS7PQUghw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788407770; a=rsa-sha256; cv=none; b=eMFMAMdar1ZsVgPgIvkdp9I0oFid3oqwRZ9NPJMhHtIlqAp2Z9l9k0mAipjLKKuatdYYrX klbtoa+qNinKmkt0udn3qv2MoCQ0GRMDWIjQ9KWlCPc8Ef/9640OiQJx4zIfgywQF6Kt+q Cn7H49Nu9ipQ/iHYkVVsCYBva4ovw9hk5uTp/yPdtkmJb1aLa6b+qTLtX/H4uLyWm7lHtm 0FgrBk5d3SnNnwzg7ihAQmAkjCCiMMCBFI95r4Be/INWGXl+Z3MNv99/nfLnL3VRI/VDt3 zJwDIIIfA3NkPxMsbECTPH6icKMUqWr7QxmGoUXzAMW1AAcdokOuaq5RkkX4HA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788407770; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3w2rdoW4DR+qHljQZlagQwvq0617ETys6/yFVhqydXc=; b=Auob2QCEsrr92i4VjXw1ZrNXqyrHPnBBe+pOgB3XS0qkyeL3HumLfJDZEMxntFKuuxb+lC WkTjaJUztr4Ok5h8XCL0AW/EuXe8bCnMflD3Hi4FZbnFipK5xNtoDd0AVUpcKkopikZSdk AgHfT9XkdP+3WAKDlc2wK5ez/TiSP4bc36oJyostfh60sPxTrHxRG7LNb9yE26CjGRExY5 pc/kvRs2a3La8QCb6C5XA4fNFCbeCSbzUO3s+8uc29TyTdJphAI8U1huaR5sABXYRcM4j4 ZKqaqVYMy+KR9fI114ryEPly0pKSfZhfrH2nd48I/j6UyAg6oq4UF/Wc/oxgPg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hb5P63hRpz1Bxj for ; Thu, 03 Sep 2026 03:56:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3785d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 03 Sep 2026 03:56:10 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: a229432d3ed0 - main - tpm_tis: Restore validated interrupts after resume List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a229432d3ed05282f7cf1510a06d6d93d554c1df Auto-Submitted: auto-generated Date: Thu, 03 Sep 2026 03:56:10 +0000 Message-Id: <6a98efda.3785d.a7dd7f@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=a229432d3ed05282f7cf1510a06d6d93d554c1df commit a229432d3ed05282f7cf1510a06d6d93d554c1df Author: Kevin Bowling AuthorDate: 2026-08-26 10:54:59 +0000 Commit: Kevin Bowling CommitDate: 2026-09-03 03:55:24 +0000 tpm_tis: Restore validated interrupts after resume TIS interrupt routing and enable registers may lose their state across S3, while the driver retains its software indication that interrupts work. A subsequent locality or command wait can then sleep for an interrupt that cannot arrive. Remember whether interrupts worked before suspend and restore the vector, pending status, and enable mask before TPM2_Startup. Put the transport in polling mode first; the interrupt handler promotes it back to interrupt waits only after observing an interrupt from the restored configuration. If register restoration fails, Startup and subsequent commands continue using polling. Preserve the initial interrupt-enable mask, including the firmware's trigger and polarity selection proven by the attach time interrupt test, and restore that exact mask rather than accepting post-S3 defaults. Program the same safe baseline for polling devices during attach and resume. Acquire locality, disable global interrupt delivery, and acknowledge pending status so firmware cannot leave interrupts armed without a handler. Use the same register programming helper during attach and resume, and stop trying to configure interrupts after a locality acquisition failure. Three consecutive device suspend and resume cycles completed on a Lenovo TPM2 FIFO device without an IRQ resource. GetRandom succeeded after each resume, and module detach completed without errors. Reviewed by: kevans MFC after: 2 weeks Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59197 --- sys/dev/tpm/tpm20.h | 1 + sys/dev/tpm/tpm_tis_core.c | 104 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 24 deletions(-) diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h index 7570812219b9..3bf59112bed8 100644 --- a/sys/dev/tpm/tpm20.h +++ b/sys/dev/tpm/tpm20.h @@ -127,6 +127,7 @@ struct tpm_sc { void *intr_cookie; int intr_type; /* Current event type */ + uint32_t intr_mask; /* Saved TIS interrupt configuration */ bool interrupts; bool common_initialized; diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c index 15370e648f1e..f4b8ef23b3c7 100644 --- a/sys/dev/tpm/tpm_tis_core.c +++ b/sys/dev/tpm/tpm_tis_core.c @@ -79,7 +79,9 @@ static int tpmtis_detach(device_t dev); static void tpmtis_intr_handler(void *arg); +static bool tpmtis_program_intr(struct tpm_sc *sc, bool enable); static void tpmtis_setup_intr(struct tpm_sc *sc); +static int tpmtis_resume(device_t dev); static bool tpmtis_read_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf); static bool tpmtis_write_bytes(struct tpm_sc *sc, size_t count, uint8_t *buf); @@ -131,8 +133,7 @@ skip_irq: tpmtis_detach(dev); return (result); } - if (sc->intr_cookie != NULL) - tpmtis_setup_intr(sc); + tpmtis_setup_intr(sc); return (0); } @@ -182,43 +183,98 @@ tpmtis_test_intr(struct tpm_sc *sc) sx_xunlock(&sc->dev_lock); } -static void -tpmtis_setup_intr(struct tpm_sc *sc) +static bool +tpmtis_program_intr(struct tpm_sc *sc, bool enable) { + rman_res_t irq; uint32_t reg; - uint8_t irq; - irq = bus_get_resource_start(sc->dev, SYS_RES_IRQ, sc->irq_rid); + sx_assert(&sc->dev_lock, SA_XLOCKED); - /* - * SIRQ has to be between 1 - 15. - * I found a system with ACPI table that reported a value of 0x2d. - * An attempt to use such value resulted in an interrupt storm. - */ - if (irq == 0 || irq > 0xF) - return; + if (enable) { + irq = bus_get_resource_start(sc->dev, SYS_RES_IRQ, + sc->irq_rid); + + /* + * SIRQ has to be between 1 - 15. A system reporting 0x2d + * produced an interrupt storm when that value was used. + */ + if (irq == 0 || irq > 0xF) + return (false); + } - if(!tpmtis_request_locality(sc, 0)) - sc->interrupts = false; + if (!tpmtis_request_locality(sc, 0)) + return (false); - TPM_WRITE_1(sc->dev, TPM_INT_VECTOR, irq); + /* Disable delivery before acknowledging or reconfiguring interrupts. */ + reg = TPM_READ_4(sc->dev, TPM_INT_ENABLE); + reg &= ~TPM_INT_ENABLE_GLOBAL_ENABLE; + TPM_WRITE_4(sc->dev, TPM_INT_ENABLE, reg); /* Clear all pending interrupts. */ reg = TPM_READ_4(sc->dev, TPM_INT_STS); TPM_WRITE_4(sc->dev, TPM_INT_STS, reg); - reg = TPM_READ_4(sc->dev, TPM_INT_ENABLE); - reg |= TPM_INT_ENABLE_GLOBAL_ENABLE | - TPM_INT_ENABLE_DATA_AVAIL | - TPM_INT_ENABLE_LOC_CHANGE | - TPM_INT_ENABLE_CMD_RDY | - TPM_INT_ENABLE_STS_VALID; - TPM_WRITE_4(sc->dev, TPM_INT_ENABLE, reg); + if (enable) { + TPM_WRITE_1(sc->dev, TPM_INT_VECTOR, (uint8_t)irq); + + if (sc->intr_mask == 0) { + reg = TPM_READ_4(sc->dev, TPM_INT_ENABLE); + reg |= TPM_INT_ENABLE_DATA_AVAIL | + TPM_INT_ENABLE_LOC_CHANGE | + TPM_INT_ENABLE_CMD_RDY | + TPM_INT_ENABLE_STS_VALID; + reg &= ~TPM_INT_ENABLE_GLOBAL_ENABLE; + sc->intr_mask = reg; + } + TPM_WRITE_4(sc->dev, TPM_INT_ENABLE, + sc->intr_mask | TPM_INT_ENABLE_GLOBAL_ENABLE); + } tpmtis_relinquish_locality(sc); + return (true); +} + +static void +tpmtis_setup_intr(struct tpm_sc *sc) +{ + bool configured, enable; + + sc->interrupts = false; + enable = sc->intr_cookie != NULL; + sx_xlock(&sc->dev_lock); + configured = tpmtis_program_intr(sc, enable); + sx_xunlock(&sc->dev_lock); + if (!configured || !enable) + return; tpmtis_test_intr(sc); } +static int +tpmtis_resume(device_t dev) +{ + struct tpm_sc *sc; + bool restore_intr; + + sc = device_get_softc(dev); + sx_xlock(&sc->dev_lock); + restore_intr = sc->interrupts; + + /* + * Interrupt routing and enable state may be lost across suspend. Keep + * the transport in polling mode until a restored interrupt is actually + * observed by the handler. + */ + sc->interrupts = false; + if (!tpmtis_program_intr(sc, restore_intr)) + device_printf(dev, + "failed to %s interrupts; using polling\n", + restore_intr ? "restore" : "disable"); + sx_xunlock(&sc->dev_lock); + + return (tpm20_resume(dev)); +} + static void tpmtis_intr_handler(void *arg) { @@ -501,7 +557,7 @@ static device_method_t tpmtis_methods[] = { DEVMETHOD(device_detach, tpmtis_detach), DEVMETHOD(device_shutdown, tpm20_shutdown), DEVMETHOD(device_suspend, tpm20_suspend), - DEVMETHOD(device_resume, tpm20_resume), + DEVMETHOD(device_resume, tpmtis_resume), DEVMETHOD(tpm_transmit, tpmtis_transmit), DEVMETHOD_END };