Message ID | b46b8748-ec13-6f22-5168-228101d121d9@maciej.szmigiero.name |
---|---|
State | New |
Headers | show |
On Wed, May 03, 2017 at 12:34:08AM +0200, Maciej S. Szmigiero wrote: > 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. > > This is a backport for 4.9 kernel version of the original commit, with > renaming of "TPM_TIS_ITPM_POSSIBLE" flag removed since it was only a > cosmetic change and not a part of the real bug fix. > > Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> > Cc: <stable@vger.kernel.org> # 4.9.x Thanks for doing this and sorry for messing things up, not one, but *two* times. Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> /Jarkko > --- > drivers/char/tpm/tpm-interface.c | 53 ++++++++++++++++++++++++---------------- > 1 file changed, 32 insertions(+), 21 deletions(-) > > diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c > index 3a9149cf0110..d0ac2d56520f 100644 > --- a/drivers/char/tpm/tpm-interface.c > +++ b/drivers/char/tpm/tpm-interface.c > @@ -489,8 +489,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) > int tpm_get_timeouts(struct tpm_chip *chip) > { > struct tpm_cmd_t tpm_cmd; > - unsigned long new_timeout[4]; > - unsigned long old_timeout[4]; > + unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; > struct duration_t *duration_cap; > ssize_t rc; > > @@ -542,11 +541,15 @@ int tpm_get_timeouts(struct tpm_chip *chip) > != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) > return -EINVAL; > > - old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a); > - old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); > - old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); > - old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.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(tpm_cmd.params.getcap_out.cap.timeout.a); > + timeout_chip[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); > + timeout_chip[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); > + timeout_chip[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d); > + memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); > > /* > * Provide ability for vendor overrides of timeout values in case > @@ -554,16 +557,24 @@ int tpm_get_timeouts(struct tpm_chip *chip) > */ > 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; > } > } > @@ -572,16 +583,16 @@ int tpm_get_timeouts(struct tpm_chip *chip) > 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]); > > duration: > tpm_cmd.header.in = tpm_getcap_header; ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 3a9149cf0110..d0ac2d56520f 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -489,8 +489,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; - unsigned long new_timeout[4]; - unsigned long old_timeout[4]; + unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4]; struct duration_t *duration_cap; ssize_t rc; @@ -542,11 +541,15 @@ int tpm_get_timeouts(struct tpm_chip *chip) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) return -EINVAL; - old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a); - old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); - old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); - old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.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(tpm_cmd.params.getcap_out.cap.timeout.a); + timeout_chip[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b); + timeout_chip[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c); + timeout_chip[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d); + memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff)); /* * Provide ability for vendor overrides of timeout values in case @@ -554,16 +557,24 @@ int tpm_get_timeouts(struct tpm_chip *chip) */ 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; } } @@ -572,16 +583,16 @@ int tpm_get_timeouts(struct tpm_chip *chip) 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]); duration: tpm_cmd.header.in = tpm_getcap_header;
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. This is a backport for 4.9 kernel version of the original commit, with renaming of "TPM_TIS_ITPM_POSSIBLE" flag removed since it was only a cosmetic change and not a part of the real bug fix. Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Cc: <stable@vger.kernel.org> # 4.9.x --- drivers/char/tpm/tpm-interface.c | 53 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot