Skip to content

Commit

Permalink
tpm_tis: verify locality released before returning from release_locality
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jerry Snitselaar authored and Jarkko Sakkinen committed May 14, 2018
1 parent 1fbad30 commit 33bafe9
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion drivers/char/tpm/tpm_tis_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 33bafe9

Please sign in to comment.