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:
Geert Uytterhoeven 2014-07-09 12:26:22 +02:00 committed by Mark Brown
parent 533465a8f8
commit 85912a88c1

View File

@ -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);
} }