aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm53xx/patches-4.14/800-Revert-spi-bcm-qspi-Fix-bcm_qspi_bspi_read-performan.patch
blob: 64f971d349f4664ac0f8e186cf84b0aee73b4092 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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;
 }