Skip to contentSkip to conversation

arm: sunxi: Add NULL pointer check

PATCH New Stefan Mavrodiev 5 participants 25 messages Dec 5, 2018 – Dec 20, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +2 -1
index b86b5a00ad..38cc743c61 100644
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
 	while (len--) {
 		byte = readb(&priv->regs->rxdata);
-		*priv->rx_buf++ = byte;
+		if (priv->rx_buf)
+			*priv->rx_buf++ = byte;
 	}
 }
 
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
 	while (len--) {
 		byte = readb(&priv->regs->rxdata);
-		*priv->rx_buf++ = byte;
+		if (priv->rx_buf)
+			*priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

I'm not sure if that can even happen?

Maxime

Signature · 10 lines
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181205/278b4f81/attachment.sig>
#2 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
  drivers/spi/sun4i_spi.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
  	while (len--) {
  		byte = readb(&priv->regs->rxdata);
-		*priv->rx_buf++ = byte;
+		if (priv->rx_buf)
+			*priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't
work. I'm thinking that the fifo must be drained in any case.

Quoted 3 lines

Maxime

#3 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 28 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
  drivers/spi/sun4i_spi.c | 3 ++-

  1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct 
 sun4i_spi_priv *priv, int len)
         while (len--) {
           byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 9 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't
work. I'm thinking that the fifo must be drained in any case.

Quoted 3 lines

Maxime

Any further comments?

#4 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 30 lines · Stefan Mavrodiev
Quoted 28 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
  drivers/spi/sun4i_spi.c | 3 ++-

  1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void
 sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
         while (len--) {
           byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't work. I'm thinking that the fifo must be drained in any case.

Any further comments?

I was expecting you to comment on whether the FIFO needed to be drained or not :)

Maxime

Signature · 10 lines
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181214/474b96eb/attachment.sig>
#5 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 29 lines · Maxime Ripard
Quoted 28 lines · Stefan Mavrodiev
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
   drivers/spi/sun4i_spi.c | 3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void
 sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
         while (len--) {
           byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't work. I'm thinking that the fifo must be drained in any case.

Any further comments?

I was expecting you to comment on whether the FIFO needed to be drained or not :)

Sorry. I didn't understand that.

Anyway. After some code checking, I found that the FIFO needs to be drained because TP_EN (Transmit Pause Enable) bit is set during bus claim.

"....

In master mode, it is used to control transmit state machine to stop smart burst sending when RX FIFO is full.

..."

Perhaps this bit should be enabled only when we want to read back data?

Quoted 3 lines

Maxime

#6 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 44 lines · Stefan Mavrodiev
Quoted 29 lines · Maxime Ripard
Quoted 28 lines · Stefan Mavrodiev
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
   drivers/spi/sun4i_spi.c | 3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void
 sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
         while (len--) {
           byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't work. I'm thinking that the fifo must be drained in any case.

Any further comments?

I was expecting you to comment on whether the FIFO needed to be drained or not :)

Sorry. I didn't understand that.

Anyway. After some code checking, I found that the FIFO needs to be drained because TP_EN (Transmit Pause Enable) bit is set during bus claim.

Quoted 8 lines

"....

In master mode, it is used to control transmit state machine to stop smart burst sending when RX FIFO is full.

..."

Perhaps this bit should be enabled only when we want to read back data?

It's been a while since I last looked at the spi driver. What is linux doing?

Maxime

Signature · 10 lines
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181214/a68f5355/attachment.sig>
#7 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 45 lines · Maxime Ripard
Quoted 44 lines · Stefan Mavrodiev
Quoted 29 lines · Maxime Ripard
Quoted 28 lines · Stefan Mavrodiev
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
    drivers/spi/sun4i_spi.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void
 sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
          while (len--) {
            byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't work. I'm thinking that the fifo must be drained in any case.

Any further comments?

I was expecting you to comment on whether the FIFO needed to be drained or not :)

Sorry. I didn't understand that.

Anyway. After some code checking, I found that the FIFO needs to be drained because TP_EN (Transmit Pause Enable) bit is set during bus claim.

"....

Quoted 8 lines
Quoted 6 lines

In master mode, it is used to control transmit state machine to stop smart burst sending when RX FIFO is full.

..."

Perhaps this bit should be enabled only when we want to read back data?

It's been a while since I last looked at the spi driver. What is linux doing?

In the kernel version there is the same check, like the one in the patch:

drivers/spi/spi-sun4i.c:
static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
......

while (len--) {
    byte = readb(sspi->base_addr + SUN4I_RXDATA_REG); if (sspi->rx_buf)
        *sspi->rx_buf++ = byte;
}
.....

Guess I've missed this check when I was adopting the driver for u-boot.

Quoted 3 lines

Maxime

#8 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 63 lines · Stefan Mavrodiev
Quoted 46 lines · Maxime Ripard
Quoted 45 lines · Stefan Mavrodiev
Quoted 29 lines · Maxime Ripard
Quoted 28 lines · Stefan Mavrodiev
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Maxime Ripard
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
    drivers/spi/sun4i_spi.c | 3 ++-

    1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void
 sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
           while (len--) {
             byte = readb(&priv->regs->rxdata);
-        *priv->rx_buf++ = byte;
+        if (priv->rx_buf)
+            *priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
Quoted 1 line

I'm not sure if that can even happen?

I've tried to check that before draining the receive fifo, but then the controller doesn't work. I'm thinking that the fifo must be drained in any case.

Any further comments?

I was expecting you to comment on whether the FIFO needed to be drained or not :)

Sorry. I didn't understand that.

Anyway. After some code checking, I found that the FIFO needs to be drained
because TP_EN (Transmit Pause Enable) bit is set during bus claim.

"....

Quoted 8 lines
Quoted 6 lines

In master mode, it is used to control transmit state machine to stop smart burst sending when RX FIFO is full.

..."

Perhaps this bit should be enabled only when we want to read back data?

It's been a while since I last looked at the spi driver. What is linux doing?

In the kernel version there is the same check, like the one in the patch:

drivers/spi/spi-sun4i.c:
static inline void sun4i_spi_drain_fifo(struct sun4i_spi *sspi, int len)
......

Quoted 13 lines

while (len--) {
    byte = readb(sspi->base_addr + SUN4I_RXDATA_REG); if (sspi->rx_buf)
        *sspi->rx_buf++ = byte;
}
.....

Guess I've missed this check when I was adopting the driver for u-boot.

Quoted 3 lines

Maxime

Any comments?
I think with all said, the patch can be merged as it is.

#9 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

In reply to Maxime Ripard

On 05/12/2018 15:46, Maxime Ripard wrote:

Hi,

Quoted 18 lines · Stefan Mavrodiev
Quoted 17 lines

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
Quoted 8 lines

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 5 lines
drivers/spi/sun4i_spi.c +2 -1
 	while (len--) {
 		byte = readb(&priv->regs->rxdata);
-		*priv->rx_buf++ = byte;
+		if (priv->rx_buf)
+			*priv->rx_buf++ = byte;

It seems pretty inefficient to test the pointer at each access, it would be better to check it once before starting the transfer.

I appreciate the intention to avoid bloat and the attention to detail, but:

This check boils down to exactly one 16-bit instruction:
10c: b11a cbz r2, 116 <sun4i_spi_xfer+0x116>
- which only accesses a register
- inside a loop with does an MMIO(!) read from a device
- handling transfers from a serial device transferring 100s of KB/s
- in a system which's sole purpose is to read data on a single core
- in U-Boot ;-)

So the "performance impact" of this check is probably totally negligible.

There are quite some spi_xfer() calls with explicit NULL arguments, for instance when we just want to transfer something.

So I wonder if we just want to take this patch, since it fixes a memory corruption issue, plus we have a similar check in the TX path.

Cheers,
Andre.

#10 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

In reply to Stefan Mavrodiev
Quoted 17 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
        while (len--) {
                byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

#11 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 27 lines · Jagan Teki
Quoted 17 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
        while (len--) {
                byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

This patch shouldn't be merged in its current state. Please look at the on-going discussion.

Maxime

Signature · 10 lines
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20181214/fa60dfa5/attachment.sig>
#12 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 29 lines · Maxime Ripard
Quoted 27 lines · Jagan Teki
Quoted 17 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
        while (len--) {
                byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 5 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

This patch shouldn't be merged in its current state. Please look at the on-going discussion.

I have given my comments, no plan to merge as of now since the discussion is going-on.

#13 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

In reply to Jagan Teki
Quoted 28 lines · Jagan Teki
Quoted 17 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
 drivers/spi/sun4i_spi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
        while (len--) {
                byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

Didn't find any response on this? Indeed I'm waiting for it.

#14 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
  drivers/spi/sun4i_spi.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
         while (len--) {
                 byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Quoted 1 line

Didn't find any response on this? Indeed I'm waiting for it.

#15 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 29 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
  drivers/spi/sun4i_spi.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
         while (len--) {
                 byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

#16 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 29 lines · Jagan Teki
Quoted 28 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
   drivers/spi/sun4i_spi.c | 3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
          while (len--) {
                  byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

#17 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 32 lines · Stefan Mavrodiev
Quoted 29 lines · Jagan Teki
Quoted 28 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
   drivers/spi/sun4i_spi.c | 3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
          while (len--) {
                  byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
       u32 reg, cnt
       u8 byte;

        /* See how much data is available */
        reg = readl(&priv->regs->fifo_sta);
        reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
        cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

        if (len > cnt)
                len = cnt;

        while (len--) {
                byte = readb(&priv->regs->rxdata);
                *priv->rx_buf++ = byte;
        }
}

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

#18 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 62 lines · Jagan Teki
Quoted 30 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
    drivers/spi/sun4i_spi.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
           while (len--) {
                   byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
        u32 reg, cnt
        u8 byte;

         /* See how much data is available */
         reg = readl(&priv->regs->fifo_sta);
         reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
         cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

         if (len > cnt)
                 len = cnt;

         while (len--) {
                 byte = readb(&priv->regs->rxdata);
                 *priv->rx_buf++ = byte;
         }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
              const void *dout, void *din, unsigned long flags)
{
    struct udevice *bus = dev->parent;
    struct sun4i_spi_priv *priv = dev_get_priv(bus); struct dm_spi_slave_platdata *slave_plat =
dev_get_parent_platdata(dev);

    u32 len = bitlen / 8;
    u32 reg, cnt;
    u8 nbytes;
    int ret;

    priv->tx_buf = dout;
    priv->rx_buf = din;

    if (bitlen % 8) {
        debug("%s: non byte-aligned SPI transfer.\n", __func__); return -ENAVAIL;
    }

    if (flags & SPI_XFER_BEGIN) sun4i_spi_set_cs(bus, slave_plat->cs, true);

    reg = readl(&priv->regs->ctl);

    /* Reset FIFOs */
    writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

    while (len) {
        /* Setup the transfer now... */
        nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

        if (!priv->rx_buf)
            printf("%s: Sending %d bytes, ", __func__, nbytes);

        /* Setup the counters */ writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc); writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

        /* Fill the TX FIFO */
        sun4i_spi_fill_fifo(priv, nbytes);

        /* Start the transfer */
        reg = readl(&priv->regs->ctl); writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

        /* Wait transfer to complete */
        ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK, false, SUN4I_SPI_TIMEOUT_US, false); if (ret) {
            printf("ERROR: sun4i_spi: Timeout transferring data\n"); sun4i_spi_set_cs(bus, slave_plat->cs, false); return ret;
        }

        /* Drain the RX FIFO */
        if (!priv->rx_buf) {
            reg = readl(&priv->regs->fifo_sta); reg &= SUN4I_FIFO_STA_RF_CNT_MASK; cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS; printf("rx fifo: before: %d, ", cnt); }

        sun4i_spi_drain_fifo(priv, nbytes);

        if (!priv->rx_buf) {
            reg = readl(&priv->regs->fifo_sta); reg &= SUN4I_FIFO_STA_RF_CNT_MASK; cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS; printf("after: %d\n", cnt);
        }

        len -= nbytes;
    }

    if (flags & SPI_XFER_END) sun4i_spi_set_cs(bus, slave_plat->cs, false);

    return 0;
}

This will print only when destination buffer is NULL. This gave me the following output:

sun4i_spi_xfer: Sending 1 bytes, rx fifo: before: 1, after: 0
sun4i_spi_xfer: Sending 1 bytes, rx fifo: before: 1, after: 0
sun4i_spi_xfer: Sending 1 bytes, rx fifo: before: 1, after: 0
sun4i_spi_xfer: Sending 4 bytes, rx fifo: before: 4, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 4 bytes, rx fifo: before: 4, after: 0
sun4i_spi_xfer: Sending 1 bytes, rx fifo: before: 1, after: 0
sun4i_spi_xfer: Sending 1 bytes, rx fifo: before: 1, after: 0
sun4i_spi_xfer: Sending 4 bytes, rx fifo: before: 4, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0
sun4i_spi_xfer: Sending 63 bytes, rx fifo: before: 63, after: 0 .... etc

As you can see the fifo is drained.

#19 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 134 lines · Stefan Mavrodiev
Quoted 62 lines · Jagan Teki
Quoted 30 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
    drivers/spi/sun4i_spi.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
           while (len--) {
                   byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
        u32 reg, cnt
        u8 byte;

         /* See how much data is available */
         reg = readl(&priv->regs->fifo_sta);
         reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
         cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

         if (len > cnt)
                 len = cnt;

         while (len--) {
                 byte = readb(&priv->regs->rxdata);
                 *priv->rx_buf++ = byte;
         }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
     struct udevice *bus = dev->parent;
     struct sun4i_spi_priv *priv = dev_get_priv(bus);
     struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

     u32 len = bitlen / 8;
     u32 reg, cnt;
     u8 nbytes;
     int ret;

     priv->tx_buf = dout;
     priv->rx_buf = din;

     if (bitlen % 8) {
         debug("%s: non byte-aligned SPI transfer.\n", __func__);
         return -ENAVAIL;
     }

     if (flags & SPI_XFER_BEGIN)
         sun4i_spi_set_cs(bus, slave_plat->cs, true);

     reg = readl(&priv->regs->ctl);

     /* Reset FIFOs */
     writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

     while (len) {
         /* Setup the transfer now... */
         nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

         if (!priv->rx_buf)
             printf("%s: Sending %d bytes, ", __func__, nbytes);

         /* Setup the counters */
         writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
         writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

         /* Fill the TX FIFO */
         sun4i_spi_fill_fifo(priv, nbytes);

         /* Start the transfer */
         reg = readl(&priv->regs->ctl);
         writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

         /* Wait transfer to complete */
         ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                     false, SUN4I_SPI_TIMEOUT_US, false);
         if (ret) {
             printf("ERROR: sun4i_spi: Timeout transferring data\n");
             sun4i_spi_set_cs(bus, slave_plat->cs, false);
             return ret;
         }

         /* Drain the RX FIFO */
Quoted 8 lines
         if (!priv->rx_buf) {
             reg = readl(&priv->regs->fifo_sta);
             reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
             cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
             printf("rx fifo: before: %d, ", cnt);
         }

         sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

        /* See how much data is available */
        reg = readl(&priv->regs->fifo_sta);
        reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
        cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

        if (len > cnt)
                len = cnt;
#20 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 143 lines · Jagan Teki
Quoted 131 lines · Stefan Mavrodiev
Quoted 61 lines · Jagan Teki
Quoted 29 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
     drivers/spi/sun4i_spi.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
            while (len--) {
                    byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
         u32 reg, cnt
         u8 byte;

          /* See how much data is available */
          reg = readl(&priv->regs->fifo_sta);
          reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
          cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

          if (len > cnt)
                  len = cnt;

          while (len--) {
                  byte = readb(&priv->regs->rxdata);
                  *priv->rx_buf++ = byte;
          }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
      struct udevice *bus = dev->parent;
      struct sun4i_spi_priv *priv = dev_get_priv(bus);
      struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

      u32 len = bitlen / 8;
      u32 reg, cnt;
      u8 nbytes;
      int ret;

      priv->tx_buf = dout;
      priv->rx_buf = din;

      if (bitlen % 8) {
          debug("%s: non byte-aligned SPI transfer.\n", __func__);
          return -ENAVAIL;
      }

      if (flags & SPI_XFER_BEGIN)
          sun4i_spi_set_cs(bus, slave_plat->cs, true);

      reg = readl(&priv->regs->ctl);

      /* Reset FIFOs */
      writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

      while (len) {
          /* Setup the transfer now... */
          nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

          if (!priv->rx_buf)
              printf("%s: Sending %d bytes, ", __func__, nbytes);

          /* Setup the counters */
          writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
          writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

          /* Fill the TX FIFO */
          sun4i_spi_fill_fifo(priv, nbytes);

          /* Start the transfer */
          reg = readl(&priv->regs->ctl);
          writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

          /* Wait transfer to complete */
          ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                      false, SUN4I_SPI_TIMEOUT_US, false);
          if (ret) {
              printf("ERROR: sun4i_spi: Timeout transferring data\n");
              sun4i_spi_set_cs(bus, slave_plat->cs, false);
              return ret;
          }

          /* Drain the RX FIFO */
Quoted 8 lines
          if (!priv->rx_buf) {
              reg = readl(&priv->regs->fifo_sta);
              reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
              cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
              printf("rx fifo: before: %d, ", cnt);
          }

          sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

Quoted 7 lines
         /* See how much data is available */
         reg = readl(&priv->regs->fifo_sta);
         reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
         cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

         if (len > cnt)
                 len = cnt;

Yes, I didn't made any modification to sun4i_spi_drain_fifo() function:

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
{
    u8 byte;

    while (len--) {
        byte = readb(&priv->regs->rxdata);
        if (priv->rx_buf)
            *priv->rx_buf++ = byte;
    }
}

#21 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 151 lines · Stefan Mavrodiev
Quoted 148 lines · Jagan Teki
Quoted 131 lines · Stefan Mavrodiev
Quoted 61 lines · Jagan Teki
Quoted 29 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
     drivers/spi/sun4i_spi.c | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
            while (len--) {
                    byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
         u32 reg, cnt
         u8 byte;

          /* See how much data is available */
          reg = readl(&priv->regs->fifo_sta);
          reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
          cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

          if (len > cnt)
                  len = cnt;

          while (len--) {
                  byte = readb(&priv->regs->rxdata);
                  *priv->rx_buf++ = byte;
          }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
      struct udevice *bus = dev->parent;
      struct sun4i_spi_priv *priv = dev_get_priv(bus);
      struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

      u32 len = bitlen / 8;
      u32 reg, cnt;
      u8 nbytes;
      int ret;

      priv->tx_buf = dout;
      priv->rx_buf = din;

      if (bitlen % 8) {
          debug("%s: non byte-aligned SPI transfer.\n", __func__);
          return -ENAVAIL;
      }

      if (flags & SPI_XFER_BEGIN)
          sun4i_spi_set_cs(bus, slave_plat->cs, true);

      reg = readl(&priv->regs->ctl);

      /* Reset FIFOs */
      writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

      while (len) {
          /* Setup the transfer now... */
          nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

          if (!priv->rx_buf)
              printf("%s: Sending %d bytes, ", __func__, nbytes);

          /* Setup the counters */
          writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
          writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

          /* Fill the TX FIFO */
          sun4i_spi_fill_fifo(priv, nbytes);

          /* Start the transfer */
          reg = readl(&priv->regs->ctl);
          writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

          /* Wait transfer to complete */
          ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                      false, SUN4I_SPI_TIMEOUT_US, false);
          if (ret) {
              printf("ERROR: sun4i_spi: Timeout transferring data\n");
              sun4i_spi_set_cs(bus, slave_plat->cs, false);
              return ret;
          }

          /* Drain the RX FIFO */
Quoted 8 lines
          if (!priv->rx_buf) {
              reg = readl(&priv->regs->fifo_sta);
              reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
              cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
              printf("rx fifo: before: %d, ", cnt);
          }

          sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

         /* See how much data is available */
         reg = readl(&priv->regs->fifo_sta);
         reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
         cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
Quoted 4 lines
Quoted 2 lines

if (len > cnt)
len = cnt;

Yes, I didn't made any modification to sun4i_spi_drain_fifo() function:

OK, thanks for the details and test.

Please send the v2 with proper commit head it should be "spi: sun4i: ..." Also I didn't find this patch on patchwork, don't know why?

#22 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 149 lines · Jagan Teki
Quoted 148 lines · Stefan Mavrodiev
Quoted 146 lines · Jagan Teki
Quoted 129 lines · Stefan Mavrodiev
Quoted 61 lines · Jagan Teki
Quoted 29 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
      drivers/spi/sun4i_spi.c | 3 ++-
      1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
             while (len--) {
                     byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
          u32 reg, cnt
          u8 byte;

           /* See how much data is available */
           reg = readl(&priv->regs->fifo_sta);
           reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
           cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

           if (len > cnt)
                   len = cnt;

           while (len--) {
                   byte = readb(&priv->regs->rxdata);
                   *priv->rx_buf++ = byte;
           }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
       struct udevice *bus = dev->parent;
       struct sun4i_spi_priv *priv = dev_get_priv(bus);
       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

       u32 len = bitlen / 8;
       u32 reg, cnt;
       u8 nbytes;
       int ret;

       priv->tx_buf = dout;
       priv->rx_buf = din;

       if (bitlen % 8) {
           debug("%s: non byte-aligned SPI transfer.\n", __func__);
           return -ENAVAIL;
       }

       if (flags & SPI_XFER_BEGIN)
           sun4i_spi_set_cs(bus, slave_plat->cs, true);

       reg = readl(&priv->regs->ctl);

       /* Reset FIFOs */
       writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

       while (len) {
           /* Setup the transfer now... */
           nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

           if (!priv->rx_buf)
               printf("%s: Sending %d bytes, ", __func__, nbytes);

           /* Setup the counters */
           writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
           writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

           /* Fill the TX FIFO */
           sun4i_spi_fill_fifo(priv, nbytes);

           /* Start the transfer */
           reg = readl(&priv->regs->ctl);
           writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

           /* Wait transfer to complete */
           ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                       false, SUN4I_SPI_TIMEOUT_US, false);
           if (ret) {
               printf("ERROR: sun4i_spi: Timeout transferring data\n");
               sun4i_spi_set_cs(bus, slave_plat->cs, false);
               return ret;
           }

           /* Drain the RX FIFO */
Quoted 8 lines
           if (!priv->rx_buf) {
               reg = readl(&priv->regs->fifo_sta);
               reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
               cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
               printf("rx fifo: before: %d, ", cnt);
           }

           sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

          /* See how much data is available */
          reg = readl(&priv->regs->fifo_sta);
          reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
          cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
Quoted 7 lines
Quoted 3 lines
Quoted 2 lines

if (len > cnt)
len = cnt;

Yes, I didn't made any modification to sun4i_spi_drain_fifo() function:

OK, thanks for the details and test.

Please send the v2 with proper commit head it should be "spi: sun4i: ..." Also I didn't find this patch on patchwork, don't know why?

No idea. I can see it here:
https://patchwork.ozlabs.org/patch/1008181/

#23 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 154 lines · Stefan Mavrodiev
Quoted 151 lines · Jagan Teki
Quoted 150 lines · Stefan Mavrodiev
Quoted 148 lines · Jagan Teki
Quoted 129 lines · Stefan Mavrodiev
Quoted 61 lines · Jagan Teki
Quoted 29 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 16 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL. This cause the data from the FIFO to be stored inside the internal SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

---
      drivers/spi/sun4i_spi.c | 3 ++-
      1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/sun4i_spi.c +0 -0
index b86b5a00ad..38cc743c61 100644

drivers/spi/sun4i_spi.c static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) · line 133

Quoted 6 lines
drivers/spi/sun4i_spi.c +2 -1
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
 
             while (len--) {
                     byte = readb(&priv->regs->rxdata);
-               *priv->rx_buf++ = byte;
+               if (priv->rx_buf)
+                       *priv->rx_buf++ = byte;
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
          u32 reg, cnt
          u8 byte;

           /* See how much data is available */
           reg = readl(&priv->regs->fifo_sta);
           reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
           cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

           if (len > cnt)
                   len = cnt;

           while (len--) {
                   byte = readb(&priv->regs->rxdata);
                   *priv->rx_buf++ = byte;
           }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
       struct udevice *bus = dev->parent;
       struct sun4i_spi_priv *priv = dev_get_priv(bus);
       struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

       u32 len = bitlen / 8;
       u32 reg, cnt;
       u8 nbytes;
       int ret;

       priv->tx_buf = dout;
       priv->rx_buf = din;

       if (bitlen % 8) {
           debug("%s: non byte-aligned SPI transfer.\n", __func__);
           return -ENAVAIL;
       }

       if (flags & SPI_XFER_BEGIN)
           sun4i_spi_set_cs(bus, slave_plat->cs, true);

       reg = readl(&priv->regs->ctl);

       /* Reset FIFOs */
       writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

       while (len) {
           /* Setup the transfer now... */
           nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

           if (!priv->rx_buf)
               printf("%s: Sending %d bytes, ", __func__, nbytes);

           /* Setup the counters */
           writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
           writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

           /* Fill the TX FIFO */
           sun4i_spi_fill_fifo(priv, nbytes);

           /* Start the transfer */
           reg = readl(&priv->regs->ctl);
           writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

           /* Wait transfer to complete */
           ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                       false, SUN4I_SPI_TIMEOUT_US, false);
           if (ret) {
               printf("ERROR: sun4i_spi: Timeout transferring data\n");
               sun4i_spi_set_cs(bus, slave_plat->cs, false);
               return ret;
           }

           /* Drain the RX FIFO */
Quoted 8 lines
           if (!priv->rx_buf) {
               reg = readl(&priv->regs->fifo_sta);
               reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
               cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
               printf("rx fifo: before: %d, ", cnt);
           }

           sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

          /* See how much data is available */
          reg = readl(&priv->regs->fifo_sta);
          reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
          cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

          if (len > cnt)
                  len = cnt;
Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Yes, I didn't made any modification to sun4i_spi_drain_fifo() function:

OK, thanks for the details and test.

Please send the v2 with proper commit head it should be "spi: sun4i: ..." Also I didn't find this patch on patchwork, don't know why?

No idea. I can see it here:
https://patchwork.ozlabs.org/patch/1008181/

OK, got it. I will format the commit and apply if are OK?

#24 lore raw

PATCH 1/1 arm: sunxi: Add NULL pointer check

Quoted 153 lines · Jagan Teki
Quoted 152 lines · Stefan Mavrodiev
Quoted 150 lines · Jagan Teki
Quoted 149 lines · Stefan Mavrodiev
Quoted 148 lines · Jagan Teki
Quoted 129 lines · Stefan Mavrodiev
Quoted 61 lines · Jagan Teki
Quoted 29 lines · Stefan Mavrodiev
Quoted 28 lines · Jagan Teki
Quoted 27 lines · Stefan Mavrodiev
Quoted 26 lines · Jagan Teki
Quoted 25 lines · Jagan Teki
Quoted 22 lines · Stefan Mavrodiev

Current driver doesn't check if the destination pointer is NULL.
This cause the data from the FIFO to be stored inside the internal
SDRAM ( address 0 ).

The patch add simple check if the destination pointer is NULL.

Signed-off-by: Stefan Mavrodiev <[email protected]>
---
drivers/spi/sun4i_spi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index b86b5a00ad..38cc743c61 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -129,7 +129,8 @@ static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

while (len--) {
byte = readb(&priv->regs->rxdata);
- *priv->rx_buf++ = byte;
+ if (priv->rx_buf)
+ *priv->rx_buf++ = byte;

Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Quoted 2 lines

But, have you tested how much data in the fifo before drained? It's better we can get the available data before reading via fifo_sta

I don't understand what's the point of doing this?

Didn't get? don't you understand what I'm saying or it not require from point of you?

Maybe I don't understand correctly what you're saying.

You comment now and previous mail doesn't match. better be specific.

For draining fifo.
We can find how much data available before reading from fifo and assign to local rx.

static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)

{
           u32 reg, cnt
           u8 byte;

            /* See how much data is available */
            reg = readl(&priv->regs->fifo_sta);
            reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
            cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

            if (len > cnt)
                    len = cnt;

            while (len--) {
                    byte = readb(&priv->regs->rxdata);
                    *priv->rx_buf++ = byte;
            }
}
Quoted 5 lines

This can be perfect drain fifo, and this is what I'm trying to test you with existing code and after your patch and verify whether all the data perfectly drain or not before and after.

Hope you understand, this time.

Hope I understood this time...

I've made some modification to sun4i_spi_xfer:

static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)

{
        struct udevice *bus = dev->parent;
        struct sun4i_spi_priv *priv = dev_get_priv(bus);
        struct dm_spi_slave_platdata *slave_plat =

dev_get_parent_platdata(dev);

        u32 len = bitlen / 8;
        u32 reg, cnt;
        u8 nbytes;
        int ret;

        priv->tx_buf = dout;
        priv->rx_buf = din;

        if (bitlen % 8) {
            debug("%s: non byte-aligned SPI transfer.\n", __func__);
            return -ENAVAIL;
        }

        if (flags & SPI_XFER_BEGIN)
            sun4i_spi_set_cs(bus, slave_plat->cs, true);

        reg = readl(&priv->regs->ctl);

        /* Reset FIFOs */
        writel(reg | SUN4I_CTL_RF_RST | SUN4I_CTL_TF_RST, &priv->regs->ctl);

        while (len) {
            /* Setup the transfer now... */
            nbytes = min(len, (u32)(SUN4I_FIFO_DEPTH - 1));

            if (!priv->rx_buf)
                printf("%s: Sending %d bytes, ", __func__, nbytes);

            /* Setup the counters */
            writel(SUN4I_BURST_CNT(nbytes), &priv->regs->bc);
            writel(SUN4I_XMIT_CNT(nbytes), &priv->regs->tc);

            /* Fill the TX FIFO */
            sun4i_spi_fill_fifo(priv, nbytes);

            /* Start the transfer */
            reg = readl(&priv->regs->ctl);
            writel(reg | SUN4I_CTL_XCH, &priv->regs->ctl);

            /* Wait transfer to complete */
            ret = wait_for_bit_le32(&priv->regs->ctl, SUN4I_CTL_XCH_MASK,
                        false, SUN4I_SPI_TIMEOUT_US, false);
            if (ret) {
                printf("ERROR: sun4i_spi: Timeout transferring data\n");
                sun4i_spi_set_cs(bus, slave_plat->cs, false);
                return ret;
            }

            /* Drain the RX FIFO */
Quoted 8 lines
            if (!priv->rx_buf) {
                reg = readl(&priv->regs->fifo_sta);
                reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
                cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;
                printf("rx fifo: before: %d, ", cnt);
            }

            sun4i_spi_drain_fifo(priv, nbytes);

So it's draining fifo without need to checking the available count insun4i_spi_drain_fifo(), I mean the below code not require.

           /* See how much data is available */
           reg = readl(&priv->regs->fifo_sta);
           reg &= SUN4I_FIFO_STA_RF_CNT_MASK;
           cnt = reg >> SUN4I_FIFO_STA_RF_CNT_BITS;

           if (len > cnt)
                   len = cnt;
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Yes, I didn't made any modification to sun4i_spi_drain_fifo() function:

OK, thanks for the details and test.

Please send the v2 with proper commit head it should be "spi: sun4i: ..." Also I didn't find this patch on patchwork, don't know why?

No idea. I can see it here:
https://patchwork.ozlabs.org/patch/1008181/

OK, got it. I will format the commit and apply if are OK?

Sure. Thank you.