Encapsulate power gating and locality functionality to tpm_chip_start() and tpm_chip_stop() in order to clean up the branching mess in tpm_transmit(). Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> Reviewed-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> --- drivers/char/tpm/tpm-chip.c | 110 +++++++++++++++++++++++++++++++ drivers/char/tpm/tpm-interface.c | 86 +----------------------- drivers/char/tpm/tpm.h | 2 + 3 files changed, 115 insertions(+), 83 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 157505b0f755..65f1561eba81 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -37,6 +37,116 @@ struct class *tpm_class; struct class *tpmrm_class; dev_t tpm_devt; +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; + + rc = chip->ops->request_locality(chip, 0); + if (rc < 0) + return rc; + + chip->locality = rc; + return 0; +} + +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; + + rc = chip->ops->relinquish_locality(chip, chip->locality); + if (rc) + dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); + + 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); +} + +/** + * tpm_chip_start() - power on the TPM + * @chip: a TPM chip to use + * @flags: TPM transmit flags + * + * Return: + * * The response length - OK + * * -errno - A system error + */ +int tpm_chip_start(struct tpm_chip *chip, unsigned int flags) +{ + int ret; + + if (chip->ops->clk_enable) + chip->ops->clk_enable(chip, true); + + if (chip->locality == -1) { + ret = tpm_request_locality(chip, flags); + if (ret) { + chip->ops->clk_enable(chip, false); + return ret; + } + } + + ret = tpm_cmd_ready(chip, flags); + if (ret) { + tpm_relinquish_locality(chip, flags); + if (chip->ops->clk_enable) + chip->ops->clk_enable(chip, false); + return ret; + } + + return 0; +} + +/** + * tpm_chip_stop() - power off the TPM + * @chip: a TPM chip to use + * @flags: TPM transmit flags + * + * Return: + * * The response length - OK + * * -errno - A system error + */ +void tpm_chip_stop(struct tpm_chip *chip, unsigned int flags) +{ + tpm_go_idle(chip, flags); + tpm_relinquish_locality(chip, flags); + if (chip->ops->clk_enable) + chip->ops->clk_enable(chip, false); +} + + /** * tpm_try_get_ops() - Get a ref to the tpm_chip * @chip: Chip to ref diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 5865b9671d20..2c79284ffd4e 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -62,64 +62,6 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); -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; - - rc = chip->ops->request_locality(chip, 0); - if (rc < 0) - return rc; - - chip->locality = rc; - - return 0; -} - -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; - - rc = chip->ops->relinquish_locality(chip, chip->locality); - if (rc) - dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); - - 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, u8 *buf, size_t bufsiz, unsigned int flags) { @@ -212,7 +154,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz, /* space for header and handles */ u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; unsigned int delay_msec = TPM2_DURATION_SHORT; - bool has_locality = false; u32 rc = 0; ssize_t ret; const size_t save_size = min(sizeof(save), bufsiz); @@ -227,32 +168,11 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz, memcpy(save, buf, save_size); for (;;) { - if (chip->ops->clk_enable != NULL) - chip->ops->clk_enable(chip, true); - - if (chip->locality == -1) { - ret = tpm_request_locality(chip, flags); - if (ret) - goto out_locality; - has_locality = true; - } - - ret = tpm_cmd_ready(chip, flags); + ret = tpm_chip_start(chip, flags); if (ret) - goto out_locality; - + return ret; ret = tpm_try_transmit(chip, buf, bufsiz, flags); - - /* This may fail but do not override ret. */ - tpm_go_idle(chip, flags); - -out_locality: - if (has_locality) - tpm_relinquish_locality(chip, flags); - - if (chip->ops->clk_enable != NULL) - chip->ops->clk_enable(chip, false); - + tpm_chip_stop(chip, flags); if (ret < 0) break; rc = be32_to_cpu(header->return_code); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index c7c06de651a0..c42a75710b70 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -523,6 +523,8 @@ static inline void tpm_msleep(unsigned int delay_msec) delay_msec * 1000); }; +int tpm_chip_start(struct tpm_chip *chip, unsigned int flags); +void tpm_chip_stop(struct tpm_chip *chip, unsigned int flags); struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); __must_check int tpm_try_get_ops(struct tpm_chip *chip); void tpm_put_ops(struct tpm_chip *chip); -- 2.19.1