From nobody Thu Sep 03 04:01:52 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 4hb5Wp2qmQz6qWVR for ; Thu, 03 Sep 2026 04:01:58 +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 4hb5Wp1r7qz3qw1 for ; Thu, 03 Sep 2026 04:01:58 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788408118; 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=kkkdc+fXgtoyImVB9O61HIk5ViRPZJqTAM6AD7x2oiOkuq+TThvb76X3gP2DQcTawOoxdw lnvsxfw7JILqdZDP2v+Tt6uRCaabSIYvhS/HfORca3WqlIJCG7Y1MXtyV64Xrut00STy9I 2F+F0dxMDAYqudcB0YVuOeUlGyo9+qajlUSN3zg4mGUucMA7VxGJiJ7I7whqwGBXL1aPFK +f3NVM5oO1VQnjQ6ywY0cQPH5ZP+8z8xras7BndrtY3YvIpn8eDurWMFdHw3z8sGsr/7Rp QTdtby0XdFcVHAPW18SU0MnU9fGjT+XGCDdZc2pmw+kcIrXYidQda//ANl4Q5w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788408118; a=rsa-sha256; cv=none; b=rvXu2kFI9LgAGkRGWuZcV1E9QPBxmM3dQFrSc21Wkm4tyOx/vRs0GV4AKzhlVJeNDxurtH dtOQAP2uRetOp2oHTiMG926Z5xWhPQAT8Ar25XJWiG/upWSlinwKeCLSaqiUQN5bhWRxwA y2XuNMQ4ljTVILPPWVAFMUfKKlKhG7p08HHrCgNr+1QyykTnh281XoMbUQ91bucrGlXi9J o6C6Beakyb0Y0NI/dC6HS+g//4cMVhAP2weDIPGfr3re7fzxToOP/4+Gn2xQBICCL5O3RT y0DgtpRKrY+6mne/cPvpPduZ7w1QUcTIO4B0CCzyXIWPexqqbl4nVk6R7FO/kg== 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=1788408118; 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=GCof1fhr2z+6bK2s+LZwukSeuBOFBMmU/yqSsfLaxa38CdQWzY0dpi3Tydkquj9MVDEuyI +bdC+WLFp2VEHJ4NXzcOyxOMaxIxqexxWQlFDBCr8UP1jwDi9jV/Zx9DWmObvNTWxy0192 pk1cKlZmIqYeZu1MOuFYvWYh/NhzSiK7NXUbqEFRk/rMg8I8SNaEeYXXBDfoEoqikoanyj xQXLSyEBShBNFAKMVVVbjAepZ6uBOr8tXkEBaCSQC70lGjwS2+QUW0bztQsyfvgDL5Q7gh Lhbh/1BpF5e/9gtBEDazKT+3Bpf7m92rvdSBmVp5DPeoYUjgNnsgi8xLqHFGUw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hb5Wp0Mlkz1C2m for ; Thu, 03 Sep 2026 04:01:58 +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 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: 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 */