From nobody Sun Oct 11 01:06:59 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 4j2MrM5q1kz6w8S8 for ; Sun, 11 Oct 2026 01:06:59 +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 4j2MrM3wGwz3HD1 for ; Sun, 11 Oct 2026 01:06:59 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791680819; 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=loUYQaasSPupgemw0CWFGRYKQwIGIpGN3DBf2b/7CIg=; b=Il6XYmd3QFtofAcmbt91g20yzxAjcSVjkN4g5GeDtmbUMnygn3cn5ZYjZiYit4ePYuChuc FbG8b6N8RUK3dKqkrDMJKzkwoAqZCP1/YH2QzKGKjrAjJcxZ6Bn0x3EJ25fjbNzPBshW7g 8dZ0ymjMMkpptSivyVvEqHx1xauku6w8QP/tNgwjs/x9VR2VZtbDs+ItOKzwelVkWHh1nf hzoTxChoCTC6OCWkvwWoGh5g1oDgrdX3OlVmwDfu8DRPoLttdw8u/V1X7rRlaribIowEMe z7nJfqi1YDPY1I+ZRi3r0GjUEBCeseGFbvaDYfjA1fUwSR8eJCO2KhGcW+9EUQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791680819; b=dpYQx8JTmhV7zUNq/g7UH2X2AH5erYByYdMdmFitT3PW7zEH/UekY4Tl4mhh4krf3V010l Wa9gpr0WQ9k60s6sssRe3jQt5phianFHhG6PRHXEH4z81Hv+P/M64aW70se4pSZcaP2bC/ OtzL7ihWs+5727qbDghI79md0jQ+lbDiHPGoCA3L8qDPN4Io7YXP7ClrhGkdZozXsFvoGS wglNghnvJhobhjvKBStkF6xYcOOOWQ+j/ftYpWQs3/yNBszwNq2CSZhdaa7pB4cLK30ivu /L8ySI/hSxDV8F2ze1/ltWBvkwoFFMc+9PMukcq6ddYnzxQ55xvytFP8h6KF+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791680819; 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=loUYQaasSPupgemw0CWFGRYKQwIGIpGN3DBf2b/7CIg=; b=rFqluZpbGsjHuOZ9OH2Klweg6IiOelSNkof3cPH0O5Nh+u7HRli2wsqyuy3AzzY9Wh0aXG wtMSRe2WY0YNOHx4i/4CI+G2Vp+20GxDnEQtMb/mHicKa4ZYp/RN6NTJsKEFjTTqsLpeCu cUGVwyyNP2oQ/xoWzmjeXNA0jRy3oaBfFG+mJ+i1OZkTDlNZrko5ZlFXEfb7Bs6o60IsgH Lksre6qEBkGRbPEFHoHNQn9uPs7nZuNxohD7FWyn2fgz80AVJWNLfZmhTCSQYMVmoyqRDp TxZf/sb5wA3fefrOQZWFO5FmOZds+omoq8oq22H3tXv03TlxnL7GLWJyEg0v1A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j2MrM30pMzJLQ for ; Sun, 11 Oct 2026 01:06:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33b26 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 11 Oct 2026 01:06:59 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 55c97a16dfcc - stable/15 - tpm_tis: Restore validated interrupts after resume List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository 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/stable/15 X-Git-Reftype: branch X-Git-Commit: 55c97a16dfcc1237ba8fdd37175987ca3281b29c Auto-Submitted: auto-generated Date: Sun, 11 Oct 2026 01:06:59 +0000 Message-Id: <6acae133.33b26.97af@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=55c97a16dfcc1237ba8fdd37175987ca3281b29c commit 55c97a16dfcc1237ba8fdd37175987ca3281b29c Author: Kevin Bowling AuthorDate: 2026-08-26 10:54:59 +0000 Commit: Kevin Bowling CommitDate: 2026-10-11 01:06:47 +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 Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59197 (cherry picked from commit a229432d3ed05282f7cf1510a06d6d93d554c1df) --- 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 762aa1f7fd75..66263a13ce97 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) { @@ -491,7 +547,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 };