Skip to content

Commit 1d70fe9

Browse files
maciejsszmigieroJarkko Sakkinen
authored andcommitted
tpm_tis: use default timeout value if chip reports it as zero
Since commit 1107d06 ("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 8e54caf ("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: 1107d06 ("tpm_tis: Introduce intermediate layer for TPM access") Cc: stable@vger.kernel.org Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
1 parent 62bfdac commit 1d70fe9

File tree

4 files changed

+37
-26
lines changed

4 files changed

+37
-26
lines changed

drivers/char/tpm/tpm-interface.c

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
522522
int tpm_get_timeouts(struct tpm_chip *chip)
523523
{
524524
cap_t cap;
525-
unsigned long new_timeout[4];
526-
unsigned long old_timeout[4];
525+
unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
527526
ssize_t rc;
528527

529528
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
@@ -564,28 +563,40 @@ int tpm_get_timeouts(struct tpm_chip *chip)
564563
return rc;
565564
}
566565

567-
old_timeout[0] = be32_to_cpu(cap.timeout.a);
568-
old_timeout[1] = be32_to_cpu(cap.timeout.b);
569-
old_timeout[2] = be32_to_cpu(cap.timeout.c);
570-
old_timeout[3] = be32_to_cpu(cap.timeout.d);
571-
memcpy(new_timeout, old_timeout, sizeof(new_timeout));
566+
timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
567+
timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
568+
timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
569+
timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
570+
timeout_chip[0] = be32_to_cpu(cap.timeout.a);
571+
timeout_chip[1] = be32_to_cpu(cap.timeout.b);
572+
timeout_chip[2] = be32_to_cpu(cap.timeout.c);
573+
timeout_chip[3] = be32_to_cpu(cap.timeout.d);
574+
memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
572575

573576
/*
574577
* Provide ability for vendor overrides of timeout values in case
575578
* of misreporting.
576579
*/
577580
if (chip->ops->update_timeouts != NULL)
578581
chip->timeout_adjusted =
579-
chip->ops->update_timeouts(chip, new_timeout);
582+
chip->ops->update_timeouts(chip, timeout_eff);
580583

581584
if (!chip->timeout_adjusted) {
582-
/* Don't overwrite default if value is 0 */
583-
if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
584-
int i;
585+
/* Restore default if chip reported 0 */
586+
int i;
585587

588+
for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
589+
if (timeout_eff[i])
590+
continue;
591+
592+
timeout_eff[i] = timeout_old[i];
593+
chip->timeout_adjusted = true;
594+
}
595+
596+
if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
586597
/* timeouts in msec rather usec */
587-
for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
588-
new_timeout[i] *= 1000;
598+
for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
599+
timeout_eff[i] *= 1000;
589600
chip->timeout_adjusted = true;
590601
}
591602
}
@@ -594,16 +605,16 @@ int tpm_get_timeouts(struct tpm_chip *chip)
594605
if (chip->timeout_adjusted) {
595606
dev_info(&chip->dev,
596607
HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
597-
old_timeout[0], new_timeout[0],
598-
old_timeout[1], new_timeout[1],
599-
old_timeout[2], new_timeout[2],
600-
old_timeout[3], new_timeout[3]);
608+
timeout_chip[0], timeout_eff[0],
609+
timeout_chip[1], timeout_eff[1],
610+
timeout_chip[2], timeout_eff[2],
611+
timeout_chip[3], timeout_eff[3]);
601612
}
602613

603-
chip->timeout_a = usecs_to_jiffies(new_timeout[0]);
604-
chip->timeout_b = usecs_to_jiffies(new_timeout[1]);
605-
chip->timeout_c = usecs_to_jiffies(new_timeout[2]);
606-
chip->timeout_d = usecs_to_jiffies(new_timeout[3]);
614+
chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
615+
chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
616+
chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
617+
chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
607618

608619
rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
609620
"attempting to determine the durations");

drivers/char/tpm/tpm_tis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
159159
irq = tpm_info->irq;
160160

161161
if (itpm)
162-
phy->priv.flags |= TPM_TIS_ITPM_POSSIBLE;
162+
phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
163163

164164
return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
165165
acpi_dev_handle);

drivers/char/tpm/tpm_tis_core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
264264
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
265265
int rc, status, burstcnt;
266266
size_t count = 0;
267-
bool itpm = priv->flags & TPM_TIS_ITPM_POSSIBLE;
267+
bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND;
268268

269269
if (request_locality(chip, 0) < 0)
270270
return -EBUSY;
@@ -740,15 +740,15 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
740740
(chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
741741
vendor >> 16, rid);
742742

743-
if (!(priv->flags & TPM_TIS_ITPM_POSSIBLE)) {
743+
if (!(priv->flags & TPM_TIS_ITPM_WORKAROUND)) {
744744
probe = probe_itpm(chip);
745745
if (probe < 0) {
746746
rc = -ENODEV;
747747
goto out_err;
748748
}
749749

750750
if (!!probe)
751-
priv->flags |= TPM_TIS_ITPM_POSSIBLE;
751+
priv->flags |= TPM_TIS_ITPM_WORKAROUND;
752752
}
753753

754754
/* Figure out the capabilities */

drivers/char/tpm/tpm_tis_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ enum tis_defaults {
8080
#define TPM_RID(l) (0x0F04 | ((l) << 12))
8181

8282
enum tpm_tis_flags {
83-
TPM_TIS_ITPM_POSSIBLE = BIT(0),
83+
TPM_TIS_ITPM_WORKAROUND = BIT(0),
8484
};
8585

8686
struct tpm_tis_data {

0 commit comments

Comments
 (0)