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:
Родитель
1fbad30286
Коммит
33bafe9082
|
@ -143,13 +143,58 @@ static bool check_locality(struct tpm_chip *chip, int l)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче