mutex_unlock(&chip->buffer_mutex);
}
-static void needs_resume(struct tpm_chip *chip)
+static void set_needs_resume(struct tpm_chip *chip)
{
mutex_lock(&chip->resume_mutex);
chip->resume_time = jiffies;
return rc;
}
-/**
- * tpm_continue_selftest -- run TPM's selftest
- * @chip: TPM chip to use
- *
- * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
- * a TPM error code.
- */
-int tpm_continue_selftest(struct tpm_chip *chip)
+void tpm_continue_selftest_nocheck(struct tpm_chip *chip)
{
- int rc;
struct tpm_cmd_t cmd;
-
cmd.header.in = continue_selftest_header;
- rc = tpm_transmit(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE);
- return rc;
+ tpm_transmit(chip, (u8 *) &cmd, CONTINUE_SELFTEST_RESULT_SIZE);
}
-EXPORT_SYMBOL_GPL(tpm_continue_selftest);
/* The maximum time in milliseconds that the TPM self test will take to
* complete. TODO(semenzato): 1s should be plenty for all TPMs, but how can we
*/
#define TPM_SELF_TEST_DURATION_MSEC 1000
+/* We don't want to wait for the self test to complete at resume, because it
+ * impacts the resume speed. TPM commands are infrequent so the wait is
+ * usually not needed and is wasteful. Instead, before we send any command, we
+ * check that enough time has elapsed from the resume so that we are
+ * comfortable that the self test has completed. If not, we wait. Unlike at
+ * boot, here we don't check the return code of continue_self_test, so we can
+ * use a code path which avoids recursion. Furthermore, this only works when
+ * ContinueSelfTest is blocking, that is it returns only after the self test
+ * has completed, which is the case for the Infineon TPM.
+ */
static void resume_if_needed(struct tpm_chip *chip)
{
mutex_lock(&chip->resume_mutex);
if (jiffies - chip->resume_time <
msecs_to_jiffies(TPM_SELF_TEST_DURATION_MSEC)) {
dev_info(chip->dev, "waiting for TPM self test");
- tpm_continue_selftest(chip);
+ tpm_continue_selftest_nocheck(chip);
}
chip->needs_resume = 0;
dev_info(chip->dev, "TPM delayed resume completed");
return err;
}
+/**
+ * tpm_continue_selftest -- run TPM's selftest
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+int tpm_continue_selftest(struct tpm_chip *chip)
+{
+ int rc;
+ struct tpm_cmd_t cmd;
+
+ cmd.header.in = continue_selftest_header;
+ rc = transmit_cmd(chip, (const u8 *) &cmd,
+ CONTINUE_SELFTEST_RESULT_SIZE, "continue selftest");
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
/*
* Returns max number of jiffies to wait
*/
if (chip == NULL)
return -ENODEV;
- needs_resume(chip);
+ set_needs_resume(chip);
return 0;
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);