Commit 1513ceee authored by Lukas Wunner's avatar Lukas Wunner Committed by Mark Brown

spi: bcm2835: Drop dma_pending flag

The BCM2835 SPI driver uses a flag to keep track of whether a DMA
transfer is in progress.

The flag is used to avoid terminating DMA channels multiple times if a
transfer finishes orderly while simultaneously the SPI core invokes the
->handle_err() callback because the transfer took too long.  However
terminating DMA channels multiple times is perfectly fine, so the flag
is unnecessary for this particular purpose.

The flag is also used to avoid invoking bcm2835_spi_undo_prologue()
multiple times under this race condition.  However multiple *concurrent*
invocations can no longer happen since commit 2527704d ("spi:
bcm2835: Synchronize with callback on DMA termination") because the
->handle_err() callback now uses the _sync() variant when terminating
DMA channels.

The only raison d'être of the flag is therefore that
bcm2835_spi_undo_prologue() cannot cope with multiple *sequential*
invocations.  Achieve that by setting tx_prologue to 0 at the end of
the function.  Subsequent invocations thus become no-ops.

With that, the dma_pending flag becomes unnecessary, so drop it.
Tested-by: default avatarNuno Sá <nuno.sa@analog.com>
Tested-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Signed-off-by: default avatarLukas Wunner <lukas@wunner.de>
Acked-by: default avatarStefan Wahren <wahrenst@gmx.net>
Acked-by: default avatarMartin Sperl <kernel@martin.sperl.org>
Link: https://lore.kernel.org/r/062b03b7f86af77a13ce0ec3b22e0bdbfcfba10d.1568187525.git.lukas@wunner.deSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8995673e
...@@ -94,7 +94,6 @@ MODULE_PARM_DESC(polling_limit_us, ...@@ -94,7 +94,6 @@ MODULE_PARM_DESC(polling_limit_us,
* @rx_prologue: bytes received without DMA if first RX sglist entry's * @rx_prologue: bytes received without DMA if first RX sglist entry's
* length is not a multiple of 4 (to overcome hardware limitation) * length is not a multiple of 4 (to overcome hardware limitation)
* @tx_spillover: whether @tx_prologue spills over to second TX sglist entry * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry
* @dma_pending: whether a DMA transfer is in progress
* @debugfs_dir: the debugfs directory - neede to remove debugfs when * @debugfs_dir: the debugfs directory - neede to remove debugfs when
* unloading the module * unloading the module
* @count_transfer_polling: count of how often polling mode is used * @count_transfer_polling: count of how often polling mode is used
...@@ -117,7 +116,6 @@ struct bcm2835_spi { ...@@ -117,7 +116,6 @@ struct bcm2835_spi {
int tx_prologue; int tx_prologue;
int rx_prologue; int rx_prologue;
unsigned int tx_spillover; unsigned int tx_spillover;
unsigned int dma_pending;
struct dentry *debugfs_dir; struct dentry *debugfs_dir;
u64 count_transfer_polling; u64 count_transfer_polling;
...@@ -541,6 +539,8 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) ...@@ -541,6 +539,8 @@ static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs)
sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4;
sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; sg_dma_len(&tfr->tx_sg.sgl[1]) += 4;
} }
bs->tx_prologue = 0;
} }
static void bcm2835_spi_dma_done(void *data) static void bcm2835_spi_dma_done(void *data)
...@@ -556,10 +556,8 @@ static void bcm2835_spi_dma_done(void *data) ...@@ -556,10 +556,8 @@ static void bcm2835_spi_dma_done(void *data)
* is called the tx-dma must have finished - can't get to this * is called the tx-dma must have finished - can't get to this
* situation otherwise... * situation otherwise...
*/ */
if (cmpxchg(&bs->dma_pending, true, false)) { dmaengine_terminate_async(ctlr->dma_tx);
dmaengine_terminate_async(ctlr->dma_tx); bcm2835_spi_undo_prologue(bs);
bcm2835_spi_undo_prologue(bs);
}
/* and mark as completed */; /* and mark as completed */;
complete(&ctlr->xfer_completion); complete(&ctlr->xfer_completion);
...@@ -634,9 +632,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, ...@@ -634,9 +632,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
/* start TX early */ /* start TX early */
dma_async_issue_pending(ctlr->dma_tx); dma_async_issue_pending(ctlr->dma_tx);
/* mark as dma pending */
bs->dma_pending = 1;
/* set the DMA length */ /* set the DMA length */
bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len);
...@@ -652,7 +647,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, ...@@ -652,7 +647,6 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr,
if (ret) { if (ret) {
/* need to reset on errors */ /* need to reset on errors */
dmaengine_terminate_sync(ctlr->dma_tx); dmaengine_terminate_sync(ctlr->dma_tx);
bs->dma_pending = false;
goto err_reset_hw; goto err_reset_hw;
} }
...@@ -917,11 +911,10 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr, ...@@ -917,11 +911,10 @@ static void bcm2835_spi_handle_err(struct spi_controller *ctlr,
struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
/* if an error occurred and we have an active dma, then terminate */ /* if an error occurred and we have an active dma, then terminate */
if (cmpxchg(&bs->dma_pending, true, false)) { dmaengine_terminate_sync(ctlr->dma_tx);
dmaengine_terminate_sync(ctlr->dma_tx); dmaengine_terminate_sync(ctlr->dma_rx);
dmaengine_terminate_sync(ctlr->dma_rx); bcm2835_spi_undo_prologue(bs);
bcm2835_spi_undo_prologue(bs);
}
/* and reset */ /* and reset */
bcm2835_spi_reset_hw(ctlr); bcm2835_spi_reset_hw(ctlr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment