From nobody Thu Sep 03 04:01:52 2026 X-Original-To: dev-commits-src-main@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 4hb5Wj15mPz6qWmW for ; Thu, 03 Sep 2026 04:01:53 +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 4hb5Wj0LCWz3r0k for ; Thu, 03 Sep 2026 04:01:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788408113; 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=d1n6yZPk+yDAndpotoE03DuhXTps0uPqADx8yjUK3x8=; b=gwOB3ZGl1BmeXNyOAVx3Whvk8mx7GOr85nsMt/0JZFRm+rWIfUJ07HYV3An6IGGBfqYZzm fD/0OoIn6ypq7JcTZZZim7D/Ny7AM/HuxFhobanPEK8XDUjn0pTFq2yh2uDhqyIWrEhRFx dQR+3P+HhvTIvQ9cjusnEiAbBGtLczJJB1snZF2lSd2bG0LqkmsG8z5UazzjzOBRM7X9U7 kl4BMbFDWu+MMJs+/uU41JpQxcSRTUgeZ33yOSKlUMdF4cXBAJu6eWjd5qdGgELDeXsKIW pkMG6GQgASwFEkyiXaP+7neBhrvjU6M7i8sqetTeMZDDj+ht5DgCP2Ir0moYIg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788408113; a=rsa-sha256; cv=none; b=qF2IHmi+s8fcpUrdTK5mmLyab3zlGfi01Hov9UG/uouLvny1D2fwAoENkWf8kYqSRq/K+g yBRI/AeTqwxiTkAyqsMdDBlrDTZb06juHFfANkFkqGrhz87H7pPJ7YtpjqKYxdd1I5h1+k h/hX3ZLzd8WyFyQPCwFrmdov/ZL5ut4Z9Q6swpzZrX3BfD1wUZ15BRElz4cJRNa5fews1M tNC0b0A/52qLASZzD3AgR7RBVDTqaVSblOZXiPn8d/7Er2IWKBJ8gnkhyFHxqp8VaVO3/6 GJq6Ok12F8WT2YQ+eeSWSqWacjlbr+fXLfpKgr7L+oAi+C0qvA2LVm4xIgdG9w== 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=1788408113; 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=d1n6yZPk+yDAndpotoE03DuhXTps0uPqADx8yjUK3x8=; b=uVPbPLFlNChdUpH3hqhPAQq52kiZwDL+5Dud1zxl8wgRKMt4nxYW9yuhzzgqLsx+iamWH+ GNwJSkZ4SXjrs0TdLR0pC2Lx0BT1tpZ5g/6k4/nYC4s0j7dcnWO8yrILiFuoeOJ0hjlBfP 3+07wvAkJdOeA+WXn64+uKo7n7HQZdudTEj72QsT2XTll7eupEXc94wRxvUZpXqWwuPsve EnC1iwVAc1lqJIcLPoSmc1GoJyUOcfIp1jJDUxuyXG+eQ/HqireV+nE4QyTa6ZkHHo2Qks 8Hc5ShPfGSx04WxiAvSJIxW0jUz7x4QllbvSjjGdBg9aRI2PfslXQk+yVjkqsA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hb5Wh6M7fz1C9V for ; Thu, 03 Sep 2026 04:01:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 392fc by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 03 Sep 2026 04:01:52 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 2fe8510b0a06 - main - tpm20: Release transport state after command failures List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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: 2fe8510b0a06ad577789ece7be8c9319c8ce3d06 Auto-Submitted: auto-generated Date: Thu, 03 Sep 2026 04:01:52 +0000 Message-Id: <6a98f130.392fc.b60425b@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=2fe8510b0a06ad577789ece7be8c9319c8ce3d06 commit 2fe8510b0a06ad577789ece7be8c9319c8ce3d06 Author: Kevin Bowling AuthorDate: 2026-08-27 12:48:05 +0000 Commit: Kevin Bowling CommitDate: 2026-09-03 04:00:45 +0000 tpm20: Release transport state after command failures Once a transport acquires locality, several TIS and CRB error paths return without relinquishing it. They can also leave a partial FIFO transaction or an active CRB command for the next operation to inherit. Route post-locality exits through common cleanup. Reset the TIS command state on every attempt. For CRB, cancel an active failed command when necessary, request the idle state, and relinquish locality even when the state transition itself fails. Successful command handling is unchanged apart from sharing the same cleanup path. Reviewed by: kevans MFC after: 2 weeks Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D59243 --- sys/dev/tpm/tpm_crb.c | 57 ++++++++++++++++++++++++++--------------- sys/dev/tpm/tpm_tis_core.c | 63 +++++++++++++++++++++++++++++----------------- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c index ac093c3857ba..3e567e215313 100644 --- a/sys/dev/tpm/tpm_crb.c +++ b/sys/dev/tpm/tpm_crb.c @@ -484,12 +484,15 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) struct tpmcrb_sc *crb_sc; struct tpm_sc *sc; uint32_t mask, curr_cmd; - int timeout, bytes_available; + int bytes_available, error, timeout; + bool command_started, locality; crb_sc = device_get_softc(dev); sc = &crb_sc->base; sx_assert(&sc->dev_lock, SA_XLOCKED); + command_started = false; + locality = false; if (length > crb_sc->cmd_buf_size) { device_printf(dev, @@ -507,6 +510,7 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) "Failed to obtain locality\n"); return (EIO); } + locality = true; /* Clear cancellation bit */ TPM_WRITE_4(dev, TPM_CRB_CTRL_CANCEL, TPM_CRB_CTRL_CANCEL_CLEAR); @@ -515,7 +519,8 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) if (!tpmcrb_state_idle(crb_sc, true)) { device_printf(dev, "Failed to transition to idle state\n"); - return (EIO); + error = EIO; + goto out; } } @@ -523,7 +528,8 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) if (!tpmcrb_state_ready(crb_sc, true)) { device_printf(dev, "Failed to transition to ready state\n"); - return (EIO); + error = EIO; + goto out; } /* @@ -540,20 +546,25 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) TPM_WRITE_4(dev, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD); TPM_WRITE_BARRIER(dev, TPM_CRB_CTRL_START, 4); + command_started = true; if (!tpmcrb_notify_cmdready(crb_sc, timeout)) { device_printf(dev, "Timeout while waiting for device to ready\n"); - if (!tpmcrb_cancel_cmd(sc)) - return (EIO); + if (!tpmcrb_cancel_cmd(sc)) { + error = EIO; + goto out; + } } mask = ~0; if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) { device_printf(dev, "Timeout while waiting for device to process cmd\n"); - if (!tpmcrb_cancel_cmd(sc)) - return (EIO); + if (!tpmcrb_cancel_cmd(sc)) { + error = EIO; + goto out; + } } /* Read response header. Length is passed in bytes 2 - 6. */ @@ -565,27 +576,33 @@ tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) device_printf(dev, "Incorrect response size: %d\n", bytes_available); - return (EIO); + error = EIO; + goto out; } bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE, &priv->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE); - /* - * No need to wait for the transition to idle on the way out, we can - * relinquish locality right away. - */ - 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); priv->offset = 0; priv->len = bytes_available; + error = 0; + +out: + if (locality) { + if (error != 0 && command_started && + (TPM_READ_4(dev, TPM_CRB_CTRL_START) & + TPM_CRB_CTRL_START_CMD) != 0) + (void)tpmcrb_cancel_cmd(sc); + if (!tpmcrb_state_idle(crb_sc, false)) { + device_printf(dev, + "Failed to transition to idle state post-send\n"); + if (error == 0) + error = EIO; + } + tpmcrb_relinquish_locality(sc); + } - return (0); + return (error); } /* StartMethod Implementation Details */ diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c index 08d37ebcfe19..785c887e58cf 100644 --- a/sys/dev/tpm/tpm_tis_core.c +++ b/sys/dev/tpm/tpm_tis_core.c @@ -487,25 +487,30 @@ tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length) struct tpm_sc *sc; size_t bytes_available; uint32_t mask, curr_cmd; - int timeout; + int error, timeout; + bool locality; sc = device_get_softc(dev); sx_assert(&sc->dev_lock, SA_XLOCKED); + locality = false; if (!tpmtis_request_locality(sc, 0)) { device_printf(dev, "Failed to obtain locality\n"); return (EIO); } + locality = true; if (!tpmtis_go_ready(sc)) { device_printf(dev, "Failed to switch to ready state\n"); - return (EIO); + error = EIO; + goto out; } if (!tpmtis_write_bytes(sc, length, priv->buf)) { device_printf(dev, "Failed to write cmd to device\n"); - return (EIO); + error = EIO; + goto out; } mask = TPM_STS_VALID; @@ -513,13 +518,15 @@ tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length) TPM_INT_STS_VALID, true)) { device_printf(dev, "Timeout while waiting for valid bit\n"); - return (EIO); + error = EIO; + goto out; } if (TPM_READ_4(dev, TPM_STS) & TPM_STS_DATA_EXPECTED) { device_printf(dev, "Device expects more data even though we already" " sent everything we had\n"); - return (EIO); + error = EIO; + goto out; } /* @@ -541,22 +548,27 @@ tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length) * Switching to ready state also cancels processing * current command */ - if (!tpmtis_go_ready(sc)) - return (EIO); + if (!tpmtis_go_ready(sc)) { + error = EIO; + goto out; + } /* * After canceling a command we should get a response, * check if there is one. */ if (!tpm_wait_for_reg(sc, TPM_STS, mask, mask, TPM_TIMEOUT_C, - TPM_INT_STS_DATA_AVAIL, true)) - return (EIO); + TPM_INT_STS_DATA_AVAIL, true)) { + error = EIO; + goto out; + } } /* Read response header. Length is passed in bytes 2 - 6. */ if (!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, priv->buf)) { device_printf(dev, "Failed to read response header\n"); - return (EIO); + error = EIO; + goto out; } bytes_available = be32toh(*(uint32_t *) (&priv->buf[2])); @@ -564,29 +576,34 @@ tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length) device_printf(dev, "Incorrect response size: %zu\n", bytes_available); - return (EIO); + error = EIO; + goto out; } if (!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE, &priv->buf[TPM_HEADER_SIZE])) { device_printf(dev, "Failed to read response\n"); - return (EIO); + error = EIO; + goto out; } + priv->offset = 0; + priv->len = bytes_available; + error = 0; +out: /* - * Per TIS 1.3 section 5.6.12, write commandReady after reading the - * response so the TPM can free the ReadFIFO and other internal - * resources. The next tpmtis_go_ready() provides the second - * write the spec mentions, and waits for the state transition, - * so no wait is needed here. + * Per TIS 1.3 section 5.6.12, write commandReady after every command + * attempt so the TPM can discard a partial FIFO transaction and free + * its internal resources. The next tpmtis_go_ready() provides the + * second write the spec mentions and waits for the state transition. */ - TPM_WRITE_4(sc->dev, TPM_STS, TPM_STS_CMD_RDY); - TPM_WRITE_BARRIER(sc->dev, TPM_STS, 4); - tpmtis_relinquish_locality(sc); - priv->offset = 0; - priv->len = bytes_available; + if (locality) { + TPM_WRITE_4(sc->dev, TPM_STS, TPM_STS_CMD_RDY); + TPM_WRITE_BARRIER(sc->dev, TPM_STS, 4); + tpmtis_relinquish_locality(sc); + } - return (0); + return (error); } /* ACPI Driver */