[tpmdd-devel] tpmdd-devel Digest, Vol 110, Issue 19

Submitted by Benoit HOUYERE on Feb. 17, 2017, 3:20 p.m.

Details

Message ID f60e26ea3ca54a8f964b98c49089ac37@SFHDAG3NODE3.st.com
State New
Headers show

Commit Message

Benoit HOUYERE Feb. 17, 2017, 3:20 p.m.
Hi Jarko,

For your information : 

   1. [PATCH 4/5] tpm_tis_spi: Remove limitation of	transfers to
      MAX_SPI_FRAMESIZE bytes (Peter Huewe)  
	Tested-by: Benoit Houyere <benoit.houyere@st.com>
   2. [PATCH 0/5] Fix whole native SPI TPM driver (Peter Huewe)
	Tested-by: Benoit Houyere <benoit.houyere@st.com>
   3. [PATCH 1/5] tpm_tis_spi: Use single function to	transfer data
      (Peter Huewe)
	Tested-by: Benoit Houyere <benoit.houyere@st.com>
   4. [PATCH 2/5] tpm_tis_spi: Abort transfer when too many	wait
      states are signaled (Peter Huewe)
	Tested-by: Benoit Houyere <benoit.houyere@st.com>
   5. [PATCH 3/5] tpm_tis_spi: Check correct byte for wait	state
      indicator (Peter Huewe)
	Tested-by: Benoit Houyere <benoit.houyere@st.com>
   6. [PATCH 5/5] tpm_tis_spi: Add small delay after last	transfer
      (Peter Huewe)
	Tested-by: Benoit Houyere <benoit.houyere@st.com>


Best Regards,

Benoit
-----Original Message-----
From: tpmdd-devel-request@lists.sourceforge.net [mailto:tpmdd-devel-request@lists.sourceforge.net] 
Sent: jeudi 16 février 2017 17:11
To: tpmdd-devel@lists.sourceforge.net
Subject: tpmdd-devel Digest, Vol 110, Issue 19

Send tpmdd-devel mailing list submissions to
	tpmdd-devel@lists.sourceforge.net

To subscribe or unsubscribe via the World Wide Web, visit
	https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
or, via email, send a message with subject or body 'help' to
	tpmdd-devel-request@lists.sourceforge.net

You can reach the person managing the list at
	tpmdd-devel-owner@lists.sourceforge.net

When replying, please edit your Subject line so it is more specific than "Re: Contents of tpmdd-devel digest..."


Today's Topics:

   1. [PATCH 4/5] tpm_tis_spi: Remove limitation of	transfers to
      MAX_SPI_FRAMESIZE bytes (Peter Huewe) 
   2. [PATCH 0/5] Fix whole native SPI TPM driver (Peter Huewe)
   3. [PATCH 1/5] tpm_tis_spi: Use single function to	transfer data
      (Peter Huewe)
   4. [PATCH 2/5] tpm_tis_spi: Abort transfer when too many	wait
      states are signaled (Peter Huewe)
   5. [PATCH 3/5] tpm_tis_spi: Check correct byte for wait	state
      indicator (Peter Huewe)
   6. [PATCH 5/5] tpm_tis_spi: Add small delay after last	transfer
      (Peter Huewe)


----------------------------------------------------------------------

Message: 1
Date: Thu, 16 Feb 2017 16:08:25 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 4/5] tpm_tis_spi: Remove limitation of
	transfers to MAX_SPI_FRAMESIZE bytes
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net,	Christophe Ricard
	<christophe-h.ricard@st.com>, Peter	Huewe <peter.huewe@infineon.com>,
	Alexander
Message-ID:
	<1487261306-2494-5-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

Limiting transfers to MAX_SPI_FRAMESIZE was not expected by the upper layers, as tpm_tis has no such limitation. Add a loop to hide that limitation.

Cc: <stable@vger.kernel.org>
Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
 drivers/char/tpm/tpm_tis_spi.c | 108 ++++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 51 deletions(-)

Comments

Jarkko Sakkinen Feb. 20, 2017, 10:56 a.m.
On Fri, Feb 17, 2017 at 03:20:02PM +0000, Benoit HOUYERE wrote:
> Hi Jarko,
> 
> For your information : 
> 
>    1. [PATCH 4/5] tpm_tis_spi: Remove limitation of	transfers to
>       MAX_SPI_FRAMESIZE bytes (Peter Huewe)  
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>
>    2. [PATCH 0/5] Fix whole native SPI TPM driver (Peter Huewe)
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>
>    3. [PATCH 1/5] tpm_tis_spi: Use single function to	transfer data
>       (Peter Huewe)
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>
>    4. [PATCH 2/5] tpm_tis_spi: Abort transfer when too many	wait
>       states are signaled (Peter Huewe)
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>
>    5. [PATCH 3/5] tpm_tis_spi: Check correct byte for wait	state
>       indicator (Peter Huewe)
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>
>    6. [PATCH 5/5] tpm_tis_spi: Add small delay after last	transfer
>       (Peter Huewe)
> 	Tested-by: Benoit Houyere <benoit.houyere@st.com>

Thanks.

> Best Regards,
> 
> Benoit

/Jarkko

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

Patch hide | download patch | download mbox

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 16938e2253d2..b50c5b072df3 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -61,68 +61,74 @@  static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,  {
 	struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
 	int ret;
-	struct spi_message m;
-	struct spi_transfer spi_xfer = {
-		.tx_buf = phy->tx_buf,
-		.rx_buf = phy->rx_buf,
-		.len = 4,
-		.cs_change = 1,
-	};
-
-	if (len > MAX_SPI_FRAMESIZE)
-		return -ENOMEM;
 
-	phy->tx_buf[0] = direction | (len - 1);
-	phy->tx_buf[1] = 0xd4;
-	phy->tx_buf[2] = addr >> 8;
-	phy->tx_buf[3] = addr;
+	spi_bus_lock(phy->spi_device->master);
 
-	spi_message_init(&m);
-	spi_message_add_tail(&spi_xfer, &m);
+	while (len) {
+		struct spi_message m;
+		struct spi_transfer spi_xfer = {
+			.tx_buf = phy->tx_buf,
+			.rx_buf = phy->rx_buf,
+			.len = 4,
+			.cs_change = 1,
+		};
+		u8 transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+		phy->tx_buf[0] = direction | (transfer_len - 1);
+		phy->tx_buf[1] = 0xd4;
+		phy->tx_buf[2] = addr >> 8;
+		phy->tx_buf[3] = addr;
+
+		spi_message_init(&m);
+		spi_message_add_tail(&spi_xfer, &m);
+		ret = spi_sync_locked(phy->spi_device, &m);
+		if (ret < 0)
+			goto exit;
 
-	spi_bus_lock(phy->spi_device->master);
-	ret = spi_sync_locked(phy->spi_device, &m);
-	if (ret < 0)
-		goto exit;
-
-	if ((phy->rx_buf[3] & 0x01) == 0) {
-		// handle SPI wait states
-		int i;
-
-		phy->tx_buf[0] = 0;
-
-		for (i = 0; i < TPM_RETRY; i++) {
-			spi_xfer.len = 1;
-			spi_message_init(&m);
-			spi_message_add_tail(&spi_xfer, &m);
-			ret = spi_sync_locked(phy->spi_device, &m);
-			if (ret < 0)
+		if ((phy->rx_buf[3] & 0x01) == 0) {
+			// handle SPI wait states
+			int i;
+
+			phy->tx_buf[0] = 0;
+
+			for (i = 0; i < TPM_RETRY; i++) {
+				spi_xfer.len = 1;
+				spi_message_init(&m);
+				spi_message_add_tail(&spi_xfer, &m);
+				ret = spi_sync_locked(phy->spi_device, &m);
+				if (ret < 0)
+					goto exit;
+				if (phy->rx_buf[0] & 0x01)
+					break;
+			}
+
+			if (i == TPM_RETRY) {
+				ret = -ETIMEDOUT;
 				goto exit;
-			if (phy->rx_buf[0] & 0x01)
-				break;
+			}
 		}
 
-		if (i == TPM_RETRY) {
-			ret = -ETIMEDOUT;
-			goto exit;
+		spi_xfer.cs_change = 0;
+		spi_xfer.len = transfer_len;
+
+		if (direction) {
+			spi_xfer.tx_buf = NULL;
+			spi_xfer.rx_buf = buffer;
+		} else {
+			spi_xfer.tx_buf = buffer;
+			spi_xfer.rx_buf = NULL;
 		}
-	}
 
-	spi_xfer.cs_change = 0;
-	spi_xfer.len = len;
+		spi_message_init(&m);
+		spi_message_add_tail(&spi_xfer, &m);
+		ret = spi_sync_locked(phy->spi_device, &m);
+		if (ret < 0)
+			goto exit;
 
-	if (direction) {
-		spi_xfer.tx_buf = NULL;
-		spi_xfer.rx_buf = buffer;
-	} else {
-		spi_xfer.tx_buf = buffer;
-		spi_xfer.rx_buf = NULL;
+		len -= transfer_len;
+		buffer += transfer_len;
 	}
 
-	spi_message_init(&m);
-	spi_message_add_tail(&spi_xfer, &m);
-	ret = spi_sync_locked(phy->spi_device, &m);
-
 exit:
 	spi_bus_unlock(phy->spi_device->master);
 	return ret;
--
2.7.4




------------------------------

Message: 2
Date: Thu, 16 Feb 2017 16:08:21 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 0/5] Fix whole native SPI TPM driver
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, tpmdd-devel@lists.sourceforge.net,
	Christophe Ricard <christophe-h.ricard@st.com>, Peter	Huewe
	<peter.huewe@infineon.com>
Message-ID:
	<1487261306-2494-1-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

During our testing it showed that unfortunately the whole native spi tpm driver
was more or less non-functional since it was merged, e.g. the wrong byte for
waitstate handling was used and transfers larger than 64 bytes did not work at all.

This was probably caused by the merging of the different approaches back then,
as the initial RFC patch did not have these problems, and also my sudden lack
of time/commitment back then.
I'm sorry that the final driver code went untested for that long time.

This patch set fixes these issues one by one.
In order to avoid duplication the read/write function was consolidated to one
transfer function, so we do not have to apply the same fix at two locations.
Maybe consider squashing it - we splitted it for easier review.
 
Affected Kernels: 4.8, 4.9, 4.10
Patchset was tested on Raspberry Pi2 with SLB9670 (TPM1.2 and TPM2.0)

Peter Huewe (5):
  tpm_tis_spi: Use single function to transfer data
  tpm_tis_spi: Abort transfer when too many wait states are signaled
  tpm_tis_spi: Check correct byte for wait state indicator
  tpm_tis_spi: Remove limitation of transfers to MAX_SPI_FRAMESIZE bytes
  tpm_tis_spi: Add small delay after last transfer

 drivers/char/tpm/tpm_tis_spi.c | 163 +++++++++++++++++------------------------
 1 file changed, 69 insertions(+), 94 deletions(-)

-- 
2.7.4




------------------------------

Message: 3
Date: Thu, 16 Feb 2017 16:08:22 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 1/5] tpm_tis_spi: Use single function to
	transfer data
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net,	Christophe Ricard
	<christophe-h.ricard@st.com>, Peter	Huewe <peter.huewe@infineon.com>,
	Alexander
Message-ID:
	<1487261306-2494-2-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

The algorithm for sending data to the TPM is mostly identical to the
algorithm for receiving data from the TPM, so a single function is
sufficient to handle both cases.

This is a prequisite for all the other fixes, so we don't have to fix
everything twice (send/receive)

Cc: <stable@vger.kernel.org>
[prerequisite for other fixes in this series]
Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
 drivers/char/tpm/tpm_tis_spi.c | 87 ++++++++++++------------------------------
 1 file changed, 24 insertions(+), 63 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index 5292e5768a7e..6e1a3c43f621 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -47,8 +47,8 @@  struct tpm_tis_spi_phy {
 	struct tpm_tis_data priv;
 	struct spi_device *spi_device;
 
-	u8 tx_buf[MAX_SPI_FRAMESIZE + 4];
-	u8 rx_buf[MAX_SPI_FRAMESIZE + 4];
+	u8 tx_buf[4];
+	u8 rx_buf[4];
 };
 
 static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
@@ -56,8 +56,8 @@  static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da
 	return container_of(data, struct tpm_tis_spi_phy, priv);
 }
 
-static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
-				  u16 len, u8 *result)
+static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,
+				u8 *buffer, u8 direction)
 {
 	struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
 	int ret, i;
@@ -66,17 +66,17 @@  static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
 		.tx_buf = phy->tx_buf,
 		.rx_buf = phy->rx_buf,
 		.len = 4,
+		.cs_change = 1,
 	};
 
 	if (len > MAX_SPI_FRAMESIZE)
 		return -ENOMEM;
 
-	phy->tx_buf[0] = 0x80 | (len - 1);
+	phy->tx_buf[0] = direction | (len - 1);
 	phy->tx_buf[1] = 0xd4;
-	phy->tx_buf[2] = (addr >> 8)  & 0xFF;
-	phy->tx_buf[3] = addr	      & 0xFF;
+	phy->tx_buf[2] = addr >> 8;
+	phy->tx_buf[3] = addr;
 
-	spi_xfer.cs_change = 1;
 	spi_message_init(&m);
 	spi_message_add_tail(&spi_xfer, &m);
 
@@ -85,7 +85,7 @@  static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
 	if (ret < 0)
 		goto exit;
 
-	memset(phy->tx_buf, 0, len);
+	phy->tx_buf[0] = 0;
 
 	/* According to TCG PTP specification, if there is no TPM present at
 	 * all, then the design has a weak pull-up on MISO. If a TPM is not
@@ -103,7 +103,14 @@  static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
 
 	spi_xfer.cs_change = 0;
 	spi_xfer.len = len;
-	spi_xfer.rx_buf = result;
+
+	if (direction) {
+		spi_xfer.tx_buf = NULL;
+		spi_xfer.rx_buf = buffer;
+	} else {
+		spi_xfer.tx_buf = buffer;
+		spi_xfer.rx_buf = NULL;
+	}
 
 	spi_message_init(&m);
 	spi_message_add_tail(&spi_xfer, &m);
@@ -114,62 +121,16 @@  static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
 	return ret;
 }
 
+static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
+				  u16 len, u8 *result)
+{
+	return tpm_tis_spi_transfer(data, addr, len, result, 0x80);
+}
+
 static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
 				   u16 len, u8 *value)
 {
-	struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
-	int ret, i;
-	struct spi_message m;
-	struct spi_transfer spi_xfer = {
-		.tx_buf = phy->tx_buf,
-		.rx_buf = phy->rx_buf,
-		.len = 4,
-	};
-
-	if (len > MAX_SPI_FRAMESIZE)
-		return -ENOMEM;
-
-	phy->tx_buf[0] = len - 1;
-	phy->tx_buf[1] = 0xd4;
-	phy->tx_buf[2] = (addr >> 8)  & 0xFF;
-	phy->tx_buf[3] = addr         & 0xFF;
-
-	spi_xfer.cs_change = 1;
-	spi_message_init(&m);
-	spi_message_add_tail(&spi_xfer, &m);
-
-	spi_bus_lock(phy->spi_device->master);
-	ret = spi_sync_locked(phy->spi_device, &m);
-	if (ret < 0)
-		goto exit;
-
-	memset(phy->tx_buf, 0, len);
-
-	/* According to TCG PTP specification, if there is no TPM present at
-	 * all, then the design has a weak pull-up on MISO. If a TPM is not
-	 * present, a pull-up on MISO means that the SB controller sees a 1,
-	 * and will latch in 0xFF on the read.
-	 */
-	for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) {
-		spi_xfer.len = 1;
-		spi_message_init(&m);
-		spi_message_add_tail(&spi_xfer, &m);
-		ret = spi_sync_locked(phy->spi_device, &m);
-		if (ret < 0)
-			goto exit;
-	}
-
-	spi_xfer.len = len;
-	spi_xfer.tx_buf = value;
-	spi_xfer.cs_change = 0;
-	spi_xfer.tx_buf = value;
-	spi_message_init(&m);
-	spi_message_add_tail(&spi_xfer, &m);
-	ret = spi_sync_locked(phy->spi_device, &m);
-
-exit:
-	spi_bus_unlock(phy->spi_device->master);
-	return ret;
+	return tpm_tis_spi_transfer(data, addr, len, value, 0);
 }
 
 static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
-- 
2.7.4




------------------------------

Message: 4
Date: Thu, 16 Feb 2017 16:08:23 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 2/5] tpm_tis_spi: Abort transfer when
	too many	wait states are signaled
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net,	Christophe Ricard
	<christophe-h.ricard@st.com>, Peter	Huewe <peter.huewe@infineon.com>,
	Alexander
Message-ID:
	<1487261306-2494-3-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

Abort the transfer with ETIMEDOUT when the TPM signals more than
TPM_RETRY wait states. Continuing with the transfer in this state
will only lead to arbitrary failures in other parts of the code.

Cc: <stable@vger.kernel.org>
Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
 drivers/char/tpm/tpm_tis_spi.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index 6e1a3c43f621..d782b9974c14 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -101,6 +101,11 @@  static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,
 			goto exit;
 	}
 
+	if (i == TPM_RETRY) {
+		ret = -ETIMEDOUT;
+		goto exit;
+	}
+
 	spi_xfer.cs_change = 0;
 	spi_xfer.len = len;
 
-- 
2.7.4




------------------------------

Message: 5
Date: Thu, 16 Feb 2017 16:08:24 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 3/5] tpm_tis_spi: Check correct byte for
	wait	state indicator
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net,	Christophe Ricard
	<christophe-h.ricard@st.com>, Peter	Huewe <peter.huewe@infineon.com>,
	Alexander
Message-ID:
	<1487261306-2494-4-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

Wait states are signaled in the last byte received from the TPM in
response to the header, not the first byte. Check rx_buf[3] instead of
rx_buf[0].

Cc: <stable@vger.kernel.org>
Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
 drivers/char/tpm/tpm_tis_spi.c | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index d782b9974c14..16938e2253d2 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -60,7 +60,7 @@  static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,
 				u8 *buffer, u8 direction)
 {
 	struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
-	int ret, i;
+	int ret;
 	struct spi_message m;
 	struct spi_transfer spi_xfer = {
 		.tx_buf = phy->tx_buf,
@@ -85,25 +85,27 @@  static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,
 	if (ret < 0)
 		goto exit;
 
-	phy->tx_buf[0] = 0;
-
-	/* According to TCG PTP specification, if there is no TPM present at
-	 * all, then the design has a weak pull-up on MISO. If a TPM is not
-	 * present, a pull-up on MISO means that the SB controller sees a 1,
-	 * and will latch in 0xFF on the read.
-	 */
-	for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) {
-		spi_xfer.len = 1;
-		spi_message_init(&m);
-		spi_message_add_tail(&spi_xfer, &m);
-		ret = spi_sync_locked(phy->spi_device, &m);
-		if (ret < 0)
+	if ((phy->rx_buf[3] & 0x01) == 0) {
+		// handle SPI wait states
+		int i;
+
+		phy->tx_buf[0] = 0;
+
+		for (i = 0; i < TPM_RETRY; i++) {
+			spi_xfer.len = 1;
+			spi_message_init(&m);
+			spi_message_add_tail(&spi_xfer, &m);
+			ret = spi_sync_locked(phy->spi_device, &m);
+			if (ret < 0)
+				goto exit;
+			if (phy->rx_buf[0] & 0x01)
+				break;
+		}
+
+		if (i == TPM_RETRY) {
+			ret = -ETIMEDOUT;
 			goto exit;
-	}
-
-	if (i == TPM_RETRY) {
-		ret = -ETIMEDOUT;
-		goto exit;
+		}
 	}
 
 	spi_xfer.cs_change = 0;
-- 
2.7.4




------------------------------

Message: 6
Date: Thu, 16 Feb 2017 16:09:46 +0000
From: Peter Huewe <peter.huewe@infineon.com>
Subject: [tpmdd-devel] [PATCH 5/5] tpm_tis_spi: Add small delay after
	last	transfer
To: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org,
	tpmdd-devel@lists.sourceforge.net,	Christophe Ricard
	<christophe-h.ricard@st.com>, Peter	Huewe <peter.huewe@infineon.com>,
	Alexander
Message-ID:
	<1487261386-2641-5-git-send-email-peter.huewe@infineon.com>
Content-Type: text/plain

Testing the implementation with a Raspberry Pi 2 showed that under some
circumstances its SPI master erroneously releases the CS line before the
transfer is complete, i.e. before the end of the last clock. In this case
the TPM ignores the transfer and misses for example the GO command. The
driver is unable to detect this communication problem and will wait for a
command response that is never going to arrive, timing out eventually.

As a workaround, the small delay ensures that the CS line is held long
enough, even with a faulty SPI master. Other SPI masters are not affected,
except for a negligible performance penalty.

Cc: <stable@vger.kernel.org>
Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
 drivers/char/tpm/tpm_tis_spi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index b50c5b072df3..685c51bf5d7e 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -110,6 +110,7 @@  static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u8 len,
 
 		spi_xfer.cs_change = 0;
 		spi_xfer.len = transfer_len;
+		spi_xfer.delay_usecs = 5;
 
 		if (direction) {
 			spi_xfer.tx_buf = NULL;