lkml.org 
[lkml]   [2021]   [May]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.12 325/677] spi: spi-zynqmp-gqspi: return -ENOMEM if dma_map_single fails
    Date
    From: Quanyang Wang <quanyang.wang@windriver.com>

    [ Upstream commit 126bdb606fd2802454e6048caef1be3e25dd121e ]

    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>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/spi/spi-zynqmp-gqspi.c | 26 ++++++++++++++++++++------
    1 file changed, 20 insertions(+), 6 deletions(-)

    diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
    index 8cd20ff084f4..7162387b9f96 100644
    --- a/drivers/spi/spi-zynqmp-gqspi.c
    +++ b/drivers/spi/spi-zynqmp-gqspi.c
    @@ -731,7 +731,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;
    @@ -745,7 +745,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;
    @@ -753,8 +753,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;
    @@ -775,6 +777,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;
    }

    /**
    @@ -811,11 +815,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;
    }

    /**
    @@ -1029,8 +1039,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) |
    @@ -1157,6 +1170,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;
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-05-12 23:01    [W:2.283 / U:2.764 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site