Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935625AbdCJJ3I (ORCPT ); Fri, 10 Mar 2017 04:29:08 -0500 Received: from mail.linuxfoundation.org ([140.211.169.12]:39668 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934942AbdCJJ3E (ORCPT ); Fri, 10 Mar 2017 04:29:04 -0500 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "Maciej S. Szmigiero" , Jarkko Sakkinen Subject: [PATCH 4.10 040/167] tpm_tis: use default timeout value if chip reports it as zero Date: Fri, 10 Mar 2017 10:08:03 +0100 Message-Id: <20170310083959.624353169@linuxfoundation.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170310083956.767605269@linuxfoundation.org> References: <20170310083956.767605269@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6342 Lines: 177 4.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Maciej S. Szmigiero commit 1d70fe9d9c3a4c627f9757cbba5d628687b121c1 upstream. Since commit 1107d065fdf1 ("tpm_tis: Introduce intermediate layer for TPM access") Atmel 3203 TPM on ThinkPad X61S (TPM firmware version 13.9) no longer works. The initialization proceeds fine until we get and start using chip-reported timeouts - and the chip reports C and D timeouts of zero. It turns out that until commit 8e54caf407b98e ("tpm: Provide a generic means to override the chip returned timeouts") we had actually let default timeout values remain in this case, so let's bring back this behavior to make chips like Atmel 3203 work again. Use a common code that was introduced by that commit so a warning is printed in this case and /sys/class/tpm/tpm*/timeouts correctly says the timeouts aren't chip-original. Fixes: 1107d065fdf1 ("tpm_tis: Introduce intermediate layer for TPM access") Signed-off-by: Maciej S. Szmigiero Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-interface.c | 53 +++++++++++++++++++++++---------------- drivers/char/tpm/tpm_tis.c | 2 - drivers/char/tpm/tpm_tis_core.c | 6 ++-- drivers/char/tpm/tpm_tis_core.h | 2 - 4 files changed, 37 insertions(+), 26 deletions(-) --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -499,8 +499,7 @@ static int tpm_startup(struct tpm_chip * int tpm_get_timeouts(struct tpm_chip *chip) { cap_t cap; - unsigned long new_timeout[4]; - unsigned long old_timeout[4]; + unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; ssize_t rc; if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS) @@ -538,11 +537,15 @@ int tpm_get_timeouts(struct tpm_chip *ch if (rc) return rc; - old_timeout[0] = be32_to_cpu(cap.timeout.a); - old_timeout[1] = be32_to_cpu(cap.timeout.b); - old_timeout[2] = be32_to_cpu(cap.timeout.c); - old_timeout[3] = be32_to_cpu(cap.timeout.d); - memcpy(new_timeout, old_timeout, sizeof(new_timeout)); + timeout_old[0] = jiffies_to_usecs(chip->timeout_a); + timeout_old[1] = jiffies_to_usecs(chip->timeout_b); + timeout_old[2] = jiffies_to_usecs(chip->timeout_c); + timeout_old[3] = jiffies_to_usecs(chip->timeout_d); + timeout_chip[0] = be32_to_cpu(cap.timeout.a); + timeout_chip[1] = be32_to_cpu(cap.timeout.b); + timeout_chip[2] = be32_to_cpu(cap.timeout.c); + timeout_chip[3] = be32_to_cpu(cap.timeout.d); + memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); /* * Provide ability for vendor overrides of timeout values in case @@ -550,16 +553,24 @@ int tpm_get_timeouts(struct tpm_chip *ch */ if (chip->ops->update_timeouts != NULL) chip->timeout_adjusted = - chip->ops->update_timeouts(chip, new_timeout); + chip->ops->update_timeouts(chip, timeout_eff); if (!chip->timeout_adjusted) { - /* Don't overwrite default if value is 0 */ - if (new_timeout[0] != 0 && new_timeout[0] < 1000) { - int i; + /* Restore default if chip reported 0 */ + int i; + for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) { + if (timeout_eff[i]) + continue; + + timeout_eff[i] = timeout_old[i]; + chip->timeout_adjusted = true; + } + + if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) { /* timeouts in msec rather usec */ - for (i = 0; i != ARRAY_SIZE(new_timeout); i++) - new_timeout[i] *= 1000; + for (i = 0; i != ARRAY_SIZE(timeout_eff); i++) + timeout_eff[i] *= 1000; chip->timeout_adjusted = true; } } @@ -568,16 +579,16 @@ int tpm_get_timeouts(struct tpm_chip *ch if (chip->timeout_adjusted) { dev_info(&chip->dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", - old_timeout[0], new_timeout[0], - old_timeout[1], new_timeout[1], - old_timeout[2], new_timeout[2], - old_timeout[3], new_timeout[3]); + timeout_chip[0], timeout_eff[0], + timeout_chip[1], timeout_eff[1], + timeout_chip[2], timeout_eff[2], + timeout_chip[3], timeout_eff[3]); } - chip->timeout_a = usecs_to_jiffies(new_timeout[0]); - chip->timeout_b = usecs_to_jiffies(new_timeout[1]); - chip->timeout_c = usecs_to_jiffies(new_timeout[2]); - chip->timeout_d = usecs_to_jiffies(new_timeout[3]); + chip->timeout_a = usecs_to_jiffies(timeout_eff[0]); + chip->timeout_b = usecs_to_jiffies(timeout_eff[1]); + chip->timeout_c = usecs_to_jiffies(timeout_eff[2]); + chip->timeout_d = usecs_to_jiffies(timeout_eff[3]); rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap, "attempting to determine the durations"); --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -159,7 +159,7 @@ static int tpm_tis_init(struct device *d irq = tpm_info->irq; if (itpm) - phy->priv.flags |= TPM_TIS_ITPM_POSSIBLE; + phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND; return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg, acpi_dev_handle); --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -264,7 +264,7 @@ static int tpm_tis_send_data(struct tpm_ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int rc, status, burstcnt; size_t count = 0; - bool itpm = priv->flags & TPM_TIS_ITPM_POSSIBLE; + bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; if (request_locality(chip, 0) < 0) return -EBUSY; @@ -740,7 +740,7 @@ int tpm_tis_core_init(struct device *dev (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", vendor >> 16, rid); - if (!(priv->flags & TPM_TIS_ITPM_POSSIBLE)) { + if (!(priv->flags & TPM_TIS_ITPM_WORKAROUND)) { probe = probe_itpm(chip); if (probe < 0) { rc = -ENODEV; @@ -748,7 +748,7 @@ int tpm_tis_core_init(struct device *dev } if (!!probe) - priv->flags |= TPM_TIS_ITPM_POSSIBLE; + priv->flags |= TPM_TIS_ITPM_WORKAROUND; } /* Figure out the capabilities */ --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -80,7 +80,7 @@ enum tis_defaults { #define TPM_RID(l) (0x0F04 | ((l) << 12)) enum tpm_tis_flags { - TPM_TIS_ITPM_POSSIBLE = BIT(0), + TPM_TIS_ITPM_WORKAROUND = BIT(0), }; struct tpm_tis_data {