aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2012-11-21 16:15:54 -0500
committerKent Yoder <key@linux.vnet.ibm.com>2013-02-05 10:38:24 -0500
commit4643826a3da17767494b85c956c73c138c96a7ea (patch)
treefff1c50e77544b0c9ee9e9573867eb2a3e05bd47 /drivers/char
parent1fbc5e95356a4600fab3a04a82dc8bb49591aedd (diff)
TPM: Work around buggy TPMs that block during continue self test
We've been testing an alternative TPM for our embedded products and found random kernel boot failures due to time outs after the continue self test command. This was happening randomly, and has been *very* hard to track down, but it looks like with this chip there is some kind of race with the tpm_tis_status() check of TPM_STS_COMMAND_READY. If things get there 'too fast' then it sees the chip is ready, or tpm_tis_ready() works. Otherwise it takes somewhere over 400ms before the chip will return TPM_STS_COMMAND_READY. Adding some delay after tpm_continue_selftest() makes things reliably hit the failure path, otherwise it is a crapshot. The spec says it should be returning TPM_WARN_DOING_SELFTEST, not holding off on ready.. Boot log during this event looks like this: tpm_tis 70030000.tpm_tis: 1.2 TPM (device-id 0x3204, rev-id 64) tpm_tis 70030000.tpm_tis: Issuing TPM_STARTUP tpm_tis 70030000.tpm_tis: tpm_transmit: tpm_send: error -62 tpm_tis 70030000.tpm_tis: [Hardware Error]: TPM command timed out during continue self test tpm_tis 70030000.tpm_tis: tpm_transmit: tpm_send: error -62 tpm_tis 70030000.tpm_tis: [Hardware Error]: TPM command timed out during continue self test tpm_tis 70030000.tpm_tis: tpm_transmit: tpm_send: error -62 tpm_tis 70030000.tpm_tis: [Hardware Error]: TPM command timed out during continue self test tpm_tis 70030000.tpm_tis: tpm_transmit: tpm_send: error -62 tpm_tis 70030000.tpm_tis: [Hardware Error]: TPM command timed out during continue self test The other TPM vendor we use doesn't show this wonky behaviour: tpm_tis 70030000.tpm_tis: 1.2 TPM (device-id 0xFE, rev-id 70) Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 023dfbaffe73..e38054b33bb4 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -843,7 +843,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
843{ 843{
844 int rc; 844 int rc;
845 unsigned int loops; 845 unsigned int loops;
846 unsigned int delay_msec = 1000; 846 unsigned int delay_msec = 100;
847 unsigned long duration; 847 unsigned long duration;
848 struct tpm_cmd_t cmd; 848 struct tpm_cmd_t cmd;
849 849
@@ -864,6 +864,14 @@ int tpm_do_selftest(struct tpm_chip *chip)
864 cmd.header.in = pcrread_header; 864 cmd.header.in = pcrread_header;
865 cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); 865 cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
866 rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); 866 rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
867 /* Some buggy TPMs will not respond to tpm_tis_ready() for
868 * around 300ms while the self test is ongoing, keep trying
869 * until the self test duration expires. */
870 if (rc == -ETIME) {
871 dev_info(chip->dev, HW_ERR "TPM command timed out during continue self test");
872 msleep(delay_msec);
873 continue;
874 }
867 875
868 if (rc < TPM_HEADER_SIZE) 876 if (rc < TPM_HEADER_SIZE)
869 return -EFAULT; 877 return -EFAULT;