From patchwork Fri Feb 17 15:20:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benoit HOUYERE X-Patchwork-Id: 729221 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vPyjJ4XQjz9s7w for ; Sat, 18 Feb 2017 03:12:35 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=sfs-ml-3.v29.ch3.sourceforge.com) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1cel91-0000VL-TZ; Fri, 17 Feb 2017 16:12:27 +0000 Received: from sog-mx-2.v43.ch3.sourceforge.com ([172.29.43.192] helo=mx.sourceforge.net) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1cel91-0000VF-EP for tpmdd-devel@lists.sourceforge.net; Fri, 17 Feb 2017 16:12:27 +0000 Received-SPF: pass (sog-mx-2.v43.ch3.sourceforge.com: domain of st.com designates 91.207.212.93 as permitted sender) client-ip=91.207.212.93; envelope-from=benoit.houyere@st.com; helo=mx07-00178001.pphosted.com; Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by sog-mx-2.v43.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.76) id 1cel8z-0007Wd-2o for tpmdd-devel@lists.sourceforge.net; Fri, 17 Feb 2017 16:12:27 +0000 Received: from pps.filterd (m0046660.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id v1HFB5YJ028235 for ; Fri, 17 Feb 2017 16:20:04 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-.pphosted.com with ESMTP id 28hrmac909-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Fri, 17 Feb 2017 16:20:04 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 9ECDA31 for ; Fri, 17 Feb 2017 15:20:03 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag3node3.st.com [10.75.127.9]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 6B76B265F for ; Fri, 17 Feb 2017 15:20:03 +0000 (GMT) Received: from SFHDAG3NODE3.st.com (10.75.127.9) by SFHDAG3NODE3.st.com (10.75.127.9) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Fri, 17 Feb 2017 16:20:02 +0100 Received: from SFHDAG3NODE3.st.com ([fe80::3507:b372:7648:476]) by SFHDAG3NODE3.st.com ([fe80::3507:b372:7648:476%20]) with mapi id 15.00.1178.000; Fri, 17 Feb 2017 16:20:02 +0100 From: Benoit HOUYERE To: "tpmdd-devel@lists.sourceforge.net" Thread-Topic: tpmdd-devel Digest, Vol 110, Issue 19 Thread-Index: AQHSiG899VlUf3pLw0m3PfdPBSvRyKFtT/MQ Date: Fri, 17 Feb 2017 15:20:02 +0000 Message-ID: References: In-Reply-To: Accept-Language: fr-FR, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.75.127.46] MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-17_13:, , signatures=0 X-Spam-Score: -1.5 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1cel8z-0007Wd-2o Subject: Re: [tpmdd-devel] tpmdd-devel Digest, Vol 110, Issue 19 X-BeenThere: tpmdd-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Tpm Device Driver maintainance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: tpmdd-devel-bounces@lists.sourceforge.net 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 2. [PATCH 0/5] Fix whole native SPI TPM driver (Peter Huewe) Tested-by: Benoit Houyere 3. [PATCH 1/5] tpm_tis_spi: Use single function to transfer data (Peter Huewe) Tested-by: Benoit Houyere 4. [PATCH 2/5] tpm_tis_spi: Abort transfer when too many wait states are signaled (Peter Huewe) Tested-by: Benoit Houyere 5. [PATCH 3/5] tpm_tis_spi: Check correct byte for wait state indicator (Peter Huewe) Tested-by: Benoit Houyere 6. [PATCH 5/5] tpm_tis_spi: Add small delay after last transfer (Peter Huewe) Tested-by: Benoit Houyere 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 Subject: [tpmdd-devel] [PATCH 4/5] tpm_tis_spi: Remove limitation of transfers to MAX_SPI_FRAMESIZE bytes To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe , 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: Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe --- drivers/char/tpm/tpm_tis_spi.c | 108 ++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 51 deletions(-) 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 Subject: [tpmdd-devel] [PATCH 0/5] Fix whole native SPI TPM driver To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe 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 Subject: [tpmdd-devel] [PATCH 1/5] tpm_tis_spi: Use single function to transfer data To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe , 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: [prerequisite for other fixes in this series] Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe --- 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 Subject: [tpmdd-devel] [PATCH 2/5] tpm_tis_spi: Abort transfer when too many wait states are signaled To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe , 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: Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe --- 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 Subject: [tpmdd-devel] [PATCH 3/5] tpm_tis_spi: Check correct byte for wait state indicator To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe , 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: Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe --- 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 Subject: [tpmdd-devel] [PATCH 5/5] tpm_tis_spi: Add small delay after last transfer To: Jarkko Sakkinen Cc: linux-kernel@vger.kernel.org, stable@vger.kernel.org, tpmdd-devel@lists.sourceforge.net, Christophe Ricard , Peter Huewe , 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: Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen Signed-off-by: Peter Huewe --- 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;