diff options
author | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2017-03-24 10:45:49 +0100 |
---|---|---|
committer | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2017-04-03 21:46:02 +0200 |
commit | 877c57d0d0cac2c8fc661f708d8ee3fa7aa8d28b (patch) | |
tree | 36fcb0bf566df51a40ce092141394426800e02d0 /drivers/char/tpm/tpm_crb.c | |
parent | tpm: make check_locality return bool (diff) | |
download | linux-877c57d0d0cac2c8fc661f708d8ee3fa7aa8d28b.tar.xz linux-877c57d0d0cac2c8fc661f708d8ee3fa7aa8d28b.zip |
tpm_crb: request and relinquish locality 0
This commit adds support for requesting and relinquishing locality 0 in
tpm_crb for the course of command transmission.
In order to achieve this, two new callbacks are added to struct
tpm_class_ops:
- request_locality
- relinquish_locality
With CRB interface you first set either requestAccess or relinquish bit
from TPM_LOC_CTRL_x register and then wait for locAssigned and
tpmRegValidSts bits to be set in the TPM_LOC_STATE_x register.
The reason why were are doing this is to make sure that the driver
will work properly with Intel TXT that uses locality 2. There's no
explicit guarantee that it would relinquish this locality. In more
general sense this commit enables tpm_crb to be a well behaving
citizen in a multi locality environment.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Tested-by: Jerry Snitselaar <jsnitsel@redhat.com>
Diffstat (limited to 'drivers/char/tpm/tpm_crb.c')
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 9f3160912152..d91e47dc2d79 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -34,6 +34,16 @@ enum crb_defaults { CRB_ACPI_START_INDEX = 1, }; +enum crb_loc_ctrl { + CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0), + CRB_LOC_CTRL_RELINQUISH = BIT(1), +}; + +enum crb_loc_state { + CRB_LOC_STATE_LOC_ASSIGNED = BIT(1), + CRB_LOC_STATE_TPM_REG_VALID_STS = BIT(7), +}; + enum crb_ctrl_req { CRB_CTRL_REQ_CMD_READY = BIT(0), CRB_CTRL_REQ_GO_IDLE = BIT(1), @@ -172,6 +182,35 @@ static int __maybe_unused crb_cmd_ready(struct device *dev, return 0; } +static int crb_request_locality(struct tpm_chip *chip, int loc) +{ + struct crb_priv *priv = dev_get_drvdata(&chip->dev); + u32 value = CRB_LOC_STATE_LOC_ASSIGNED | + CRB_LOC_STATE_TPM_REG_VALID_STS; + + if (!priv->regs_h) + return 0; + + iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, + TPM2_TIMEOUT_C)) { + dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); + return -ETIME; + } + + return 0; +} + +static void crb_relinquish_locality(struct tpm_chip *chip, int loc) +{ + struct crb_priv *priv = dev_get_drvdata(&chip->dev); + + if (!priv->regs_h) + return; + + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); +} + static u8 crb_status(struct tpm_chip *chip) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); @@ -278,6 +317,8 @@ static const struct tpm_class_ops tpm_crb = { .send = crb_send, .cancel = crb_cancel, .req_canceled = crb_req_canceled, + .request_locality = crb_request_locality, + .relinquish_locality = crb_relinquish_locality, .req_complete_mask = CRB_DRV_STS_COMPLETE, .req_complete_val = CRB_DRV_STS_COMPLETE, }; |