spi: spi-zynqmp-gqspi: return -ENOMEM if dma_map_single fails
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: 1c26372e5a
("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>
This commit is contained in:
Родитель
a2c5bedb2d
Коммит
126bdb606f
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче