Skip to content

Commit

Permalink
spi: spi-zynqmp-gqspi: return -ENOMEM if dma_map_single fails
Browse files Browse the repository at this point in the history
[ Upstream commit 126bdb6 ]

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: 1c26372 ("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>
  • Loading branch information
wqyoung authored and gregkh committed May 14, 2021
1 parent 23269ac commit bad5a23
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions drivers/spi/spi-zynqmp-gqspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -745,16 +745,18 @@ 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;
rx_bytes = (xqspi->bytes_to_receive - rx_rem);

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;
Expand All @@ -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;
}

/**
Expand Down Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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) |
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit bad5a23

Please sign in to comment.