From: Rafał Miłecki Date: Sun, 29 Jul 2018 09:01:14 +0000 (+0200) Subject: bcm53xx: revert SPI controller commit breaking flash reads X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=0417b08b06dd946c2670d0a19e3426c61e33f6be;p=openwrt%2Fstaging%2Flynxis.git bcm53xx: revert SPI controller commit breaking flash reads 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 --- 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 index 0000000000..64f971d349 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.14/800-Revert-spi-bcm-qspi-Fix-bcm_qspi_bspi_read-performan.patch @@ -0,0 +1,146 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 +--- + +--- 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; + }