spi: spi-zynqmp-gqspi: return -ENOMEM if dma_map_single fails
authorQuanyang Wang <quanyang.wang@windriver.com>
Fri, 16 Apr 2021 00:46:52 +0000 (08:46 +0800)
committerMark Brown <broonie@kernel.org>
Fri, 16 Apr 2021 12:44:15 +0000 (13:44 +0100)
The spi controller supports 44-bit address space on AXI in DMA mode,
so set dma_addr_t width to 44-bit to avoid using a swiotlb mapping.
In addition, if dma_map_single fails, it should return immediately
instead of continuing doing the DMA operation which bases on invalid
address.

This fixes the following crash which occurs in reading a big block
from flash:

[  123.633577] zynqmp-qspi ff0f0000.spi: swiotlb buffer is full (sz: 4194304 bytes), total 32768 (slots), used 0 (slots)
[  123.644230] zynqmp-qspi ff0f0000.spi: ERR:rxdma:memory not mapped
[  123.784625] Unable to handle kernel paging request at virtual address 00000000003fffc0
[  123.792536] Mem abort info:
[  123.795313]   ESR = 0x96000145
[  123.798351]   EC = 0x25: DABT (current EL), IL = 32 bits
[  123.803655]   SET = 0, FnV = 0
[  123.806693]   EA = 0, S1PTW = 0
[  123.809818] Data abort info:
[  123.812683]   ISV = 0, ISS = 0x00000145
[  123.816503]   CM = 1, WnR = 1
[  123.819455] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000805047000
[  123.825887] [00000000003fffc0] pgd=0000000803b45003, p4d=0000000803b45003, pud=0000000000000000
[  123.834586] Internal error: Oops: 96000145 [#1] PREEMPT SMP

Fixes: 1c26372e5aa9 ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework")
Signed-off-by: Quanyang Wang <quanyang.wang@windriver.com>
Link: https://lore.kernel.org/r/20210416004652.2975446-6-quanyang.wang@windriver.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-zynqmp-gqspi.c

index 419bc1e6358b7ad5c0e7266a126f9e63e5904533..328b6559bb19a2f9240f793e58bc746d941e3959 100644 (file)
@@ -733,7 +733,7 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
  * zynqmp_qspi_setuprxdma - This function sets up the RX DMA operation
  * @xqspi:     xqspi is a pointer to the GQSPI instance.
  */
-static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
+static int zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 {
        u32 rx_bytes, rx_rem, config_reg;
        dma_addr_t addr;
@@ -747,7 +747,7 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
                zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
                xqspi->mode = GQSPI_MODE_IO;
                xqspi->dma_rx_bytes = 0;
-               return;
+               return 0;
        }
 
        rx_rem = xqspi->bytes_to_receive % 4;
@@ -755,8 +755,10 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 
        addr = dma_map_single(xqspi->dev, (void *)xqspi->rxbuf,
                              rx_bytes, DMA_FROM_DEVICE);
-       if (dma_mapping_error(xqspi->dev, addr))
+       if (dma_mapping_error(xqspi->dev, addr)) {
                dev_err(xqspi->dev, "ERR:rxdma:memory not mapped\n");
+               return -ENOMEM;
+       }
 
        xqspi->dma_rx_bytes = rx_bytes;
        xqspi->dma_addr = addr;
@@ -777,6 +779,8 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 
        /* Write the number of bytes to transfer */
        zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_SIZE_OFST, rx_bytes);
+
+       return 0;
 }
 
 /**
@@ -813,11 +817,17 @@ static void zynqmp_qspi_write_op(struct zynqmp_qspi *xqspi, u8 tx_nbits,
  * @genfifoentry:      genfifoentry is pointer to the variable in which
  *                     GENFIFO mask is returned to calling function
  */
-static void zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits,
+static int zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits,
                                u32 genfifoentry)
 {
-       zynqmp_qspi_setuprxdma(xqspi);
+       int ret;
+
+       ret = zynqmp_qspi_setuprxdma(xqspi);
+       if (ret)
+               return ret;
        zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry);
+
+       return 0;
 }
 
 /**
@@ -1031,8 +1041,11 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
                        xqspi->rxbuf = (u8 *)op->data.buf.in;
                        xqspi->bytes_to_receive = op->data.nbytes;
                        xqspi->bytes_to_transfer = 0;
-                       zynqmp_qspi_read_op(xqspi, op->data.buswidth,
+                       err = zynqmp_qspi_read_op(xqspi, op->data.buswidth,
                                            genfifoentry);
+                       if (err)
+                               goto return_err;
+
                        zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
                                           zynqmp_gqspi_read
                                           (xqspi, GQSPI_CONFIG_OFST) |
@@ -1159,6 +1172,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
                goto clk_dis_all;
        }
 
+       dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
        ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
        ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;
        ctlr->mem_ops = &zynqmp_qspi_mem_ops;