From patchwork Thu Mar 6 09:00:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan McDowell X-Patchwork-Id: 14004048 Received: from the.earth.li (the.earth.li [93.93.131.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26CF019D071; Thu, 6 Mar 2025 09:01:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=93.93.131.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741251666; cv=none; b=XVZ1+kGYXio0dxYy/h/zGIiyA6q6b5nNo63sTDPR+9s8hzl2SbLutEB5t3uTwbFiZbd5sXDyhyqcfOIlqMFU8muFlukwFz5nqbqpmKP5s25N9eYoZMszI2WUmcSiM2aVGRRfZwzVZcJPC3TAEM27wpjHVXWVt1P9mwLT28ngJsQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741251666; c=relaxed/simple; bh=bFPyYCMrzKR8vp8DZ4QjKL2f7mF9ZTGXU+XgZbC8/SE=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=HhvgE5Hgv4L5uKm2f5Hb/cEv1+ox+stjg7R/IqAlWqoSvvTAFcavrgymXembcyTbbSotfBRwEJlrP0cG2lFywa1iHWNGcTrbHdZlGSc3ShniHjT+YiO1moZBzko5rK4xsv5jeNTmHX+AoIPQ6PTPG5iTaIOuNlnTHZc7Yv793Dg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=earth.li; spf=pass smtp.mailfrom=earth.li; dkim=pass (2048-bit key) header.d=earth.li header.i=@earth.li header.b=SOMuJmNd; arc=none smtp.client-ip=93.93.131.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=earth.li Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=earth.li Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=earth.li header.i=@earth.li header.b="SOMuJmNd" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=earth.li; s=the; h=Content-Type:MIME-Version:Message-ID:Subject:Cc:To:From:Date:Sender: Reply-To:Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date :Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=6IrX1eM8G/pcQ9Ik0E9LCERhzGjEzWP/RJw7jGqJxW4=; b=S OMuJmNdn7T7jkpjiqYfIS8QIoC9gxUfeBwfleKjzyilJ0Yhkvtc2rqhlhx6a9bsiS15557l9+hjoh 1z9tPEAvdoJUVFSz240v3wDV0lJEdS233gZCzO6n9DM/WEqjvdOlc/hYO5HK9xHFge1lWJ0KVCyvo B8karKoa6UM33TZaHkPs4OkFx9a2DyQJsO48VbW1K8w+Xo8gCgNNMcT3UfOo8dUGMIv3ghU9WJytq Q/Aw2KHAKoFemjyKiLHcBHa7ymfx6aGwUqA0OApxmSCvoUoSf+b40ra6CD1H1FPg5imTec+dL+Ftu dcxq+huiqtGU9N1RIY3qHTSEDO6+2FwtA==; Received: from noodles by the.earth.li with local (Exim 4.96) (envelope-from ) id 1tq768-00BiOQ-17; Thu, 06 Mar 2025 09:00:56 +0000 Date: Thu, 6 Mar 2025 09:00:56 +0000 From: Jonathan McDowell To: Jarkko Sakkinen , Peter Huewe , Jason Gunthorpe , James Bottomley , Stefan Berger Cc: linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] tpm, tpm_tis: Workaround failed command reception on Infineon devices Message-ID: Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline From: Jonathan McDowell Some Infineon devices have a issue where the status register will get stuck with a quick REQUEST_USE / COMMAND_READY sequence. This is not simply a matter of requiring a longer timeout; the work around is to retry the command submission. Add appropriate logic to do this in the send path. This is fixed in later firmware revisions, but those are not always available, and cannot generally be easily updated from outside a firmware environment. Testing has been performed with a simple repeated loop of doing a TPM2_CC_GET_CAPABILITY for TPM_CAP_PROP_MANUFACTURER using the Go code at: https://the.earth.li/~noodles/tpm-stuff/timeout-reproducer-simple.go It can take several hours to reproduce, and millions of operations. Signed-off-by: Jonathan McDowell --- drivers/char/tpm/tpm_tis_core.c | 17 ++++++++++++++--- drivers/char/tpm/tpm_tis_core.h | 1 + include/linux/tpm.h | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 167d71747666..e4eae206a353 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -464,7 +464,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, &priv->int_queue, false) < 0) { - rc = -ETIME; + if (test_bit(TPM_TIS_STATUS_WORKAROUND, &priv->flags)) + rc = -EAGAIN; + else + rc = -ETIME; goto out_err; } status = tpm_tis_status(chip); @@ -481,7 +484,10 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, &priv->int_queue, false) < 0) { - rc = -ETIME; + if (test_bit(TPM_TIS_STATUS_WORKAROUND, &priv->flags)) + rc = -EAGAIN; + else + rc = -ETIME; goto out_err; } status = tpm_tis_status(chip); @@ -546,9 +552,11 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) if (rc >= 0) /* Data transfer done successfully */ break; - else if (rc != -EIO) + else if (rc != EAGAIN && rc != -EIO) /* Data transfer failed, not recoverable */ return rc; + + usleep_range(priv->timeout_min, priv->timeout_max); } /* go and do it */ @@ -1144,6 +1152,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, priv->timeout_max = TIS_TIMEOUT_MAX_ATML; } + if (priv->manufacturer_id == TPM_VID_IFX) + set_bit(TPM_TIS_STATUS_WORKAROUND, &priv->flags); + if (is_bsw()) { priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, ILB_REMAP_SIZE); diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index 690ad8e9b731..ce97b58dc005 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -89,6 +89,7 @@ enum tpm_tis_flags { TPM_TIS_INVALID_STATUS = 1, TPM_TIS_DEFAULT_CANCELLATION = 2, TPM_TIS_IRQ_TESTED = 3, + TPM_TIS_STATUS_WORKAROUND = 4, }; struct tpm_tis_data { diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 20a40ade8030..6c3125300c00 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -335,6 +335,7 @@ enum tpm2_cc_attrs { #define TPM_VID_WINBOND 0x1050 #define TPM_VID_STM 0x104A #define TPM_VID_ATML 0x1114 +#define TPM_VID_IFX 0x15D1 enum tpm_chip_flags { TPM_CHIP_FLAG_BOOTSTRAPPED = BIT(0),