All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Recovery from data transfer errors for tpm_tis
@ 2023-06-05 17:59 Alexander Steffen
  2023-06-05 17:59 ` [PATCH v2 1/4] tpm_tis: Explicitly check for error code Alexander Steffen
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Alexander Steffen @ 2023-06-05 17:59 UTC (permalink / raw)
  To: jarkko, linux-integrity, linux-kernel; +Cc: Alexander Steffen

Data transfer to/from hardware TPM devices is not always fully reliable.
The existing driver code contains already many checks to detect
corrupted data (e.g. unexpected register values, CRC failures, etc.) and
usually returns EIO in such cases. This series adds automatic retries to
the command/response transmission in tpm_tis_send/tpm_tis_recv, so that
occasional communication errors do not cause the command execution to
fail and the perceived reliability of the TPM device is increased.

v2:
* Remove Change-Ids accidentially left in commit messages

Alexander Steffen (4):
  tpm_tis: Explicitly check for error code
  tpm_tis: Move CRC check to generic send routine
  tpm_tis: Use responseRetry to recover from data transfer errors
  tpm_tis: Resend command to recover from data transfer errors

 drivers/char/tpm/tpm_tis_core.c | 73 +++++++++++++++++++++++++--------
 drivers/char/tpm/tpm_tis_core.h |  1 +
 2 files changed, 56 insertions(+), 18 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/4] tpm_tis: Explicitly check for error code
  2023-06-05 17:59 [PATCH 0/4] Recovery from data transfer errors for tpm_tis Alexander Steffen
@ 2023-06-05 17:59 ` Alexander Steffen
  2023-06-06 21:09   ` Jarkko Sakkinen
  2023-06-05 17:59 ` [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine Alexander Steffen
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Alexander Steffen @ 2023-06-05 17:59 UTC (permalink / raw)
  To: jarkko, linux-integrity, linux-kernel; +Cc: Alexander Steffen

recv_data either returns the number of received bytes, or a negative value
representing an error code. Adding the return value directly to the total
number of received bytes therefore looks a little weird, since it might add
a negative error code to a sum of bytes.

The following check for size < expected usually makes the function return
ETIME in that case, so it does not cause too many problems in practice. But
to make the code look cleaner and because the caller might still be
interested in the original error code, explicitly check for the presence of
an error code and pass that through.

Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
---
 drivers/char/tpm/tpm_tis_core.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 558144fa707a..aaaa136044ae 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -363,8 +363,13 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 		goto out;
 	}
 
-	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
-			  expected - TPM_HEADER_SIZE);
+	rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
+		       expected - TPM_HEADER_SIZE);
+	if (rc < 0) {
+		size = rc;
+		goto out;
+	}
+	size += rc;
 	if (size < expected) {
 		dev_err(&chip->dev, "Unable to read remainder of result\n");
 		size = -ETIME;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine
  2023-06-05 17:59 [PATCH 0/4] Recovery from data transfer errors for tpm_tis Alexander Steffen
  2023-06-05 17:59 ` [PATCH v2 1/4] tpm_tis: Explicitly check for error code Alexander Steffen
@ 2023-06-05 17:59 ` Alexander Steffen
  2023-06-06 21:10   ` Jarkko Sakkinen
  2023-06-05 17:59 ` [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors Alexander Steffen
  2023-06-05 17:59 ` [PATCH v2 4/4] tpm_tis: Resend command " Alexander Steffen
  3 siblings, 1 reply; 13+ messages in thread
From: Alexander Steffen @ 2023-06-05 17:59 UTC (permalink / raw)
  To: jarkko, linux-integrity, linux-kernel; +Cc: Alexander Steffen

The CRC functionality is initialized before tpm_tis_core, so it can be used
on all code paths within the module. Therefore, move the CRC check to the
generic send routine, that also contains all other checks for successful
command transmission, so that all those checks are in one place.

Also, this ensures that tpm_tis_ready is called when a CRC failure is
detected, to clear the invalid data from the TPM, which did not happen
previously.

Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
---
 drivers/char/tpm/tpm_tis_core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index aaaa136044ae..5ddaf24518be 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -466,6 +466,12 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
 		goto out_err;
 	}
 
+	rc = tpm_tis_verify_crc(priv, len, buf);
+	if (rc < 0) {
+		dev_err(&chip->dev, "CRC mismatch for command.\n");
+		goto out_err;
+	}
+
 	return 0;
 
 out_err:
@@ -510,12 +516,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
 	if (rc < 0)
 		return rc;
 
-	rc = tpm_tis_verify_crc(priv, len, buf);
-	if (rc < 0) {
-		dev_err(&chip->dev, "CRC mismatch for command.\n");
-		return rc;
-	}
-
 	/* go and do it */
 	rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
 	if (rc < 0)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-05 17:59 [PATCH 0/4] Recovery from data transfer errors for tpm_tis Alexander Steffen
  2023-06-05 17:59 ` [PATCH v2 1/4] tpm_tis: Explicitly check for error code Alexander Steffen
  2023-06-05 17:59 ` [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine Alexander Steffen
@ 2023-06-05 17:59 ` Alexander Steffen
  2023-06-06 21:17   ` Jarkko Sakkinen
  2023-06-06 21:18   ` Jarkko Sakkinen
  2023-06-05 17:59 ` [PATCH v2 4/4] tpm_tis: Resend command " Alexander Steffen
  3 siblings, 2 replies; 13+ messages in thread
From: Alexander Steffen @ 2023-06-05 17:59 UTC (permalink / raw)
  To: jarkko, linux-integrity, linux-kernel; +Cc: Alexander Steffen

TPM responses may become damaged during transmission, for example due to
bit flips on the wire. Instead of aborting when detecting such issues, the
responseRetry functionality can be used to make the TPM retransmit its
response and receive it again without errors.

Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
---
 drivers/char/tpm/tpm_tis_core.c | 40 ++++++++++++++++++++++++++-------
 drivers/char/tpm/tpm_tis_core.h |  1 +
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 5ddaf24518be..a08768e55803 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -345,11 +345,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 	u32 expected;
 	int rc;
 
-	if (count < TPM_HEADER_SIZE) {
-		size = -EIO;
-		goto out;
-	}
-
 	size = recv_data(chip, buf, TPM_HEADER_SIZE);
 	/* read first 10 bytes, including tag, paramsize, and result */
 	if (size < TPM_HEADER_SIZE) {
@@ -382,7 +377,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 		goto out;
 	}
 	status = tpm_tis_status(chip);
-	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+	if (status & TPM_STS_DATA_AVAIL) {
 		dev_err(&chip->dev, "Error left over data\n");
 		size = -EIO;
 		goto out;
@@ -396,10 +391,39 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 	}
 
 out:
-	tpm_tis_ready(chip);
 	return size;
 }
 
+static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+	unsigned int try;
+	int rc = 0;
+
+	if (count < TPM_HEADER_SIZE) {
+		rc = -EIO;
+		goto out;
+	}
+
+	for (try = 0; try < TPM_RETRY; try++) {
+		rc = tpm_tis_recv(chip, buf, count);
+
+		if (rc == -EIO) {
+			/* Data transfer errors, indicated by EIO, can be
+			 * recovered by rereading the response.
+			 */
+			tpm_tis_write8(priv, TPM_STS(priv->locality),
+				       TPM_STS_RESPONSE_RETRY);
+		} else {
+			break;
+		}
+	}
+
+out:
+	tpm_tis_ready(chip);
+	return rc;
+}
+
 /*
  * If interrupts are used (signaled by an irq set in the vendor structure)
  * tpm.c can skip polling for the data to be available as the interrupt is
@@ -986,7 +1010,7 @@ static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)
 static const struct tpm_class_ops tpm_tis = {
 	.flags = TPM_OPS_AUTO_STARTUP,
 	.status = tpm_tis_status,
-	.recv = tpm_tis_recv,
+	.recv = tpm_tis_recv_with_retries,
 	.send = tpm_tis_send,
 	.cancel = tpm_tis_ready,
 	.update_timeouts = tpm_tis_update_timeouts,
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index e978f457fd4d..8458cd4a84ec 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -34,6 +34,7 @@ enum tis_status {
 	TPM_STS_GO = 0x20,
 	TPM_STS_DATA_AVAIL = 0x10,
 	TPM_STS_DATA_EXPECT = 0x08,
+	TPM_STS_RESPONSE_RETRY = 0x02,
 	TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/4] tpm_tis: Resend command to recover from data transfer errors
  2023-06-05 17:59 [PATCH 0/4] Recovery from data transfer errors for tpm_tis Alexander Steffen
                   ` (2 preceding siblings ...)
  2023-06-05 17:59 ` [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors Alexander Steffen
@ 2023-06-05 17:59 ` Alexander Steffen
  2023-06-06 21:19   ` Jarkko Sakkinen
  3 siblings, 1 reply; 13+ messages in thread
From: Alexander Steffen @ 2023-06-05 17:59 UTC (permalink / raw)
  To: jarkko, linux-integrity, linux-kernel; +Cc: Alexander Steffen

Similar to the transmission of TPM responses, also the transmission of TPM
commands may become corrupted. Instead of aborting when detecting such
issues, try resending the command again.

Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
---
 drivers/char/tpm/tpm_tis_core.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index a08768e55803..47073cc79b51 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -535,10 +535,18 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
 	int rc;
 	u32 ordinal;
 	unsigned long dur;
+	unsigned int try;
 
-	rc = tpm_tis_send_data(chip, buf, len);
-	if (rc < 0)
-		return rc;
+	for (try = 0; try < TPM_RETRY; try++) {
+		rc = tpm_tis_send_data(chip, buf, len);
+		if (rc >= 0) {
+			/* Data transfer done successfully */
+			break;
+		} else if (rc != -EIO) {
+			/* Data transfer failed, not recoverable */
+			return rc;
+		}
+	}
 
 	/* go and do it */
 	rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 1/4] tpm_tis: Explicitly check for error code
  2023-06-05 17:59 ` [PATCH v2 1/4] tpm_tis: Explicitly check for error code Alexander Steffen
@ 2023-06-06 21:09   ` Jarkko Sakkinen
  0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-06 21:09 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
> recv_data either returns the number of received bytes, or a negative value
> representing an error code. Adding the return value directly to the total
> number of received bytes therefore looks a little weird, since it might add
> a negative error code to a sum of bytes.
>
> The following check for size < expected usually makes the function return
> ETIME in that case, so it does not cause too many problems in practice. But
> to make the code look cleaner and because the caller might still be
> interested in the original error code, explicitly check for the presence of
> an error code and pass that through.
>

Cc: stable@vger.kernel.org
Fixes: cb5354253af2 ("[PATCH] tpm: spacing cleanups 2")

> Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
> ---
>  drivers/char/tpm/tpm_tis_core.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index 558144fa707a..aaaa136044ae 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -363,8 +363,13 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  		goto out;
>  	}
>  
> -	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
> -			  expected - TPM_HEADER_SIZE);
> +	rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
> +		       expected - TPM_HEADER_SIZE);
> +	if (rc < 0) {
> +		size = rc;
> +		goto out;
> +	}
> +	size += rc;
>  	if (size < expected) {
>  		dev_err(&chip->dev, "Unable to read remainder of result\n");
>  		size = -ETIME;
> -- 
> 2.34.1

BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine
  2023-06-05 17:59 ` [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine Alexander Steffen
@ 2023-06-06 21:10   ` Jarkko Sakkinen
  0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-06 21:10 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
> The CRC functionality is initialized before tpm_tis_core, so it can be used
> on all code paths within the module. Therefore, move the CRC check to the
> generic send routine, that also contains all other checks for successful
> command transmission, so that all those checks are in one place.
>
> Also, this ensures that tpm_tis_ready is called when a CRC failure is
> detected, to clear the invalid data from the TPM, which did not happen
> previously.
>
> Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
> ---
>  drivers/char/tpm/tpm_tis_core.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index aaaa136044ae..5ddaf24518be 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -466,6 +466,12 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
>  		goto out_err;
>  	}
>  
> +	rc = tpm_tis_verify_crc(priv, len, buf);
> +	if (rc < 0) {
> +		dev_err(&chip->dev, "CRC mismatch for command.\n");
> +		goto out_err;
> +	}
> +
>  	return 0;
>  
>  out_err:
> @@ -510,12 +516,6 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>  	if (rc < 0)
>  		return rc;
>  
> -	rc = tpm_tis_verify_crc(priv, len, buf);
> -	if (rc < 0) {
> -		dev_err(&chip->dev, "CRC mismatch for command.\n");
> -		return rc;
> -	}
> -
>  	/* go and do it */
>  	rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
>  	if (rc < 0)
> -- 
> 2.34.1

Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>

BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-05 17:59 ` [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors Alexander Steffen
@ 2023-06-06 21:17   ` Jarkko Sakkinen
  2023-06-07 17:14     ` Alexander Steffen
  2023-06-06 21:18   ` Jarkko Sakkinen
  1 sibling, 1 reply; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-06 21:17 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
> TPM responses may become damaged during transmission, for example due to
> bit flips on the wire. Instead of aborting when detecting such issues, the
> responseRetry functionality can be used to make the TPM retransmit its
> response and receive it again without errors.
>
> Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
> ---
>  drivers/char/tpm/tpm_tis_core.c | 40 ++++++++++++++++++++++++++-------
>  drivers/char/tpm/tpm_tis_core.h |  1 +
>  2 files changed, 33 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index 5ddaf24518be..a08768e55803 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -345,11 +345,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  	u32 expected;
>  	int rc;
>  
> -	if (count < TPM_HEADER_SIZE) {
> -		size = -EIO;
> -		goto out;
> -	}
> -
>  	size = recv_data(chip, buf, TPM_HEADER_SIZE);
>  	/* read first 10 bytes, including tag, paramsize, and result */
>  	if (size < TPM_HEADER_SIZE) {
> @@ -382,7 +377,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  		goto out;
>  	}
>  	status = tpm_tis_status(chip);
> -	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
> +	if (status & TPM_STS_DATA_AVAIL) {

Please remove (no-op).

>  		dev_err(&chip->dev, "Error left over data\n");
>  		size = -EIO;
>  		goto out;
> @@ -396,10 +391,39 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  	}
>  
>  out:
> -	tpm_tis_ready(chip);
>  	return size;
>  }
>  
> +static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)

This *substitutes* the curent tpm_tis_recv(), right?

So it *is* tpm_tis_recv(), i.e. no renames thank you :-)

> +{
> +	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> +	unsigned int try;
> +	int rc = 0;
> +
> +	if (count < TPM_HEADER_SIZE) {
> +		rc = -EIO;
> +		goto out;
> +	}
> +
> +	for (try = 0; try < TPM_RETRY; try++) {
> +		rc = tpm_tis_recv(chip, buf, count);

I would rename single shot tpm_tis_recv() as tpm_tis_try_recv().

> +
> +		if (rc == -EIO) {
> +			/* Data transfer errors, indicated by EIO, can be
> +			 * recovered by rereading the response.
> +			 */
> +			tpm_tis_write8(priv, TPM_STS(priv->locality),
> +				       TPM_STS_RESPONSE_RETRY);
> +		} else {
> +			break;
> +		}

And if this should really be managed inside tpm_tis_try_recv(), and
then return zero (as the code block consumes the return value).

> +	}
> +
> +out:
> +	tpm_tis_ready(chip);

Empty line here (nit).

> +	return rc;
> +}
> +
>  /*
>   * If interrupts are used (signaled by an irq set in the vendor structure)
>   * tpm.c can skip polling for the data to be available as the interrupt is
> @@ -986,7 +1010,7 @@ static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)
>  static const struct tpm_class_ops tpm_tis = {
>  	.flags = TPM_OPS_AUTO_STARTUP,
>  	.status = tpm_tis_status,
> -	.recv = tpm_tis_recv,
> +	.recv = tpm_tis_recv_with_retries,
>  	.send = tpm_tis_send,
>  	.cancel = tpm_tis_ready,
>  	.update_timeouts = tpm_tis_update_timeouts,
> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
> index e978f457fd4d..8458cd4a84ec 100644
> --- a/drivers/char/tpm/tpm_tis_core.h
> +++ b/drivers/char/tpm/tpm_tis_core.h
> @@ -34,6 +34,7 @@ enum tis_status {
>  	TPM_STS_GO = 0x20,
>  	TPM_STS_DATA_AVAIL = 0x10,
>  	TPM_STS_DATA_EXPECT = 0x08,
> +	TPM_STS_RESPONSE_RETRY = 0x02,
>  	TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */
>  };
>  
> -- 
> 2.34.1

BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-05 17:59 ` [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors Alexander Steffen
  2023-06-06 21:17   ` Jarkko Sakkinen
@ 2023-06-06 21:18   ` Jarkko Sakkinen
  1 sibling, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-06 21:18 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
> +static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> +	unsigned int try;
> +	int rc = 0;
> +
> +	if (count < TPM_HEADER_SIZE) {
> +		rc = -EIO;
> +		goto out;
> +	}

	if (count < TPM_HEADER_SIZE)
		return -EIO;

BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 4/4] tpm_tis: Resend command to recover from data transfer errors
  2023-06-05 17:59 ` [PATCH v2 4/4] tpm_tis: Resend command " Alexander Steffen
@ 2023-06-06 21:19   ` Jarkko Sakkinen
  0 siblings, 0 replies; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-06 21:19 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
> Similar to the transmission of TPM responses, also the transmission of TPM
> commands may become corrupted. Instead of aborting when detecting such
> issues, try resending the command again.
>
> Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
> ---
>  drivers/char/tpm/tpm_tis_core.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index a08768e55803..47073cc79b51 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -535,10 +535,18 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
>  	int rc;
>  	u32 ordinal;
>  	unsigned long dur;
> +	unsigned int try;
>  
> -	rc = tpm_tis_send_data(chip, buf, len);
> -	if (rc < 0)
> -		return rc;
> +	for (try = 0; try < TPM_RETRY; try++) {
> +		rc = tpm_tis_send_data(chip, buf, len);
> +		if (rc >= 0) {
> +			/* Data transfer done successfully */
> +			break;
> +		} else if (rc != -EIO) {
> +			/* Data transfer failed, not recoverable */
> +			return rc;
> +		}

Remove curly braces from the two statements above.

> +	}
>  
>  	/* go and do it */
>  	rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
> -- 
> 2.34.1


BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-06 21:17   ` Jarkko Sakkinen
@ 2023-06-07 17:14     ` Alexander Steffen
  2023-06-08 14:00       ` Jarkko Sakkinen
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Steffen @ 2023-06-07 17:14 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-integrity, linux-kernel

On 06.06.23 23:17, Jarkko Sakkinen wrote:
> On Mon Jun 5, 2023 at 8:59 PM EEST, Alexander Steffen wrote:
>> TPM responses may become damaged during transmission, for example due to
>> bit flips on the wire. Instead of aborting when detecting such issues, the
>> responseRetry functionality can be used to make the TPM retransmit its
>> response and receive it again without errors.
>>
>> Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
>> ---
>>   drivers/char/tpm/tpm_tis_core.c | 40 ++++++++++++++++++++++++++-------
>>   drivers/char/tpm/tpm_tis_core.h |  1 +
>>   2 files changed, 33 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
>> index 5ddaf24518be..a08768e55803 100644
>> --- a/drivers/char/tpm/tpm_tis_core.c
>> +++ b/drivers/char/tpm/tpm_tis_core.c
>> @@ -345,11 +345,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>>        u32 expected;
>>        int rc;
>>
>> -     if (count < TPM_HEADER_SIZE) {
>> -             size = -EIO;
>> -             goto out;
>> -     }
>> -
>>        size = recv_data(chip, buf, TPM_HEADER_SIZE);
>>        /* read first 10 bytes, including tag, paramsize, and result */
>>        if (size < TPM_HEADER_SIZE) {
>> @@ -382,7 +377,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>>                goto out;
>>        }
>>        status = tpm_tis_status(chip);
>> -     if (status & TPM_STS_DATA_AVAIL) {      /* retry? */
>> +     if (status & TPM_STS_DATA_AVAIL) {
> 
> Please remove (no-op).

You mean I shouldn't change the line and leave the comment in? To me it 
looked like a very brief TODO comment "should we retry here?", and since 
with this change it now actually does retry, I removed it.

>>                dev_err(&chip->dev, "Error left over data\n");
>>                size = -EIO;
>>                goto out;
>> @@ -396,10 +391,39 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>>        }
>>
>>   out:
>> -     tpm_tis_ready(chip);
>>        return size;
>>   }
>>
>> +static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)
> 
> This *substitutes* the curent tpm_tis_recv(), right?
> 
> So it *is* tpm_tis_recv(), i.e. no renames thank you :-)
> 
>> +{
>> +     struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>> +     unsigned int try;
>> +     int rc = 0;
>> +
>> +     if (count < TPM_HEADER_SIZE) {
>> +             rc = -EIO;
>> +             goto out;
>> +     }
>> +
>> +     for (try = 0; try < TPM_RETRY; try++) {
>> +             rc = tpm_tis_recv(chip, buf, count);
> 
> I would rename single shot tpm_tis_recv() as tpm_tis_try_recv().
> 
>> +
>> +             if (rc == -EIO) {
>> +                     /* Data transfer errors, indicated by EIO, can be
>> +                      * recovered by rereading the response.
>> +                      */
>> +                     tpm_tis_write8(priv, TPM_STS(priv->locality),
>> +                                    TPM_STS_RESPONSE_RETRY);
>> +             } else {
>> +                     break;
>> +             }
> 
> And if this should really be managed inside tpm_tis_try_recv(), and
> then return zero (as the code block consumes the return value).

What exactly should be done in tpm_tis_try_recv()? It could set 
TPM_STS_RESPONSE_RETRY, but then it would still need to return an error 
code, so that this loop knows whether to call it again or not.

>> +     }
>> +
>> +out:
>> +     tpm_tis_ready(chip);
> 
> Empty line here (nit).
> 
>> +     return rc;
>> +}
>> +
>>   /*
>>    * If interrupts are used (signaled by an irq set in the vendor structure)
>>    * tpm.c can skip polling for the data to be available as the interrupt is
>> @@ -986,7 +1010,7 @@ static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)
>>   static const struct tpm_class_ops tpm_tis = {
>>        .flags = TPM_OPS_AUTO_STARTUP,
>>        .status = tpm_tis_status,
>> -     .recv = tpm_tis_recv,
>> +     .recv = tpm_tis_recv_with_retries,
>>        .send = tpm_tis_send,
>>        .cancel = tpm_tis_ready,
>>        .update_timeouts = tpm_tis_update_timeouts,
>> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
>> index e978f457fd4d..8458cd4a84ec 100644
>> --- a/drivers/char/tpm/tpm_tis_core.h
>> +++ b/drivers/char/tpm/tpm_tis_core.h
>> @@ -34,6 +34,7 @@ enum tis_status {
>>        TPM_STS_GO = 0x20,
>>        TPM_STS_DATA_AVAIL = 0x10,
>>        TPM_STS_DATA_EXPECT = 0x08,
>> +     TPM_STS_RESPONSE_RETRY = 0x02,
>>        TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */
>>   };
>>
>> --
>> 2.34.1
> 
> BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-07 17:14     ` Alexander Steffen
@ 2023-06-08 14:00       ` Jarkko Sakkinen
  2023-06-13 17:37         ` Alexander Steffen
  0 siblings, 1 reply; 13+ messages in thread
From: Jarkko Sakkinen @ 2023-06-08 14:00 UTC (permalink / raw)
  To: Alexander Steffen, linux-integrity, linux-kernel

On Wed Jun 7, 2023 at 8:14 PM EEST, Alexander Steffen wrote:
> >> -     if (status & TPM_STS_DATA_AVAIL) {      /* retry? */
> >> +     if (status & TPM_STS_DATA_AVAIL) {
> > 
> > Please remove (no-op).
>
> You mean I shouldn't change the line and leave the comment in? To me it 
> looked like a very brief TODO comment "should we retry here?", and since 
> with this change it now actually does retry, I removed it.

Right, ok, point taken, you can keep it.

> >>                dev_err(&chip->dev, "Error left over data\n");
> >>                size = -EIO;
> >>                goto out;
> >> @@ -396,10 +391,39 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> >>        }
> >>
> >>   out:
> >> -     tpm_tis_ready(chip);
> >>        return size;
> >>   }
> >>
> >> +static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)
> > 
> > This *substitutes* the curent tpm_tis_recv(), right?
> > 
> > So it *is* tpm_tis_recv(), i.e. no renames thank you :-)
> > 
> >> +{
> >> +     struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
> >> +     unsigned int try;
> >> +     int rc = 0;
> >> +
> >> +     if (count < TPM_HEADER_SIZE) {
> >> +             rc = -EIO;
> >> +             goto out;
> >> +     }
> >> +
> >> +     for (try = 0; try < TPM_RETRY; try++) {
> >> +             rc = tpm_tis_recv(chip, buf, count);
> > 
> > I would rename single shot tpm_tis_recv() as tpm_tis_try_recv().
> > 
> >> +
> >> +             if (rc == -EIO) {
> >> +                     /* Data transfer errors, indicated by EIO, can be
> >> +                      * recovered by rereading the response.
> >> +                      */
> >> +                     tpm_tis_write8(priv, TPM_STS(priv->locality),
> >> +                                    TPM_STS_RESPONSE_RETRY);
> >> +             } else {
> >> +                     break;
> >> +             }
> > 
> > And if this should really be managed inside tpm_tis_try_recv(), and
> > then return zero (as the code block consumes the return value).
>
> What exactly should be done in tpm_tis_try_recv()? It could set 
> TPM_STS_RESPONSE_RETRY, but then it would still need to return an error 
> code, so that this loop knows whether to call it again or not.

So my thinking was to:

- Rename tpm_tis_recv() as tpm_tis_try_recv()
- Rename this new function as tpm_tis_recv().

BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors
  2023-06-08 14:00       ` Jarkko Sakkinen
@ 2023-06-13 17:37         ` Alexander Steffen
  0 siblings, 0 replies; 13+ messages in thread
From: Alexander Steffen @ 2023-06-13 17:37 UTC (permalink / raw)
  To: Jarkko Sakkinen, linux-integrity, linux-kernel

On 08.06.23 16:00, Jarkko Sakkinen wrote:
> On Wed Jun 7, 2023 at 8:14 PM EEST, Alexander Steffen wrote:
>>>> -     if (status & TPM_STS_DATA_AVAIL) {      /* retry? */
>>>> +     if (status & TPM_STS_DATA_AVAIL) {
>>>
>>> Please remove (no-op).
>>
>> You mean I shouldn't change the line and leave the comment in? To me it
>> looked like a very brief TODO comment "should we retry here?", and since
>> with this change it now actually does retry, I removed it.
> 
> Right, ok, point taken, you can keep it.
> 
>>>>                 dev_err(&chip->dev, "Error left over data\n");
>>>>                 size = -EIO;
>>>>                 goto out;
>>>> @@ -396,10 +391,39 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>>>>         }
>>>>
>>>>    out:
>>>> -     tpm_tis_ready(chip);
>>>>         return size;
>>>>    }
>>>>
>>>> +static int tpm_tis_recv_with_retries(struct tpm_chip *chip, u8 *buf, size_t count)
>>>
>>> This *substitutes* the curent tpm_tis_recv(), right?
>>>
>>> So it *is* tpm_tis_recv(), i.e. no renames thank you :-)
>>>
>>>> +{
>>>> +     struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
>>>> +     unsigned int try;
>>>> +     int rc = 0;
>>>> +
>>>> +     if (count < TPM_HEADER_SIZE) {
>>>> +             rc = -EIO;
>>>> +             goto out;
>>>> +     }
>>>> +
>>>> +     for (try = 0; try < TPM_RETRY; try++) {
>>>> +             rc = tpm_tis_recv(chip, buf, count);
>>>
>>> I would rename single shot tpm_tis_recv() as tpm_tis_try_recv().
>>>
>>>> +
>>>> +             if (rc == -EIO) {
>>>> +                     /* Data transfer errors, indicated by EIO, can be
>>>> +                      * recovered by rereading the response.
>>>> +                      */
>>>> +                     tpm_tis_write8(priv, TPM_STS(priv->locality),
>>>> +                                    TPM_STS_RESPONSE_RETRY);
>>>> +             } else {
>>>> +                     break;
>>>> +             }
>>>
>>> And if this should really be managed inside tpm_tis_try_recv(), and
>>> then return zero (as the code block consumes the return value).
>>
>> What exactly should be done in tpm_tis_try_recv()? It could set
>> TPM_STS_RESPONSE_RETRY, but then it would still need to return an error
>> code, so that this loop knows whether to call it again or not.
> 
> So my thinking was to:
> 
> - Rename tpm_tis_recv() as tpm_tis_try_recv()
> - Rename this new function as tpm_tis_recv().

Sounds good, thanks. Will be done in v3.

> BR, Jarkko

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-06-13 17:37 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-05 17:59 [PATCH 0/4] Recovery from data transfer errors for tpm_tis Alexander Steffen
2023-06-05 17:59 ` [PATCH v2 1/4] tpm_tis: Explicitly check for error code Alexander Steffen
2023-06-06 21:09   ` Jarkko Sakkinen
2023-06-05 17:59 ` [PATCH v2 2/4] tpm_tis: Move CRC check to generic send routine Alexander Steffen
2023-06-06 21:10   ` Jarkko Sakkinen
2023-06-05 17:59 ` [PATCH v2 3/4] tpm_tis: Use responseRetry to recover from data transfer errors Alexander Steffen
2023-06-06 21:17   ` Jarkko Sakkinen
2023-06-07 17:14     ` Alexander Steffen
2023-06-08 14:00       ` Jarkko Sakkinen
2023-06-13 17:37         ` Alexander Steffen
2023-06-06 21:18   ` Jarkko Sakkinen
2023-06-05 17:59 ` [PATCH v2 4/4] tpm_tis: Resend command " Alexander Steffen
2023-06-06 21:19   ` Jarkko Sakkinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.