Fix a simple bug which can limits its transfer size,
and add a simple helper function for code cleanups.

Fixes: a59b2c7c56bf ("spi: spi-mtk-nor: support standard spi properties")
Signed-off-by: Ikjoon Jang <[email protected]>

---

(no changes since v1)

 drivers/spi/spi-mtk-nor.c | 62 ++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c
index 6e6ca2b8e6c8..54b2c0fde95b 100644
--- a/drivers/spi/spi-mtk-nor.c
+++ b/drivers/spi/spi-mtk-nor.c
@@ -167,52 +167,63 @@ static bool mtk_nor_match_read(const struct spi_mem_op 
*op)
        return false;
 }
 
-static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+static bool need_bounce(void *cpu_addr, unsigned long len)
 {
-       size_t len;
+       return !!(((uintptr_t)cpu_addr) & MTK_NOR_DMA_ALIGN_MASK);
+}
 
+static int mtk_nor_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
        if (!op->data.nbytes)
                return 0;
 
        if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
-               if ((op->data.dir == SPI_MEM_DATA_IN) &&
-                   mtk_nor_match_read(op)) {
+               switch (op->data.dir) {
+               case SPI_MEM_DATA_IN:
+                       if (!mtk_nor_match_read(op))
+                               return -EINVAL;
+                       /* check if it's DMAable */
                        if ((op->addr.val & MTK_NOR_DMA_ALIGN_MASK) ||
-                           (op->data.nbytes < MTK_NOR_DMA_ALIGN))
+                           (op->data.nbytes < MTK_NOR_DMA_ALIGN)) {
                                op->data.nbytes = 1;
-                       else if (!((ulong)(op->data.buf.in) &
-                                  MTK_NOR_DMA_ALIGN_MASK))
+                       } else {
+                               if (need_bounce(op->data.buf.in, 
op->data.nbytes) &&
+                                   (op->data.nbytes > MTK_NOR_BOUNCE_BUF_SIZE))
+                                       op->data.nbytes = 
MTK_NOR_BOUNCE_BUF_SIZE;
                                op->data.nbytes &= ~MTK_NOR_DMA_ALIGN_MASK;
-                       else if (op->data.nbytes > MTK_NOR_BOUNCE_BUF_SIZE)
-                               op->data.nbytes = MTK_NOR_BOUNCE_BUF_SIZE;
-                       return 0;
-               } else if (op->data.dir == SPI_MEM_DATA_OUT) {
+                       }
+                       break;
+               case SPI_MEM_DATA_OUT:
                        if (op->data.nbytes >= MTK_NOR_PP_SIZE)
                                op->data.nbytes = MTK_NOR_PP_SIZE;
                        else
                                op->data.nbytes = 1;
-                       return 0;
+                       break;
+               default:
+                       break;
                }
+       } else {
+               u8 len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
+
+               if (len > MTK_NOR_PRG_MAX_SIZE)
+                       return -EINVAL;
+               if (op->data.nbytes && !(MTK_NOR_PRG_MAX_SIZE - len))
+                       return -EINVAL;
+               if (op->data.nbytes > (MTK_NOR_PRG_MAX_SIZE - len))
+                       op->data.nbytes = MTK_NOR_PRG_MAX_SIZE - len;
        }
 
-       len = MTK_NOR_PRG_MAX_SIZE - op->cmd.nbytes - op->addr.nbytes -
-             op->dummy.nbytes;
-       if (op->data.nbytes > len)
-               op->data.nbytes = len;
-
        return 0;
 }
 
 static bool mtk_nor_supports_op(struct spi_mem *mem,
                                const struct spi_mem_op *op)
 {
-       size_t len;
-
        if (op->cmd.buswidth != 1)
                return false;
 
        if ((op->addr.nbytes == 3) || (op->addr.nbytes == 4)) {
-               switch(op->data.dir) {
+               switch (op->data.dir) {
                case SPI_MEM_DATA_IN:
                        if (!mtk_nor_match_read(op))
                                return false;
@@ -226,11 +237,14 @@ static bool mtk_nor_supports_op(struct spi_mem *mem,
                default:
                        break;
                }
+       } else {
+               u8 len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
+
+               if (len > MTK_NOR_PRG_MAX_SIZE)
+                       return false;
+               if (op->data.nbytes && !(MTK_NOR_PRG_MAX_SIZE - len))
+                       return false;
        }
-       len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
-       if ((len > MTK_NOR_PRG_MAX_SIZE) ||
-           ((op->data.nbytes) && (len == MTK_NOR_PRG_MAX_SIZE)))
-               return false;
 
        return spi_mem_default_supports_op(mem, op);
 }
-- 
2.28.0.681.g6f77f65b4e-goog

Reply via email to