diff options
Diffstat (limited to 'drivers/char/tpm')
-rw-r--r-- | drivers/char/tpm/Kconfig | 12 | ||||
-rw-r--r-- | drivers/char/tpm/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 127 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-sessions.c | 104 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_loongson.c | 84 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_ppi.c | 89 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 4 |
9 files changed, 228 insertions, 197 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index dddd702b2454..8a8f692b6088 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -29,10 +29,11 @@ if TCG_TPM config TCG_TPM2_HMAC bool "Use HMAC and encrypted transactions on the TPM bus" - default X86_64 + default n select CRYPTO_ECDH select CRYPTO_LIB_AESCFB select CRYPTO_LIB_SHA256 + select CRYPTO_LIB_UTILS help Setting this causes us to deploy a scheme which uses request and response HMACs in addition to encryption for @@ -189,6 +190,15 @@ config TCG_IBMVTPM will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_ibmvtpm. +config TCG_LOONGSON + tristate "Loongson TPM Interface" + depends on MFD_LOONGSON_SE + help + If you want to make Loongson TPM support available, say Yes and + it will be accessible from within Linux. To compile this + driver as a module, choose M here; the module will be called + tpm_loongson. + config TCG_XEN tristate "XEN TPM Interface" depends on TCG_TPM && XEN diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 9de1b3ea34a9..5b5cdc0d32e4 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -46,3 +46,4 @@ obj-$(CONFIG_TCG_ARM_CRB_FFA) += tpm_crb_ffa.o obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o obj-$(CONFIG_TCG_SVSM) += tpm_svsm.o +obj-$(CONFIG_TCG_LOONGSON) += tpm_loongson.o diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index b71725827743..c9f173001d0e 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(suspend_pcr, unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) { if (chip->flags & TPM_CHIP_FLAG_TPM2) - return tpm2_calc_ordinal_duration(chip, ordinal); + return tpm2_calc_ordinal_duration(ordinal); else return tpm1_calc_ordinal_duration(chip, ordinal); } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7bb87fa5f7a1..2726bd38e5ac 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -299,7 +299,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip); int tpm2_auto_startup(struct tpm_chip *chip); void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); -unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +unsigned long tpm2_calc_ordinal_duration(u32 ordinal); int tpm2_probe(struct tpm_chip *chip); int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip); int tpm2_find_cc(struct tpm_chip *chip, u32 cc); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 524d802ede26..7d77f6fbc152 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -28,120 +28,57 @@ static struct tpm2_hash tpm2_hash_map[] = { int tpm2_get_timeouts(struct tpm_chip *chip) { - /* Fixed timeouts for TPM2 */ chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); - - /* PTP spec timeouts */ - chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT); - chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM); - chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG); - - /* Key creation commands long timeouts */ - chip->duration[TPM_LONG_LONG] = - msecs_to_jiffies(TPM2_DURATION_LONG_LONG); - chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS; - return 0; } -/** - * tpm2_ordinal_duration_index() - returns an index to the chip duration table - * @ordinal: TPM command ordinal. - * - * The function returns an index to the chip duration table - * (enum tpm_duration), that describes the maximum amount of - * time the chip could take to return the result for a particular ordinal. - * - * The values of the MEDIUM, and LONG durations are taken - * from the PC Client Profile (PTP) specification (750, 2000 msec) - * - * LONG_LONG is for commands that generates keys which empirically takes - * a longer time on some systems. - * - * Return: - * * TPM_MEDIUM - * * TPM_LONG - * * TPM_LONG_LONG - * * TPM_UNDEFINED +/* + * Contains the maximum durations in milliseconds for TPM2 commands. */ -static u8 tpm2_ordinal_duration_index(u32 ordinal) -{ - switch (ordinal) { - /* Startup */ - case TPM2_CC_STARTUP: /* 144 */ - return TPM_MEDIUM; - - case TPM2_CC_SELF_TEST: /* 143 */ - return TPM_LONG; - - case TPM2_CC_GET_RANDOM: /* 17B */ - return TPM_LONG; - - case TPM2_CC_SEQUENCE_UPDATE: /* 15C */ - return TPM_MEDIUM; - case TPM2_CC_SEQUENCE_COMPLETE: /* 13E */ - return TPM_MEDIUM; - case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */ - return TPM_MEDIUM; - case TPM2_CC_HASH_SEQUENCE_START: /* 186 */ - return TPM_MEDIUM; - - case TPM2_CC_VERIFY_SIGNATURE: /* 177 */ - return TPM_LONG_LONG; - - case TPM2_CC_PCR_EXTEND: /* 182 */ - return TPM_MEDIUM; - - case TPM2_CC_HIERARCHY_CONTROL: /* 121 */ - return TPM_LONG; - case TPM2_CC_HIERARCHY_CHANGE_AUTH: /* 129 */ - return TPM_LONG; - - case TPM2_CC_GET_CAPABILITY: /* 17A */ - return TPM_MEDIUM; - - case TPM2_CC_NV_READ: /* 14E */ - return TPM_LONG; - - case TPM2_CC_CREATE_PRIMARY: /* 131 */ - return TPM_LONG_LONG; - case TPM2_CC_CREATE: /* 153 */ - return TPM_LONG_LONG; - case TPM2_CC_CREATE_LOADED: /* 191 */ - return TPM_LONG_LONG; - - default: - return TPM_UNDEFINED; - } -} +static const struct { + unsigned long ordinal; + unsigned long duration; +} tpm2_ordinal_duration_map[] = { + {TPM2_CC_STARTUP, 750}, + {TPM2_CC_SELF_TEST, 3000}, + {TPM2_CC_GET_RANDOM, 2000}, + {TPM2_CC_SEQUENCE_UPDATE, 750}, + {TPM2_CC_SEQUENCE_COMPLETE, 750}, + {TPM2_CC_EVENT_SEQUENCE_COMPLETE, 750}, + {TPM2_CC_HASH_SEQUENCE_START, 750}, + {TPM2_CC_VERIFY_SIGNATURE, 30000}, + {TPM2_CC_PCR_EXTEND, 750}, + {TPM2_CC_HIERARCHY_CONTROL, 2000}, + {TPM2_CC_HIERARCHY_CHANGE_AUTH, 2000}, + {TPM2_CC_GET_CAPABILITY, 750}, + {TPM2_CC_NV_READ, 2000}, + {TPM2_CC_CREATE_PRIMARY, 30000}, + {TPM2_CC_CREATE, 30000}, + {TPM2_CC_CREATE_LOADED, 30000}, +}; /** - * tpm2_calc_ordinal_duration() - calculate the maximum command duration - * @chip: TPM chip to use. + * tpm2_calc_ordinal_duration() - Calculate the maximum command duration * @ordinal: TPM command ordinal. * - * The function returns the maximum amount of time the chip could take - * to return the result for a particular ordinal in jiffies. - * - * Return: A maximal duration time for an ordinal in jiffies. + * Returns the maximum amount of time the chip is expected by kernel to + * take in jiffies. */ -unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) +unsigned long tpm2_calc_ordinal_duration(u32 ordinal) { - unsigned int index; + int i; - index = tpm2_ordinal_duration_index(ordinal); + for (i = 0; i < ARRAY_SIZE(tpm2_ordinal_duration_map); i++) + if (ordinal == tpm2_ordinal_duration_map[i].ordinal) + return msecs_to_jiffies(tpm2_ordinal_duration_map[i].duration); - if (index != TPM_UNDEFINED) - return chip->duration[index]; - else - return msecs_to_jiffies(TPM2_DURATION_DEFAULT); + return msecs_to_jiffies(TPM2_DURATION_DEFAULT); } - struct tpm2_pcr_read_out { __be32 update_cnt; __be32 pcr_selects_cnt; diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index bdb119453dfb..6d03c224e6b2 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -69,8 +69,8 @@ #include <linux/unaligned.h> #include <crypto/kpp.h> #include <crypto/ecdh.h> -#include <crypto/hash.h> -#include <crypto/hmac.h> +#include <crypto/sha2.h> +#include <crypto/utils.h> /* maximum number of names the TPM must remember for authorization */ #define AUTH_MAX_NAMES 3 @@ -385,51 +385,6 @@ static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy, u32 *handle, u8 *name); /* - * It turns out the crypto hmac(sha256) is hard for us to consume - * because it assumes a fixed key and the TPM seems to change the key - * on every operation, so we weld the hmac init and final functions in - * here to give it the same usage characteristics as a regular hash - */ -static void tpm2_hmac_init(struct sha256_ctx *sctx, u8 *key, u32 key_len) -{ - u8 pad[SHA256_BLOCK_SIZE]; - int i; - - sha256_init(sctx); - for (i = 0; i < sizeof(pad); i++) { - if (i < key_len) - pad[i] = key[i]; - else - pad[i] = 0; - pad[i] ^= HMAC_IPAD_VALUE; - } - sha256_update(sctx, pad, sizeof(pad)); -} - -static void tpm2_hmac_final(struct sha256_ctx *sctx, u8 *key, u32 key_len, - u8 *out) -{ - u8 pad[SHA256_BLOCK_SIZE]; - int i; - - for (i = 0; i < sizeof(pad); i++) { - if (i < key_len) - pad[i] = key[i]; - else - pad[i] = 0; - pad[i] ^= HMAC_OPAD_VALUE; - } - - /* collect the final hash; use out as temporary storage */ - sha256_final(sctx, out); - - sha256_init(sctx); - sha256_update(sctx, pad, sizeof(pad)); - sha256_update(sctx, out, SHA256_DIGEST_SIZE); - sha256_final(sctx, out); -} - -/* * assume hash sha256 and nonces u, v of size SHA256_DIGEST_SIZE but * otherwise standard tpm2_KDFa. Note output is in bytes not bits. */ @@ -440,16 +395,16 @@ static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u, const __be32 bits = cpu_to_be32(bytes * 8); while (bytes > 0) { - struct sha256_ctx sctx; + struct hmac_sha256_ctx hctx; __be32 c = cpu_to_be32(counter); - tpm2_hmac_init(&sctx, key, key_len); - sha256_update(&sctx, (u8 *)&c, sizeof(c)); - sha256_update(&sctx, label, strlen(label)+1); - sha256_update(&sctx, u, SHA256_DIGEST_SIZE); - sha256_update(&sctx, v, SHA256_DIGEST_SIZE); - sha256_update(&sctx, (u8 *)&bits, sizeof(bits)); - tpm2_hmac_final(&sctx, key, key_len, out); + hmac_sha256_init_usingrawkey(&hctx, key, key_len); + hmac_sha256_update(&hctx, (u8 *)&c, sizeof(c)); + hmac_sha256_update(&hctx, label, strlen(label) + 1); + hmac_sha256_update(&hctx, u, SHA256_DIGEST_SIZE); + hmac_sha256_update(&hctx, v, SHA256_DIGEST_SIZE); + hmac_sha256_update(&hctx, (u8 *)&bits, sizeof(bits)); + hmac_sha256_final(&hctx, out); bytes -= SHA256_DIGEST_SIZE; counter++; @@ -593,6 +548,7 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf) u32 attrs; u8 cphash[SHA256_DIGEST_SIZE]; struct sha256_ctx sctx; + struct hmac_sha256_ctx hctx; if (!auth) return; @@ -704,14 +660,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf) sha256_final(&sctx, cphash); /* now calculate the hmac */ - tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key) - + auth->passphrase_len); - sha256_update(&sctx, cphash, sizeof(cphash)); - sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce)); - sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); - sha256_update(&sctx, &auth->attrs, 1); - tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key) - + auth->passphrase_len, hmac); + hmac_sha256_init_usingrawkey(&hctx, auth->session_key, + sizeof(auth->session_key) + + auth->passphrase_len); + hmac_sha256_update(&hctx, cphash, sizeof(cphash)); + hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce)); + hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); + hmac_sha256_update(&hctx, &auth->attrs, 1); + hmac_sha256_final(&hctx, hmac); } EXPORT_SYMBOL(tpm_buf_fill_hmac_session); @@ -751,6 +707,7 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, u8 rphash[SHA256_DIGEST_SIZE]; u32 attrs, cc; struct sha256_ctx sctx; + struct hmac_sha256_ctx hctx; u16 tag = be16_to_cpu(head->tag); int parm_len, len, i, handles; @@ -820,21 +777,20 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, sha256_final(&sctx, rphash); /* now calculate the hmac */ - tpm2_hmac_init(&sctx, auth->session_key, sizeof(auth->session_key) - + auth->passphrase_len); - sha256_update(&sctx, rphash, sizeof(rphash)); - sha256_update(&sctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); - sha256_update(&sctx, auth->our_nonce, sizeof(auth->our_nonce)); - sha256_update(&sctx, &auth->attrs, 1); + hmac_sha256_init_usingrawkey(&hctx, auth->session_key, + sizeof(auth->session_key) + + auth->passphrase_len); + hmac_sha256_update(&hctx, rphash, sizeof(rphash)); + hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); + hmac_sha256_update(&hctx, auth->our_nonce, sizeof(auth->our_nonce)); + hmac_sha256_update(&hctx, &auth->attrs, 1); /* we're done with the rphash, so put our idea of the hmac there */ - tpm2_hmac_final(&sctx, auth->session_key, sizeof(auth->session_key) - + auth->passphrase_len, rphash); - if (memcmp(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE) == 0) { - rc = 0; - } else { + hmac_sha256_final(&hctx, rphash); + if (crypto_memneq(rphash, &buf->data[offset_s], SHA256_DIGEST_SIZE)) { dev_err(&chip->dev, "TPM: HMAC check failed\n"); goto out; } + rc = 0; /* now do response decryption */ if (auth->attrs & TPM2_SA_ENCRYPT) { diff --git a/drivers/char/tpm/tpm_loongson.c b/drivers/char/tpm/tpm_loongson.c new file mode 100644 index 000000000000..9e50250763d1 --- /dev/null +++ b/drivers/char/tpm/tpm_loongson.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Loongson Technology Corporation Limited. */ + +#include <linux/device.h> +#include <linux/mfd/loongson-se.h> +#include <linux/platform_device.h> +#include <linux/wait.h> + +#include "tpm.h" + +struct tpm_loongson_cmd { + u32 cmd_id; + u32 data_off; + u32 data_len; + u32 pad[5]; +}; + +static int tpm_loongson_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct loongson_se_engine *tpm_engine = dev_get_drvdata(&chip->dev); + struct tpm_loongson_cmd *cmd_ret = tpm_engine->command_ret; + + if (cmd_ret->data_len > count) + return -EIO; + + memcpy(buf, tpm_engine->data_buffer, cmd_ret->data_len); + + return cmd_ret->data_len; +} + +static int tpm_loongson_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, size_t count) +{ + struct loongson_se_engine *tpm_engine = dev_get_drvdata(&chip->dev); + struct tpm_loongson_cmd *cmd = tpm_engine->command; + + if (count > tpm_engine->buffer_size) + return -E2BIG; + + cmd->data_len = count; + memcpy(tpm_engine->data_buffer, buf, count); + + return loongson_se_send_engine_cmd(tpm_engine); +} + +static const struct tpm_class_ops tpm_loongson_ops = { + .flags = TPM_OPS_AUTO_STARTUP, + .recv = tpm_loongson_recv, + .send = tpm_loongson_send, +}; + +static int tpm_loongson_probe(struct platform_device *pdev) +{ + struct loongson_se_engine *tpm_engine; + struct device *dev = &pdev->dev; + struct tpm_loongson_cmd *cmd; + struct tpm_chip *chip; + + tpm_engine = loongson_se_init_engine(dev->parent, SE_ENGINE_TPM); + if (!tpm_engine) + return -ENODEV; + cmd = tpm_engine->command; + cmd->cmd_id = SE_CMD_TPM; + cmd->data_off = tpm_engine->buffer_off; + + chip = tpmm_chip_alloc(dev, &tpm_loongson_ops); + if (IS_ERR(chip)) + return PTR_ERR(chip); + chip->flags = TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_IRQ; + dev_set_drvdata(&chip->dev, tpm_engine); + + return tpm_chip_register(chip); +} + +static struct platform_driver tpm_loongson = { + .probe = tpm_loongson_probe, + .driver = { + .name = "tpm_loongson", + }, +}; +module_platform_driver(tpm_loongson); + +MODULE_ALIAS("platform:tpm_loongson"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Loongson TPM driver"); diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index d53fce1c9d6f..c9793a3d986d 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -33,6 +33,20 @@ static const guid_t tpm_ppi_guid = GUID_INIT(0x3DDDFAA6, 0x361B, 0x4EB4, 0xA4, 0x24, 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53); +static const char * const tpm_ppi_info[] = { + "Not implemented", + "BIOS only", + "Blocked for OS by system firmware", + "User required", + "User not required", +}; + +/* A spinlock to protect access to the cache from concurrent reads */ +static DEFINE_MUTEX(tpm_ppi_lock); + +static u32 ppi_operations_cache[PPI_VS_REQ_END + 1]; +static bool ppi_cache_populated; + static bool tpm_ppi_req_has_parameter(u64 req) { return req == 23; @@ -277,8 +291,7 @@ cleanup: return status; } -static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, - u32 end) +static ssize_t cache_ppi_operations(acpi_handle dev_handle, char *buf) { int i; u32 ret; @@ -286,34 +299,22 @@ static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, union acpi_object *obj, tmp; union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp); - static char *info[] = { - "Not implemented", - "BIOS only", - "Blocked for OS by BIOS", - "User required", - "User not required", - }; - if (!acpi_check_dsm(dev_handle, &tpm_ppi_guid, TPM_PPI_REVISION_ID_1, 1 << TPM_PPI_FN_GETOPR)) return -EPERM; tmp.integer.type = ACPI_TYPE_INTEGER; - for (i = start; i <= end; i++) { + for (i = 0; i <= PPI_VS_REQ_END; i++) { tmp.integer.value = i; obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv, TPM_PPI_REVISION_ID_1); - if (!obj) { + if (!obj) return -ENOMEM; - } else { - ret = obj->integer.value; - ACPI_FREE(obj); - } - if (ret > 0 && ret < ARRAY_SIZE(info)) - len += sysfs_emit_at(buf, len, "%d %d: %s\n", - i, ret, info[ret]); + ret = obj->integer.value; + ppi_operations_cache[i] = ret; + ACPI_FREE(obj); } return len; @@ -324,9 +325,30 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, char *buf) { struct tpm_chip *chip = to_tpm_chip(dev); + ssize_t len = 0; + u32 ret; + int i; + + mutex_lock(&tpm_ppi_lock); + if (!ppi_cache_populated) { + len = cache_ppi_operations(chip->acpi_dev_handle, buf); + if (len < 0) { + mutex_unlock(&tpm_ppi_lock); + return len; + } - return show_ppi_operations(chip->acpi_dev_handle, buf, 0, - PPI_TPM_REQ_MAX); + ppi_cache_populated = true; + } + + for (i = 0; i <= PPI_TPM_REQ_MAX; i++) { + ret = ppi_operations_cache[i]; + if (ret >= 0 && ret < ARRAY_SIZE(tpm_ppi_info)) + len += sysfs_emit_at(buf, len, "%d %d: %s\n", + i, ret, tpm_ppi_info[ret]); + } + mutex_unlock(&tpm_ppi_lock); + + return len; } static ssize_t tpm_show_ppi_vs_operations(struct device *dev, @@ -334,9 +356,30 @@ static ssize_t tpm_show_ppi_vs_operations(struct device *dev, char *buf) { struct tpm_chip *chip = to_tpm_chip(dev); + ssize_t len = 0; + u32 ret; + int i; - return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START, - PPI_VS_REQ_END); + mutex_lock(&tpm_ppi_lock); + if (!ppi_cache_populated) { + len = cache_ppi_operations(chip->acpi_dev_handle, buf); + if (len < 0) { + mutex_unlock(&tpm_ppi_lock); + return len; + } + + ppi_cache_populated = true; + } + + for (i = PPI_VS_REQ_START; i <= PPI_VS_REQ_END; i++) { + ret = ppi_operations_cache[i]; + if (ret >= 0 && ret < ARRAY_SIZE(tpm_ppi_info)) + len += sysfs_emit_at(buf, len, "%d %d: %s\n", + i, ret, tpm_ppi_info[ret]); + } + mutex_unlock(&tpm_ppi_lock); + + return len; } static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 4b12c4b9da8b..8954a8660ffc 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -978,8 +978,8 @@ restore_irqs: * will call disable_irq which undoes all of the above. */ if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { - tpm_tis_write8(priv, original_int_vec, - TPM_INT_VECTOR(priv->locality)); + tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), + original_int_vec); rc = -1; } |