diff options
Diffstat (limited to 'drivers/char/tpm/tpm-interface.c')
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e32f6e85dc6d..1a803b0cf980 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -29,7 +29,6 @@ #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> -#include <linux/pm_runtime.h> #include <linux/tpm_eventlog.h> #include "tpm.h" @@ -369,10 +368,13 @@ err_len: return -EINVAL; } -static int tpm_request_locality(struct tpm_chip *chip) +static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_NESTED) + return 0; + if (!chip->ops->request_locality) return 0; @@ -385,10 +387,13 @@ static int tpm_request_locality(struct tpm_chip *chip) return 0; } -static void tpm_relinquish_locality(struct tpm_chip *chip) +static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_NESTED) + return; + if (!chip->ops->relinquish_locality) return; @@ -399,6 +404,28 @@ static void tpm_relinquish_locality(struct tpm_chip *chip) chip->locality = -1; } +static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_NESTED) + return 0; + + if (!chip->ops->cmd_ready) + return 0; + + return chip->ops->cmd_ready(chip); +} + +static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_NESTED) + return 0; + + if (!chip->ops->go_idle) + return 0; + + return chip->ops->go_idle(chip); +} + static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, @@ -423,7 +450,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | TSS2_RESMGR_TPM_RC_LAYER); - return bufsiz; + return sizeof(*header); } if (bufsiz > TPM_BUFSIZE) @@ -439,24 +466,24 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, return -E2BIG; } - if (!(flags & TPM_TRANSMIT_UNLOCKED)) + if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) mutex_lock(&chip->tpm_mutex); - if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, true); /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; - if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { - rc = tpm_request_locality(chip); + if (need_locality) { + rc = tpm_request_locality(chip, flags); if (rc < 0) goto out_no_locality; } - if (chip->dev.parent) - pm_runtime_get_sync(chip->dev.parent); + rc = tpm_cmd_ready(chip, flags); + if (rc) + goto out; rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) @@ -516,19 +543,22 @@ out_recv: } rc = tpm2_commit_space(chip, space, ordinal, buf, &len); + if (rc) + dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc); out: - if (chip->dev.parent) - pm_runtime_put_sync(chip->dev.parent); + rc = tpm_go_idle(chip, flags); + if (rc) + goto out; if (need_locality) - tpm_relinquish_locality(chip); + tpm_relinquish_locality(chip, flags); out_no_locality: if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); - if (!(flags & TPM_TRANSMIT_UNLOCKED)) + if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) mutex_unlock(&chip->tpm_mutex); return rc ? rc : len; } @@ -930,7 +960,7 @@ int tpm_is_tpm2(struct tpm_chip *chip) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -954,7 +984,7 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; if (chip->flags & TPM_CHIP_FLAG_TPM2) @@ -1013,7 +1043,7 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) u32 count = 0; int i; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1142,7 +1172,7 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1262,7 +1292,7 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) return -EINVAL; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1324,7 +1354,7 @@ int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) return -ENODEV; @@ -1352,7 +1382,7 @@ int tpm_unseal_trusted(struct tpm_chip *chip, { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) return -ENODEV; |