[PATCH] tpm: Cache TPM2 start method
From: Jarkko Sakkinen
Date: Fri Nov 13 2026 - 13:18:42 EST
Both tpm_tis and tpm_crb have duplicate code for retrieving the start
method from TPM2 ACPI table. Eagerly cache the start method already at chip
creation. The cached chip->start_method can then be used by the leaf
drivers; or ignored depending on the requirements.
Signed-off-by: Jarkko Sakkinen <jarkko@xxxxxxxxxx>
---
drivers/char/tpm/tpm-chip.c | 36 +++++++++++++++++++++++++++++-------
include/linux/tpm.h | 1 +
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 0be5dbfaa72e..540dd366effc 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -256,18 +256,24 @@ int tpm_class_shutdown(struct device *dev)
}
/**
- * tpm_chip_alloc() - allocate a new struct tpm_chip instance
- * @pdev: device to which the chip is associated
- * At this point pdev mst be initialized, but does not have to
- * be registered
- * @ops: struct tpm_class_ops instance
+ * tpm_chip_alloc() - Allocate a new struct tpm_chip instance
+ * @pdev: device to which the chip is associated At this point pdev mst be
+ * initialized, but does not have to be registered
+ * @ops: struct tpm_class_ops for the chip.
+ *
+ * Allocates a new struct tpm_chip instance, and assigns a free device number
+ * for it. Must be paired with put_device(&chip->dev).
*
- * Allocates a new struct tpm_chip instance and assigns a free
- * device number for it. Must be paired with put_device(&chip->dev).
+ * When ACPI is enabled, additionally tries to eagerly cache the start method
+ * from TPM2 ACPI table for the devices that need know it.
*/
struct tpm_chip *tpm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops)
{
+#ifdef CONFIG_ACPI
+ struct acpi_table_tpm2 *tbl;
+ acpi_status status;
+#endif
struct tpm_chip *chip;
int rc;
@@ -275,6 +281,22 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
if (chip == NULL)
return ERR_PTR(-ENOMEM);
+#ifdef CONFIG_ACPI
+ chip->start_method = ACPI_TPM2_NOT_ALLOWED;
+ if (!acpi_disabled) {
+ status = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
+ if (!ACPI_FAILURE(status) || tbl->header.length >= sizeof(*tbl)) {
+ chip->start_method = tbl->start_method;
+ dev_info(pdev, "TPM2 ACPI table is available");
+ } else {
+ dev_info(pdev, "TPM2 ACPI table is not available");
+ }
+
+ if (!ACPI_FAILURE(status))
+ acpi_put_table((struct acpi_table_header *)tbl);
+ }
+#endif
+
mutex_init(&chip->tpm_mutex);
init_rwsem(&chip->ops_sem);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 0db277af45c3..f6cc91615469 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -149,6 +149,7 @@ struct tpm_chip {
struct tpm_bank_info allocated_banks[TPM2_MAX_PCR_BANKS];
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
+ u32 start_method;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
--
2.47.3
--AD514XYzylQTXZCK--