mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-07-01 23:53:16 -04:00
tpm_tis: verify locality released before returning from release_locality
For certain tpm chips releasing locality can take long enough that a subsequent call to request_locality will see the locality as being active when the access register is read in check_locality. So check that the locality has been released before returning from release_locality. Cc: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Cc: Peter Huewe <peterhuewe@gmx.de> Cc: Jason Gunthorpe <jgg@ziepe.ca> Reported-by: Laurent Bigonville <bigon@debian.org> Signed-off-by: Jerry Snitselaar <jsnitsel@redhat.com> Tested-by: Laurent Bigonville <bigon@debian.org> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
This commit is contained in:
parent
1fbad30286
commit
33bafe9082
1 changed files with 46 additions and 1 deletions
|
@ -143,13 +143,58 @@ static bool check_locality(struct tpm_chip *chip, int l)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool locality_inactive(struct tpm_chip *chip, int l)
|
||||||
|
{
|
||||||
|
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||||
|
int rc;
|
||||||
|
u8 access;
|
||||||
|
|
||||||
|
rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
|
||||||
|
if (rc < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
|
||||||
|
== TPM_ACCESS_VALID)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int release_locality(struct tpm_chip *chip, int l)
|
static int release_locality(struct tpm_chip *chip, int l)
|
||||||
{
|
{
|
||||||
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
|
||||||
|
unsigned long stop, timeout;
|
||||||
|
long rc;
|
||||||
|
|
||||||
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
|
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
|
||||||
|
|
||||||
return 0;
|
stop = jiffies + chip->timeout_a;
|
||||||
|
|
||||||
|
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
|
||||||
|
again:
|
||||||
|
timeout = stop - jiffies;
|
||||||
|
if ((long)timeout <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rc = wait_event_interruptible_timeout(priv->int_queue,
|
||||||
|
(locality_inactive(chip, l)),
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
if (rc > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (rc == -ERESTARTSYS && freezing(current)) {
|
||||||
|
clear_thread_flag(TIF_SIGPENDING);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
if (locality_inactive(chip, l))
|
||||||
|
return 0;
|
||||||
|
tpm_msleep(TPM_TIMEOUT);
|
||||||
|
} while (time_before(jiffies, stop));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int request_locality(struct tpm_chip *chip, int l)
|
static int request_locality(struct tpm_chip *chip, int l)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue