]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Fri, 6 Sep 2019 20:39:10 +0000 (16:39 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 6 Sep 2019 20:39:10 +0000 (16:39 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/series
queue-4.14/spi-bcm2835aux-fix-corruptions-for-longer-spi-transf.patch [new file with mode: 0644]
queue-4.14/spi-bcm2835aux-remove-dangerous-uncontrolled-read-of.patch [new file with mode: 0644]
queue-4.14/spi-bcm2835aux-unifying-code-between-polling-and-int.patch [new file with mode: 0644]

index 97392233cc0c308cd6ad4d775a43bef4d43ebe49..0e3fe88ea9b0cc3296547bc116900dd94664889f 100644 (file)
@@ -26,3 +26,6 @@ ceph-fix-buffer-free-while-holding-i_ceph_lock-in-__.patch-14468
 ceph-fix-buffer-free-while-holding-i_ceph_lock-in-fi.patch
 kvm-arm-arm64-only-skip-mmio-insn-once.patch
 libceph-allow-ceph_buffer_put-to-receive-a-null-ceph.patch
+spi-bcm2835aux-unifying-code-between-polling-and-int.patch
+spi-bcm2835aux-remove-dangerous-uncontrolled-read-of.patch
+spi-bcm2835aux-fix-corruptions-for-longer-spi-transf.patch
diff --git a/queue-4.14/spi-bcm2835aux-fix-corruptions-for-longer-spi-transf.patch b/queue-4.14/spi-bcm2835aux-fix-corruptions-for-longer-spi-transf.patch
new file mode 100644 (file)
index 0000000..1d847d7
--- /dev/null
@@ -0,0 +1,62 @@
+From bb1bc414f2bd9ca8e28eb35aecca6403ec6527ba Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Sat, 30 Mar 2019 09:31:00 +0000
+Subject: spi: bcm2835aux: fix corruptions for longer spi transfers
+
+[ Upstream commit 73b114ee7db1750c0b535199fae383b109bd61d0 ]
+
+On long running tests with a mcp2517fd can controller it showed that
+on rare occations the data read shows corruptions for longer spi transfers.
+
+Example of a 22 byte transfer:
+
+expected (as captured on logic analyzer):
+FF FF 78 00 00 00 08 06 00 00 91 20 77 56 84 85 86 87 88 89 8a 8b
+
+read by the driver:
+FF FF 78 00 00 00 08 06 00 00 91 20 77 56 84 88 89 8a 00 00 8b 9b
+
+To fix this use BCM2835_AUX_SPI_STAT_RX_LVL to determine when we may
+read data from the fifo reliably without any corruption.
+
+Surprisingly the only values ever empirically read in
+BCM2835_AUX_SPI_STAT_RX_LVL are 0x00, 0x10, 0x20 and 0x30.
+So whenever the mask is not 0 we can read from the fifo in a safe manner.
+
+The patch has now been tested intensively and we are no longer
+able to reproduce the "RX" issue any longer.
+
+Fixes: 1ea29b39f4c812ec ("spi: bcm2835aux: add bcm2835 auxiliary spi device...")
+Reported-by: Hubert Denkmair <h.denkmair@intence.de>
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-bcm2835aux.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
+index 4454d9c6a3dd4..5c89bbb05441b 100644
+--- a/drivers/spi/spi-bcm2835aux.c
++++ b/drivers/spi/spi-bcm2835aux.c
+@@ -180,12 +180,12 @@ static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
+ static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
+ {
++      u32 stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
++
+       /* check if we have data to read */
+-      while (bs->rx_len &&
+-             (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+-                BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
++      for (; bs->rx_len && (stat & BCM2835_AUX_SPI_STAT_RX_LVL);
++           stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT))
+               bcm2835aux_rd_fifo(bs);
+-      }
+       /* check if we have data to write */
+       while (bs->tx_len &&
+-- 
+2.20.1
+
diff --git a/queue-4.14/spi-bcm2835aux-remove-dangerous-uncontrolled-read-of.patch b/queue-4.14/spi-bcm2835aux-remove-dangerous-uncontrolled-read-of.patch
new file mode 100644 (file)
index 0000000..875f760
--- /dev/null
@@ -0,0 +1,44 @@
+From b8eb2d2c96ed2fc2c974212589233f4e7d98a152 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Sat, 30 Mar 2019 09:30:59 +0000
+Subject: spi: bcm2835aux: remove dangerous uncontrolled read of fifo
+
+[ Upstream commit c7de8500fd8ecbb544846dd5f11dca578c3777e1 ]
+
+This read of the fifo is a potential candidate for a race condition
+as the spi transfer is not necessarily finished and so can lead to
+an early read of the fifo that still misses data.
+
+So it has been removed.
+
+Fixes: 1ea29b39f4c812ec ("spi: bcm2835aux: add bcm2835 auxiliary spi device...")
+Suggested-by: Hubert Denkmair <h.denkmair@intence.de>
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-bcm2835aux.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
+index 97cb3beb9cc62..4454d9c6a3dd4 100644
+--- a/drivers/spi/spi-bcm2835aux.c
++++ b/drivers/spi/spi-bcm2835aux.c
+@@ -194,13 +194,6 @@ static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
+                 BCM2835_AUX_SPI_STAT_TX_FULL))) {
+               bcm2835aux_wr_fifo(bs);
+       }
+-
+-      /* and check if we have reached "done" */
+-      while (bs->rx_len &&
+-             (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+-                BCM2835_AUX_SPI_STAT_BUSY))) {
+-              bcm2835aux_rd_fifo(bs);
+-      }
+ }
+ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+-- 
+2.20.1
+
diff --git a/queue-4.14/spi-bcm2835aux-unifying-code-between-polling-and-int.patch b/queue-4.14/spi-bcm2835aux-unifying-code-between-polling-and-int.patch
new file mode 100644 (file)
index 0000000..52412f6
--- /dev/null
@@ -0,0 +1,126 @@
+From 4f421c8a5cbc2e2461254d5132c061174daa1a47 Mon Sep 17 00:00:00 2001
+From: Martin Sperl <kernel@martin.sperl.org>
+Date: Sat, 30 Mar 2019 09:30:58 +0000
+Subject: spi: bcm2835aux: unifying code between polling and interrupt driven
+ code
+
+[ Upstream commit 7188a6f0eee3f1fae5d826cfc6d569657ff950ec ]
+
+Sharing more code between polling and interrupt-driven mode.
+
+Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
+Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-bcm2835aux.c | 51 +++++++++++++-----------------------
+ 1 file changed, 18 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
+index bd00b7cc8b78b..97cb3beb9cc62 100644
+--- a/drivers/spi/spi-bcm2835aux.c
++++ b/drivers/spi/spi-bcm2835aux.c
+@@ -178,23 +178,13 @@ static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
+                     BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
+ }
+-static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
++static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs)
+ {
+-      struct spi_master *master = dev_id;
+-      struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+-      irqreturn_t ret = IRQ_NONE;
+-
+-      /* IRQ may be shared, so return if our interrupts are disabled */
+-      if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+-            (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+-              return ret;
+-
+       /* check if we have data to read */
+       while (bs->rx_len &&
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
+               bcm2835aux_rd_fifo(bs);
+-              ret = IRQ_HANDLED;
+       }
+       /* check if we have data to write */
+@@ -203,7 +193,6 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_TX_FULL))) {
+               bcm2835aux_wr_fifo(bs);
+-              ret = IRQ_HANDLED;
+       }
+       /* and check if we have reached "done" */
+@@ -211,8 +200,21 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_BUSY))) {
+               bcm2835aux_rd_fifo(bs);
+-              ret = IRQ_HANDLED;
+       }
++}
++
++static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
++{
++      struct spi_master *master = dev_id;
++      struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
++
++      /* IRQ may be shared, so return if our interrupts are disabled */
++      if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
++            (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
++              return IRQ_NONE;
++
++      /* do common fifo handling */
++      bcm2835aux_spi_transfer_helper(bs);
+       if (!bs->tx_len) {
+               /* disable tx fifo empty interrupt */
+@@ -226,8 +228,7 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+               complete(&master->xfer_completion);
+       }
+-      /* and return */
+-      return ret;
++      return IRQ_HANDLED;
+ }
+ static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
+@@ -273,7 +274,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
+ {
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+       unsigned long timeout;
+-      u32 stat;
+       /* configure spi */
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+@@ -284,24 +284,9 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
+       /* loop until finished the transfer */
+       while (bs->rx_len) {
+-              /* read status */
+-              stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
+-
+-              /* fill in tx fifo with remaining data */
+-              if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) {
+-                      bcm2835aux_wr_fifo(bs);
+-                      continue;
+-              }
+-              /* read data from fifo for both cases */
+-              if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) {
+-                      bcm2835aux_rd_fifo(bs);
+-                      continue;
+-              }
+-              if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) {
+-                      bcm2835aux_rd_fifo(bs);
+-                      continue;
+-              }
++              /* do common fifo handling */
++              bcm2835aux_spi_transfer_helper(bs);
+               /* there is still data pending to read check the timeout */
+               if (bs->rx_len && time_after(jiffies, timeout)) {
+-- 
+2.20.1
+