2017-08-31 17:08:14

by Alexander Steffen

[permalink] [raw]
Subject: [PATCH RESEND v3 0/2] tpm_tis_spi: Use DMA-safe memory

The documentation says that DMA-safe memory is required for SPI transfers.
The I/O buffers passed in by the caller can be allocated anywhere,
including on the stack, which is not DMA-safe. So the data needs to be
copied to separate, DMA-safe buffers.

We did not see any DMA-related issues on our test systems, even without
DMA-safe buffers. But this might simply be due to the fact that the SPI
transfer size is rather small, so our systems do not bother to set up DMA
transfers. Other systems might do so.

v2:
- Updated commit message with more explanations.

v3:
- Split into two patches, one for making the buffers DMA-safe and another
for using only a single buffer.

Alexander Steffen (2):
tpm_tis_spi: Use DMA-safe memory for SPI transfers
tpm_tis_spi: Use a single buffer for SPI transfers

drivers/char/tpm/tpm_tis_spi.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)

--
2.7.4


2017-08-31 17:08:26

by Alexander Steffen

[permalink] [raw]
Subject: [PATCH RESEND v3 2/2] tpm_tis_spi: Use a single buffer for SPI transfers

A single buffer is sufficient for both tx and rx, since bytes that have
already been sent are not used anymore and can safely be overwritten with
the received bytes.

Signed-off-by: Alexander Steffen <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm_tis_spi.c | 34 ++++++++++++++--------------------
1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index 05ce841..5321245 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -46,9 +46,7 @@
struct tpm_tis_spi_phy {
struct tpm_tis_data priv;
struct spi_device *spi_device;
-
- u8 *tx_buf;
- u8 *rx_buf;
+ u8 *iobuf;
};

static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
@@ -71,14 +69,14 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
while (len) {
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;
+ phy->iobuf[0] = direction | (transfer_len - 1);
+ phy->iobuf[1] = 0xd4;
+ phy->iobuf[2] = addr >> 8;
+ phy->iobuf[3] = addr;

memset(&spi_xfer, 0, sizeof(spi_xfer));
- spi_xfer.tx_buf = phy->tx_buf;
- spi_xfer.rx_buf = phy->rx_buf;
+ spi_xfer.tx_buf = phy->iobuf;
+ spi_xfer.rx_buf = phy->iobuf;
spi_xfer.len = 4;
spi_xfer.cs_change = 1;

@@ -88,9 +86,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
if (ret < 0)
goto exit;

- if ((phy->rx_buf[3] & 0x01) == 0) {
+ if ((phy->iobuf[3] & 0x01) == 0) {
// handle SPI wait states
- phy->tx_buf[0] = 0;
+ phy->iobuf[0] = 0;

for (i = 0; i < TPM_RETRY; i++) {
spi_xfer.len = 1;
@@ -99,7 +97,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
ret = spi_sync_locked(phy->spi_device, &m);
if (ret < 0)
goto exit;
- if (phy->rx_buf[0] & 0x01)
+ if (phy->iobuf[0] & 0x01)
break;
}

@@ -117,7 +115,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
spi_xfer.tx_buf = NULL;
} else {
spi_xfer.rx_buf = NULL;
- memcpy(phy->tx_buf, buffer, transfer_len);
+ memcpy(phy->iobuf, buffer, transfer_len);
}

spi_message_init(&m);
@@ -127,7 +125,7 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
goto exit;

if (direction)
- memcpy(buffer, phy->rx_buf, transfer_len);
+ memcpy(buffer, phy->iobuf, transfer_len);

len -= transfer_len;
buffer += transfer_len;
@@ -196,12 +194,8 @@ static int tpm_tis_spi_probe(struct spi_device *dev)

phy->spi_device = dev;

- phy->tx_buf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
- if (!phy->tx_buf)
- return -ENOMEM;
-
- phy->rx_buf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
- if (!phy->rx_buf)
+ phy->iobuf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+ if (!phy->iobuf)
return -ENOMEM;

return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops,
--
2.7.4

2017-08-31 17:08:24

by Alexander Steffen

[permalink] [raw]
Subject: [PATCH RESEND v3 1/2] tpm_tis_spi: Use DMA-safe memory for SPI transfers

The buffers used as tx_buf/rx_buf in a SPI transfer need to be DMA-safe.
This cannot be guaranteed for the buffers passed to tpm_tis_spi_read_bytes
and tpm_tis_spi_write_bytes. Therefore, we need to use our own DMA-safe
buffer and copy the data to/from it.

The buffer needs to be allocated separately, to ensure that it is
cacheline-aligned and not shared with other data, so that DMA can work
correctly.

Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy")
Cc: [email protected]
Signed-off-by: Alexander Steffen <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm_tis_spi.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index 88fe72a..05ce841 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[4];
- u8 rx_buf[4];
+ u8 *tx_buf;
+ u8 *rx_buf;
};

static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
@@ -115,10 +115,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,

if (direction) {
spi_xfer.tx_buf = NULL;
- spi_xfer.rx_buf = buffer;
} else {
- spi_xfer.tx_buf = buffer;
spi_xfer.rx_buf = NULL;
+ memcpy(phy->tx_buf, buffer, transfer_len);
}

spi_message_init(&m);
@@ -127,6 +126,9 @@ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
if (ret < 0)
goto exit;

+ if (direction)
+ memcpy(buffer, phy->rx_buf, transfer_len);
+
len -= transfer_len;
buffer += transfer_len;
}
@@ -194,6 +196,14 @@ static int tpm_tis_spi_probe(struct spi_device *dev)

phy->spi_device = dev;

+ phy->tx_buf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+ if (!phy->tx_buf)
+ return -ENOMEM;
+
+ phy->rx_buf = devm_kmalloc(&dev->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+ if (!phy->rx_buf)
+ return -ENOMEM;
+
return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops,
NULL);
}
--
2.7.4

2017-09-02 10:54:29

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 0/2] tpm_tis_spi: Use DMA-safe memory

On Thu, Aug 31, 2017 at 06:58:17PM +0200, Alexander Steffen wrote:
> The documentation says that DMA-safe memory is required for SPI transfers.
> The I/O buffers passed in by the caller can be allocated anywhere,
> including on the stack, which is not DMA-safe. So the data needs to be
> copied to separate, DMA-safe buffers.
>
> We did not see any DMA-related issues on our test systems, even without
> DMA-safe buffers. But this might simply be due to the fact that the SPI
> transfer size is rather small, so our systems do not bother to set up DMA
> transfers. Other systems might do so.
>
> v2:
> - Updated commit message with more explanations.
>
> v3:
> - Split into two patches, one for making the buffers DMA-safe and another
> for using only a single buffer.
>
> Alexander Steffen (2):
> tpm_tis_spi: Use DMA-safe memory for SPI transfers
> tpm_tis_spi: Use a single buffer for SPI transfers
>
> drivers/char/tpm/tpm_tis_spi.c | 32 ++++++++++++++++++--------------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> --
> 2.7.4
>

Great, I'll try to get means to test this!

/Jarkko

2017-09-06 12:55:04

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 0/2] tpm_tis_spi: Use DMA-safe memory

On Thu, Aug 31, 2017 at 06:58:17PM +0200, Alexander Steffen wrote:
> The documentation says that DMA-safe memory is required for SPI transfers.
> The I/O buffers passed in by the caller can be allocated anywhere,
> including on the stack, which is not DMA-safe. So the data needs to be
> copied to separate, DMA-safe buffers.
>
> We did not see any DMA-related issues on our test systems, even without
> DMA-safe buffers. But this might simply be due to the fact that the SPI
> transfer size is rather small, so our systems do not bother to set up DMA
> transfers. Other systems might do so.
>
> v2:
> - Updated commit message with more explanations.
>
> v3:
> - Split into two patches, one for making the buffers DMA-safe and another
> for using only a single buffer.
>
> Alexander Steffen (2):
> tpm_tis_spi: Use DMA-safe memory for SPI transfers
> tpm_tis_spi: Use a single buffer for SPI transfers
>
> drivers/char/tpm/tpm_tis_spi.c | 32 ++++++++++++++++++--------------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> --
> 2.7.4
>

Applied to my bleeding edge master brach for more convenient testing.
Have not yet applied to my next branch.

/Jarkko

2017-09-08 12:11:28

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH RESEND v3 0/2] tpm_tis_spi: Use DMA-safe memory

On Wed, Sep 06, 2017 at 03:54:58PM +0300, Jarkko Sakkinen wrote:
> On Thu, Aug 31, 2017 at 06:58:17PM +0200, Alexander Steffen wrote:
> > The documentation says that DMA-safe memory is required for SPI transfers.
> > The I/O buffers passed in by the caller can be allocated anywhere,
> > including on the stack, which is not DMA-safe. So the data needs to be
> > copied to separate, DMA-safe buffers.
> >
> > We did not see any DMA-related issues on our test systems, even without
> > DMA-safe buffers. But this might simply be due to the fact that the SPI
> > transfer size is rather small, so our systems do not bother to set up DMA
> > transfers. Other systems might do so.
> >
> > v2:
> > - Updated commit message with more explanations.
> >
> > v3:
> > - Split into two patches, one for making the buffers DMA-safe and another
> > for using only a single buffer.
> >
> > Alexander Steffen (2):
> > tpm_tis_spi: Use DMA-safe memory for SPI transfers
> > tpm_tis_spi: Use a single buffer for SPI transfers
> >
> > drivers/char/tpm/tpm_tis_spi.c | 32 ++++++++++++++++++--------------
> > 1 file changed, 18 insertions(+), 14 deletions(-)
> >
> > --
> > 2.7.4
> >
>
> Applied to my bleeding edge master brach for more convenient testing.
> Have not yet applied to my next branch.
>
> /Jarkko

Tested-by: Jarkko Sakkinen <[email protected]>

My XP13 happened to have suitable TPM.

/Jarkko