bluetooth-btusb-use-dmi-matching-for-qca-reset_resume-quirking.patch
+tpm-st33zp24-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_i2c_infineon-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_i2c_nuvoton-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm_tis-fix-potential-buffer-overruns-caused-by-bit-glitches-on-the-bus.patch
+tpm-constify-transmit-data-pointers.patch
+tpm_tis_spi-use-dma-safe-memory-for-spi-transfers.patch
+tpm-dev-common-reject-too-short-writes.patch
--- /dev/null
+From c37fbc09bd4977736f6bc4050c6f099c587052a7 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 7 Sep 2017 15:30:45 +0200
+Subject: tpm: constify transmit data pointers
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit c37fbc09bd4977736f6bc4050c6f099c587052a7 upstream.
+
+Making cmd_getticks 'const' introduced a couple of harmless warnings:
+
+drivers/char/tpm/tpm_tis_core.c: In function 'probe_itpm':
+drivers/char/tpm/tpm_tis_core.c:469:31: error: passing argument 2 of 'tpm_tis_send_data' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
+ rc = tpm_tis_send_data(chip, cmd_getticks, len);
+drivers/char/tpm/tpm_tis_core.c:477:31: error: passing argument 2 of 'tpm_tis_send_data' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
+ rc = tpm_tis_send_data(chip, cmd_getticks, len);
+drivers/char/tpm/tpm_tis_core.c:255:12: note: expected 'u8 * {aka unsigned char *}' but argument is of type 'const u8 * {aka const unsigned char *}'
+ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
+
+This changes the related functions to all take 'const' pointers
+so that gcc can see this as being correct. I had to slightly
+modify the logic around tpm_tis_spi_transfer() for this to work
+without introducing ugly casts.
+
+Cc: stable@vger.kernel.org
+Fixes: 5e35bd8e06b9 ("tpm_tis: make array cmd_getticks static const to shink object code size")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_tis.c | 2 +-
+ drivers/char/tpm/tpm_tis_core.c | 4 ++--
+ drivers/char/tpm/tpm_tis_core.h | 4 ++--
+ drivers/char/tpm/tpm_tis_spi.c | 25 +++++++++++--------------
+ 4 files changed, 16 insertions(+), 19 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -98,7 +98,7 @@ static int tpm_tcg_read_bytes(struct tpm
+ }
+
+ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
+- u8 *value)
++ const u8 *value)
+ {
+ struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -257,7 +257,7 @@ out:
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+-static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
++static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
+ {
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ int rc, status, burstcnt;
+@@ -346,7 +346,7 @@ static void disable_interrupts(struct tp
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+-static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
++static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+ {
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ int rc;
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -98,7 +98,7 @@ struct tpm_tis_phy_ops {
+ int (*read_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
+ u8 *result);
+ int (*write_bytes)(struct tpm_tis_data *data, u32 addr, u16 len,
+- u8 *value);
++ const u8 *value);
+ int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result);
+ int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result);
+ int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src);
+@@ -128,7 +128,7 @@ static inline int tpm_tis_read32(struct
+ }
+
+ static inline int tpm_tis_write_bytes(struct tpm_tis_data *data, u32 addr,
+- u16 len, u8 *value)
++ u16 len, const u8 *value)
+ {
+ return data->phy_ops->write_bytes(data, addr, len, value);
+ }
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ b/drivers/char/tpm/tpm_tis_spi.c
+@@ -58,7 +58,7 @@ static inline struct tpm_tis_spi_phy *to
+ }
+
+ static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
+- u8 *buffer, u8 direction)
++ u8 *in, const u8 *out)
+ {
+ struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
+ int ret = 0;
+@@ -72,7 +72,7 @@ static int tpm_tis_spi_transfer(struct t
+ while (len) {
+ transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+- phy->tx_buf[0] = direction | (transfer_len - 1);
++ phy->tx_buf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+ phy->tx_buf[1] = 0xd4;
+ phy->tx_buf[2] = addr >> 8;
+ phy->tx_buf[3] = addr;
+@@ -113,14 +113,8 @@ static int tpm_tis_spi_transfer(struct t
+ spi_xfer.cs_change = 0;
+ spi_xfer.len = transfer_len;
+ spi_xfer.delay_usecs = 5;
+-
+- 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.tx_buf = out;
++ spi_xfer.rx_buf = in;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+@@ -129,7 +123,10 @@ static int tpm_tis_spi_transfer(struct t
+ goto exit;
+
+ len -= transfer_len;
+- buffer += transfer_len;
++ if (in)
++ in += transfer_len;
++ if (out)
++ out += transfer_len;
+ }
+
+ exit:
+@@ -140,13 +137,13 @@ exit:
+ 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);
++ return tpm_tis_spi_transfer(data, addr, len, result, NULL);
+ }
+
+ static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
+- u16 len, u8 *value)
++ u16 len, const u8 *value)
+ {
+- return tpm_tis_spi_transfer(data, addr, len, value, 0);
++ return tpm_tis_spi_transfer(data, addr, len, NULL, value);
+ }
+
+ static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
--- /dev/null
+From ee70bc1e7b63ac8023c9ff9475d8741e397316e7 Mon Sep 17 00:00:00 2001
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+Date: Fri, 8 Sep 2017 17:21:32 +0200
+Subject: tpm-dev-common: Reject too short writes
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+commit ee70bc1e7b63ac8023c9ff9475d8741e397316e7 upstream.
+
+tpm_transmit() does not offer an explicit interface to indicate the number
+of valid bytes in the communication buffer. Instead, it relies on the
+commandSize field in the TPM header that is encoded within the buffer.
+Therefore, ensure that a) enough data has been written to the buffer, so
+that the commandSize field is present and b) the commandSize field does not
+announce more data than has been written to the buffer.
+
+This should have been fixed with CVE-2011-1161 long ago, but apparently
+a correct version of that patch never made it into the kernel.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-dev.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/char/tpm/tpm-dev.c
++++ b/drivers/char/tpm/tpm-dev.c
+@@ -136,6 +136,12 @@ static ssize_t tpm_write(struct file *fi
+ return -EFAULT;
+ }
+
++ if (in_size < 6 ||
++ in_size < be32_to_cpu(*((__be32 *) (priv->data_buffer + 2)))) {
++ mutex_unlock(&priv->buffer_mutex);
++ return -EINVAL;
++ }
++
+ /* atomic tpm command send and result receive. We only hold the ops
+ * lock during this period so that the tpm can be unregistered even if
+ * the char dev is held open.
--- /dev/null
+From 6d24cd186d9fead3722108dec1b1c993354645ff Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:29:09 -0800
+Subject: tpm: st33zp24: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 6d24cd186d9fead3722108dec1b1c993354645ff upstream.
+
+Discrete TPMs are often connected over slow serial buses which, on
+some platforms, can have glitches causing bit flips. In all the
+driver _recv() functions, we need to use a u32 to unmarshal the
+response size, otherwise a bit flip of the 31st bit would cause the
+expected variable to go negative, which would then try to read a huge
+amount of data. Also sanity check that the expected amount of data is
+large enough for the TPM header.
+
+Signed-off-by: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Cc: stable@vger.kernel.org
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: James Morris <james.morris@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/st33zp24/st33zp24.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/st33zp24/st33zp24.c
++++ b/drivers/char/tpm/st33zp24/st33zp24.c
+@@ -458,7 +458,7 @@ static int st33zp24_recv(struct tpm_chip
+ size_t count)
+ {
+ int size = 0;
+- int expected;
++ u32 expected;
+
+ if (!chip)
+ return -EBUSY;
+@@ -475,7 +475,7 @@ static int st33zp24_recv(struct tpm_chip
+ }
+
+ expected = be32_to_cpu(*(__be32 *)(buf + 2));
+- if (expected > count) {
++ if (expected > count || expected < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
--- /dev/null
+From 9b8cb28d7c62568a5916bdd7ea1c9176d7f8f2ed Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:30:01 -0800
+Subject: tpm_i2c_infineon: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 9b8cb28d7c62568a5916bdd7ea1c9176d7f8f2ed upstream.
+
+Discrete TPMs are often connected over slow serial buses which, on
+some platforms, can have glitches causing bit flips. In all the
+driver _recv() functions, we need to use a u32 to unmarshal the
+response size, otherwise a bit flip of the 31st bit would cause the
+expected variable to go negative, which would then try to read a huge
+amount of data. Also sanity check that the expected amount of data is
+large enough for the TPM header.
+
+Signed-off-by: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Cc: stable@vger.kernel.org
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: James Morris <james.morris@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_i2c_infineon.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_i2c_infineon.c
++++ b/drivers/char/tpm/tpm_i2c_infineon.c
+@@ -437,7 +437,8 @@ static int recv_data(struct tpm_chip *ch
+ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+ {
+ int size = 0;
+- int expected, status;
++ int status;
++ u32 expected;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+@@ -452,7 +453,7 @@ static int tpm_tis_i2c_recv(struct tpm_c
+ }
+
+ expected = be32_to_cpu(*(__be32 *)(buf + 2));
+- if ((size_t) expected > count) {
++ if (((size_t) expected > count) || (expected < TPM_HEADER_SIZE)) {
+ size = -EIO;
+ goto out;
+ }
--- /dev/null
+From f9d4d9b5a5ef2f017bc344fb65a58a902517173b Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:31:16 -0800
+Subject: tpm_i2c_nuvoton: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit f9d4d9b5a5ef2f017bc344fb65a58a902517173b upstream.
+
+Discrete TPMs are often connected over slow serial buses which, on
+some platforms, can have glitches causing bit flips. In all the
+driver _recv() functions, we need to use a u32 to unmarshal the
+response size, otherwise a bit flip of the 31st bit would cause the
+expected variable to go negative, which would then try to read a huge
+amount of data. Also sanity check that the expected amount of data is
+large enough for the TPM header.
+
+Signed-off-by: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Cc: stable@vger.kernel.org
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: James Morris <james.morris@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_i2c_nuvoton.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
++++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
+@@ -281,7 +281,11 @@ static int i2c_nuvoton_recv(struct tpm_c
+ struct device *dev = chip->dev.parent;
+ struct i2c_client *client = to_i2c_client(dev);
+ s32 rc;
+- int expected, status, burst_count, retries, size = 0;
++ int status;
++ int burst_count;
++ int retries;
++ int size = 0;
++ u32 expected;
+
+ if (count < TPM_HEADER_SIZE) {
+ i2c_nuvoton_ready(chip); /* return to idle */
+@@ -323,7 +327,7 @@ static int i2c_nuvoton_recv(struct tpm_c
+ * to machine native
+ */
+ expected = be32_to_cpu(*(__be32 *) (buf + 2));
+- if (expected > count) {
++ if (expected > count || expected < size) {
+ dev_err(dev, "%s() expected > count\n", __func__);
+ size = -EIO;
+ continue;
--- /dev/null
+From 6bb320ca4a4a7b5b3db8c8d7250cc40002046878 Mon Sep 17 00:00:00 2001
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Date: Thu, 8 Feb 2018 12:32:06 -0800
+Subject: tpm_tis: fix potential buffer overruns caused by bit glitches on the bus
+
+From: Jeremy Boone <jeremy.boone@nccgroup.trust>
+
+commit 6bb320ca4a4a7b5b3db8c8d7250cc40002046878 upstream.
+
+Discrete TPMs are often connected over slow serial buses which, on
+some platforms, can have glitches causing bit flips. In all the
+driver _recv() functions, we need to use a u32 to unmarshal the
+response size, otherwise a bit flip of the 31st bit would cause the
+expected variable to go negative, which would then try to read a huge
+amount of data. Also sanity check that the expected amount of data is
+large enough for the TPM header.
+
+Signed-off-by: Jeremy Boone <jeremy.boone@nccgroup.trust>
+Cc: stable@vger.kernel.org
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: James Morris <james.morris@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_tis_core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -208,7 +208,8 @@ static int tpm_tis_recv(struct tpm_chip
+ {
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ int size = 0;
+- int expected, status;
++ int status;
++ u32 expected;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+@@ -223,7 +224,7 @@ static int tpm_tis_recv(struct tpm_chip
+ }
+
+ expected = be32_to_cpu(*(__be32 *) (buf + 2));
+- if (expected > count) {
++ if (expected > count || expected < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
--- /dev/null
+From 6b3a13173f23e798e1ba213dd4a2c065a3b8d751 Mon Sep 17 00:00:00 2001
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+Date: Mon, 11 Sep 2017 12:26:52 +0200
+Subject: tpm_tis_spi: Use DMA-safe memory for SPI transfers
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+commit 6b3a13173f23e798e1ba213dd4a2c065a3b8d751 upstream.
+
+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: stable@vger.kernel.org
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm_tis_spi.c | 45 ++++++++++++++++++++++++-----------------
+ 1 file changed, 27 insertions(+), 18 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_spi.c
++++ b/drivers/char/tpm/tpm_tis_spi.c
+@@ -47,9 +47,7 @@
+ struct tpm_tis_spi_phy {
+ struct tpm_tis_data priv;
+ struct spi_device *spi_device;
+-
+- u8 tx_buf[4];
+- u8 rx_buf[4];
++ u8 *iobuf;
+ };
+
+ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
+@@ -72,14 +70,14 @@ static int tpm_tis_spi_transfer(struct t
+ while (len) {
+ transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+- phy->tx_buf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+- phy->tx_buf[1] = 0xd4;
+- phy->tx_buf[2] = addr >> 8;
+- phy->tx_buf[3] = addr;
++ phy->iobuf[0] = (in ? 0x80 : 0) | (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;
+
+@@ -89,9 +87,9 @@ static int tpm_tis_spi_transfer(struct t
+ 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;
+@@ -100,7 +98,7 @@ static int tpm_tis_spi_transfer(struct t
+ 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;
+ }
+
+@@ -113,8 +111,14 @@ static int tpm_tis_spi_transfer(struct t
+ spi_xfer.cs_change = 0;
+ spi_xfer.len = transfer_len;
+ spi_xfer.delay_usecs = 5;
+- spi_xfer.tx_buf = out;
+- spi_xfer.rx_buf = in;
++
++ if (in) {
++ spi_xfer.tx_buf = NULL;
++ } else if (out) {
++ spi_xfer.rx_buf = NULL;
++ memcpy(phy->iobuf, out, transfer_len);
++ out += transfer_len;
++ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&spi_xfer, &m);
+@@ -122,11 +126,12 @@ static int tpm_tis_spi_transfer(struct t
+ if (ret < 0)
+ goto exit;
+
+- len -= transfer_len;
+- if (in)
++ if (in) {
++ memcpy(in, phy->iobuf, transfer_len);
+ in += transfer_len;
+- if (out)
+- out += transfer_len;
++ }
++
++ len -= transfer_len;
+ }
+
+ exit:
+@@ -192,6 +197,10 @@ static int tpm_tis_spi_probe(struct spi_
+
+ phy->spi_device = dev;
+
++ 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,
+ NULL);
+ }