aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/tpm.c31
-rw-r--r--drivers/char/tpm/tpm.h3
2 files changed, 30 insertions, 4 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 0d2e82f95577..7c3b3dcbfbc8 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1337,7 +1337,7 @@ int tpm_pm_suspend(struct device *dev)
1337{ 1337{
1338 struct tpm_chip *chip = dev_get_drvdata(dev); 1338 struct tpm_chip *chip = dev_get_drvdata(dev);
1339 struct tpm_cmd_t cmd; 1339 struct tpm_cmd_t cmd;
1340 int rc; 1340 int rc, try;
1341 1341
1342 u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; 1342 u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
1343 1343
@@ -1355,9 +1355,32 @@ int tpm_pm_suspend(struct device *dev)
1355 } 1355 }
1356 1356
1357 /* now do the actual savestate */ 1357 /* now do the actual savestate */
1358 cmd.header.in = savestate_header; 1358 for (try = 0; try < TPM_RETRY; try++) {
1359 rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 1359 cmd.header.in = savestate_header;
1360 "sending savestate before suspend"); 1360 rc = transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL);
1361
1362 /*
1363 * If the TPM indicates that it is too busy to respond to
1364 * this command then retry before giving up. It can take
1365 * several seconds for this TPM to be ready.
1366 *
1367 * This can happen if the TPM has already been sent the
1368 * SaveState command before the driver has loaded. TCG 1.2
1369 * specification states that any communication after SaveState
1370 * may cause the TPM to invalidate previously saved state.
1371 */
1372 if (rc != TPM_WARN_RETRY)
1373 break;
1374 msleep(TPM_TIMEOUT_RETRY);
1375 }
1376
1377 if (rc)
1378 dev_err(chip->dev,
1379 "Error (%d) sending savestate before suspend\n", rc);
1380 else if (try > 0)
1381 dev_warn(chip->dev, "TPM savestate took %dms\n",
1382 try * TPM_TIMEOUT_RETRY);
1383
1361 return rc; 1384 return rc;
1362} 1385}
1363EXPORT_SYMBOL_GPL(tpm_pm_suspend); 1386EXPORT_SYMBOL_GPL(tpm_pm_suspend);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 81b52015f669..0770d1d79366 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -32,10 +32,12 @@ enum tpm_const {
32 TPM_MINOR = 224, /* officially assigned */ 32 TPM_MINOR = 224, /* officially assigned */
33 TPM_BUFSIZE = 4096, 33 TPM_BUFSIZE = 4096,
34 TPM_NUM_DEVICES = 256, 34 TPM_NUM_DEVICES = 256,
35 TPM_RETRY = 50, /* 5 seconds */
35}; 36};
36 37
37enum tpm_timeout { 38enum tpm_timeout {
38 TPM_TIMEOUT = 5, /* msecs */ 39 TPM_TIMEOUT = 5, /* msecs */
40 TPM_TIMEOUT_RETRY = 100 /* msecs */
39}; 41};
40 42
41/* TPM addresses */ 43/* TPM addresses */
@@ -44,6 +46,7 @@ enum tpm_addr {
44 TPM_ADDR = 0x4E, 46 TPM_ADDR = 0x4E,
45}; 47};
46 48
49#define TPM_WARN_RETRY 0x800
47#define TPM_WARN_DOING_SELFTEST 0x802 50#define TPM_WARN_DOING_SELFTEST 0x802
48#define TPM_ERR_DEACTIVATED 0x6 51#define TPM_ERR_DEACTIVATED 0x6
49#define TPM_ERR_DISABLED 0x7 52#define TPM_ERR_DISABLED 0x7