spi: rspi: Handle dmaengine_prep_slave_sg() failures gracefully
As typically a shmobile SoC has less DMA channels than devices that can use DMA, we may want to prioritize access to the DMA channels in the future. This means that dmaengine_prep_slave_sg() may start failing arbitrarily. Handle dmaengine_prep_slave_sg() failures gracefully by falling back to PIO. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Родитель
533465a8f8
Коммит
85912a88c1
|
@ -477,7 +477,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
||||||
tx->sgl, tx->nents, DMA_TO_DEVICE,
|
tx->sgl, tx->nents, DMA_TO_DEVICE,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
if (!desc_tx)
|
if (!desc_tx)
|
||||||
return -EIO;
|
goto no_dma;
|
||||||
|
|
||||||
irq_mask |= SPCR_SPTIE;
|
irq_mask |= SPCR_SPTIE;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,7 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
||||||
rx->sgl, rx->nents, DMA_FROM_DEVICE,
|
rx->sgl, rx->nents, DMA_FROM_DEVICE,
|
||||||
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
||||||
if (!desc_rx)
|
if (!desc_rx)
|
||||||
return -EIO;
|
goto no_dma;
|
||||||
|
|
||||||
irq_mask |= SPCR_SPRIE;
|
irq_mask |= SPCR_SPRIE;
|
||||||
}
|
}
|
||||||
|
@ -540,6 +540,12 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
|
||||||
enable_irq(rspi->rx_irq);
|
enable_irq(rspi->rx_irq);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
no_dma:
|
||||||
|
pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
|
||||||
|
dev_driver_string(&rspi->master->dev),
|
||||||
|
dev_name(&rspi->master->dev));
|
||||||
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rspi_receive_init(const struct rspi_data *rspi)
|
static void rspi_receive_init(const struct rspi_data *rspi)
|
||||||
|
@ -593,8 +599,10 @@ static int rspi_common_transfer(struct rspi_data *rspi,
|
||||||
|
|
||||||
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
|
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
|
||||||
/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
|
/* rx_buf can be NULL on RSPI on SH in TX-only Mode */
|
||||||
return rspi_dma_transfer(rspi, &xfer->tx_sg,
|
ret = rspi_dma_transfer(rspi, &xfer->tx_sg,
|
||||||
xfer->rx_buf ? &xfer->rx_sg : NULL);
|
xfer->rx_buf ? &xfer->rx_sg : NULL);
|
||||||
|
if (ret != -EAGAIN)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
|
ret = rspi_pio_transfer(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len);
|
||||||
|
@ -648,8 +656,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
|
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
|
||||||
return rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
|
ret = rspi_dma_transfer(rspi, &xfer->tx_sg, NULL);
|
||||||
|
if (ret != -EAGAIN)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
|
ret = rspi_pio_transfer(rspi, xfer->tx_buf, NULL, xfer->len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -663,8 +674,11 @@ static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer)
|
||||||
|
|
||||||
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
|
static int qspi_transfer_in(struct rspi_data *rspi, struct spi_transfer *xfer)
|
||||||
{
|
{
|
||||||
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer))
|
if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) {
|
||||||
return rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
|
int ret = rspi_dma_transfer(rspi, NULL, &xfer->rx_sg);
|
||||||
|
if (ret != -EAGAIN)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
|
return rspi_pio_transfer(rspi, NULL, xfer->rx_buf, xfer->len);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче