Commit 2c97f6f2 authored by Peter Huewe's avatar Peter Huewe Committed by Jarkko Sakkinen

char/tpm: Check return code of wait_for_tpm_stat

In some weird cases it might be possible that the TPM does not set
STS.VALID within the given timeout time (or ever) but sets STS.EXPECT
(STS=0x0C) In this case the driver gets stuck in the while loop of
tpm_tis_send_data and loops endlessly.

Checking the return value of wait_for_tpm_stat fixes this and the driver
bails out correctly.  While at it fixing all other users since if the
TPM does not manage to set STS.VALID within the reasonable timeframe
something is definitely wrong and the driver should react correctly.
Signed-off-by: default avatarPeter Huewe <peterhuewe@gmx.de>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
parent e74f2f76
...@@ -180,11 +180,13 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -180,11 +180,13 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
int size = 0, burstcnt, rc; int size = 0, burstcnt, rc;
while (size < count && while (size < count) {
wait_for_tpm_stat(chip, rc = wait_for_tpm_stat(chip,
TPM_STS_DATA_AVAIL | TPM_STS_VALID, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
chip->timeout_c, chip->timeout_c,
&priv->read_queue, true) == 0) { &priv->read_queue, true);
if (rc < 0)
return rc;
burstcnt = min_t(int, get_burstcount(chip), count - size); burstcnt = min_t(int, get_burstcount(chip), count - size);
rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality), rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality),
...@@ -229,8 +231,11 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -229,8 +231,11 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
goto out; goto out;
} }
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
&priv->int_queue, false); &priv->int_queue, false) < 0) {
size = -ETIME;
goto out;
}
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(&chip->dev, "Error left over data\n"); dev_err(&chip->dev, "Error left over data\n");
...@@ -279,8 +284,11 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -279,8 +284,11 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
count += burstcnt; count += burstcnt;
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
&priv->int_queue, false); &priv->int_queue, false) < 0) {
rc = -ETIME;
goto out_err;
}
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO; rc = -EIO;
...@@ -293,8 +301,11 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -293,8 +301,11 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
if (rc < 0) if (rc < 0)
goto out_err; goto out_err;
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
&priv->int_queue, false); &priv->int_queue, false) < 0) {
rc = -ETIME;
goto out_err;
}
status = tpm_tis_status(chip); status = tpm_tis_status(chip);
if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) {
rc = -EIO; rc = -EIO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment