tpm: introduce tpm_chip_start() and tpm_chip_stop()
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@linux.intel.com> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Stefan Berger <stefanb@linux.ibm.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com> Tested-by: Alexander Steffen <Alexander.Steffen@infineon.com>
This commit is contained in:
parent
2f257402ee
commit
719b7d81f2
@ -37,6 +37,117 @@ struct class *tpm_class;
|
|||||||
struct class *tpmrm_class;
|
struct class *tpmrm_class;
|
||||||
dev_t tpm_devt;
|
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;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tpm_chip_start);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tpm_chip_stop);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tpm_try_get_ops() - Get a ref to the tpm_chip
|
* tpm_try_get_ops() - Get a ref to the tpm_chip
|
||||||
* @chip: Chip to ref
|
* @chip: Chip to ref
|
||||||
|
@ -62,64 +62,6 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
|
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, void *buf, size_t bufsiz,
|
static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
@ -221,7 +163,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
|
|||||||
/* space for header and handles */
|
/* space for header and handles */
|
||||||
u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)];
|
u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)];
|
||||||
unsigned int delay_msec = TPM2_DURATION_SHORT;
|
unsigned int delay_msec = TPM2_DURATION_SHORT;
|
||||||
bool has_locality = false;
|
|
||||||
u32 rc = 0;
|
u32 rc = 0;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
const size_t save_size = min(sizeof(save), bufsiz);
|
const size_t save_size = min(sizeof(save), bufsiz);
|
||||||
@ -236,32 +177,13 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
|
|||||||
memcpy(save, buf, save_size);
|
memcpy(save, buf, save_size);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (chip->ops->clk_enable != NULL)
|
ret = tpm_chip_start(chip, flags);
|
||||||
chip->ops->clk_enable(chip, true);
|
|
||||||
|
|
||||||
if (chip->locality == -1) {
|
|
||||||
ret = tpm_request_locality(chip, flags);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_locality;
|
return ret;
|
||||||
has_locality = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = tpm_cmd_ready(chip, flags);
|
|
||||||
if (ret)
|
|
||||||
goto out_locality;
|
|
||||||
|
|
||||||
ret = tpm_try_transmit(chip, buf, bufsiz, flags);
|
ret = tpm_try_transmit(chip, buf, bufsiz, flags);
|
||||||
|
|
||||||
/* This may fail but do not override ret. */
|
tpm_chip_stop(chip, flags);
|
||||||
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);
|
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
rc = be32_to_cpu(header->return_code);
|
rc = be32_to_cpu(header->return_code);
|
||||||
|
@ -523,6 +523,8 @@ static inline void tpm_msleep(unsigned int delay_msec)
|
|||||||
delay_msec * 1000);
|
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);
|
struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
|
||||||
__must_check int tpm_try_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);
|
void tpm_put_ops(struct tpm_chip *chip);
|
||||||
|
Loading…
Reference in New Issue
Block a user