bcm53xx: revert SPI controller commit breaking flash reads
authorRafał Miłecki <rafal@milecki.pl>
Sun, 29 Jul 2018 09:01:14 +0000 (11:01 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Sun, 29 Jul 2018 09:02:57 +0000 (11:02 +0200)
That upstream commit caused instability in flash reads. It was reported
but there isn't any proper fix as for now.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
target/linux/bcm53xx/patches-4.14/800-Revert-spi-bcm-qspi-Fix-bcm_qspi_bspi_read-performan.patch [new file with mode: 0644]

diff --git a/target/linux/bcm53xx/patches-4.14/800-Revert-spi-bcm-qspi-Fix-bcm_qspi_bspi_read-performan.patch b/target/linux/bcm53xx/patches-4.14/800-Revert-spi-bcm-qspi-Fix-bcm_qspi_bspi_read-performan.patch
new file mode 100644 (file)
index 0000000..64f971d
--- /dev/null
@@ -0,0 +1,146 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Subject: [PATCH] Revert "spi: bcm-qspi: Fix bcm_qspi_bspi_read() performance"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit 345309fa7c0c9206a5344d379b174499952d79d9.
+
+BSPI reads became unstable starting with above commit. There are BSPI
+timeouts like this:
+[   15.637809] bcm_iproc 18029200.spi: timeout waiting for BSPI
+(...)
+[   15.997809] bcm_iproc 18029200.spi: timeout waiting for BSPI
+which cause filesystem stability problems.
+
+Before above commit every time that bcm_qspi_bspi_lr_l2_isr() called
+bcm_qspi_bspi_lr_l2_isr() it was resulting in bspi_rf_msg_len becoming
+0.
+With that change it's not the case anymore which suggests there may be
+some bug around that code.
+
+It has changed and the new behavior seems to be causing problems.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/drivers/spi/spi-bcm-qspi.c
++++ b/drivers/spi/spi-bcm-qspi.c
+@@ -88,7 +88,7 @@
+ #define BSPI_BPP_MODE_SELECT_MASK             BIT(8)
+ #define BSPI_BPP_ADDR_SELECT_MASK             BIT(16)
+-#define BSPI_READ_LENGTH                      512
++#define BSPI_READ_LENGTH                      256
+ /* MSPI register offsets */
+ #define MSPI_SPCR0_LSB                                0x000
+@@ -806,7 +806,7 @@ static int bcm_qspi_bspi_flash_read(stru
+                                   struct spi_flash_read_message *msg)
+ {
+       struct bcm_qspi *qspi = spi_master_get_devdata(spi->master);
+-      u32 addr = 0, len, rdlen, len_words;
++      u32 addr = 0, len, len_words;
+       int ret = 0;
+       unsigned long timeo = msecs_to_jiffies(100);
+       struct bcm_qspi_soc_intc *soc_intc = qspi->soc_intc;
+@@ -819,7 +819,7 @@ static int bcm_qspi_bspi_flash_read(stru
+       bcm_qspi_write(qspi, MSPI, MSPI_WRITE_LOCK, 0);
+       /*
+-       * when using flex mode we need to send
++       * when using flex mode mode we need to send
+        * the upper address byte to bspi
+        */
+       if (bcm_qspi_bspi_ver_three(qspi) == false) {
+@@ -833,56 +833,47 @@ static int bcm_qspi_bspi_flash_read(stru
+       else
+               addr = msg->from & 0x00ffffff;
++      /* set BSPI RAF buffer max read length */
++      len = msg->len;
++      if (len > BSPI_READ_LENGTH)
++              len = BSPI_READ_LENGTH;
++
+       if (bcm_qspi_bspi_ver_three(qspi) == true)
+               addr = (addr + 0xc00000) & 0xffffff;
+-      /*
+-       * read into the entire buffer by breaking the reads
+-       * into RAF buffer read lengths
+-       */
+-      len = msg->len;
++      reinit_completion(&qspi->bspi_done);
++      bcm_qspi_enable_bspi(qspi);
++      len_words = (len + 3) >> 2;
++      qspi->bspi_rf_msg = msg;
++      qspi->bspi_rf_msg_status = 0;
+       qspi->bspi_rf_msg_idx = 0;
++      qspi->bspi_rf_msg_len = len;
++      dev_dbg(&qspi->pdev->dev, "bspi xfr addr 0x%x len 0x%x", addr, len);
+-      do {
+-              if (len > BSPI_READ_LENGTH)
+-                      rdlen = BSPI_READ_LENGTH;
+-              else
+-                      rdlen = len;
+-
+-              reinit_completion(&qspi->bspi_done);
+-              bcm_qspi_enable_bspi(qspi);
+-              len_words = (rdlen + 3) >> 2;
+-              qspi->bspi_rf_msg = msg;
+-              qspi->bspi_rf_msg_status = 0;
+-              qspi->bspi_rf_msg_len = rdlen;
+-              dev_dbg(&qspi->pdev->dev,
+-                      "bspi xfr addr 0x%x len 0x%x", addr, rdlen);
+-              bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
+-              bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
+-              bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
+-              if (qspi->soc_intc) {
+-                      /*
+-                       * clear soc MSPI and BSPI interrupts and enable
+-                       * BSPI interrupts.
+-                       */
+-                      soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
+-                      soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
+-              }
++      bcm_qspi_write(qspi, BSPI, BSPI_RAF_START_ADDR, addr);
++      bcm_qspi_write(qspi, BSPI, BSPI_RAF_NUM_WORDS, len_words);
++      bcm_qspi_write(qspi, BSPI, BSPI_RAF_WATERMARK, 0);
++
++      if (qspi->soc_intc) {
++              /*
++               * clear soc MSPI and BSPI interrupts and enable
++               * BSPI interrupts.
++               */
++              soc_intc->bcm_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
++              soc_intc->bcm_qspi_int_set(soc_intc, BSPI_DONE, true);
++      }
+-              /* Must flush previous writes before starting BSPI operation */
+-              mb();
+-              bcm_qspi_bspi_lr_start(qspi);
+-              if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
+-                      dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
+-                      ret = -ETIMEDOUT;
+-                      break;
+-              }
++      /* Must flush previous writes before starting BSPI operation */
++      mb();
+-              /* set msg return length */
+-              msg->retlen += rdlen;
+-              addr += rdlen;
+-              len -= rdlen;
+-      } while (len);
++      bcm_qspi_bspi_lr_start(qspi);
++      if (!wait_for_completion_timeout(&qspi->bspi_done, timeo)) {
++              dev_err(&qspi->pdev->dev, "timeout waiting for BSPI\n");
++              ret = -ETIMEDOUT;
++      } else {
++              /* set the return length for the caller */
++              msg->retlen = len;
++      }
+       return ret;
+ }