Skip to content

Commit

Permalink
CHROMIUM: dmaengine: tegra-adma: Fix another race between tasklet/ter…
Browse files Browse the repository at this point in the history
…minate_all

While commit 3706266 ("CHROMIUM: dmaengine: tegra-adma: fix race
between tasklet/terminate_all (take 2)") fixed one of the races between
the ADMA tasklet and tegra_adma_terminate_all(), another one still
remains: the ADMA tasklet (and the DMA callback) may still be running on
another CPU after tegra_adma_terminate_all() returns.  This can result
in a use-after-free in the snd_pcm_release_substream() path when the
context used in the DMA callback (struct snd_pcm_runtime) is freed after
terminating the DMA.  To fix this, kill the ADMA tasklet before
returning from tegra_adma_terminate_all() as long as we're not in the
tasklet itself.

BUG=chrome-os-partner:46247
TEST=Play/stop audio repeatedly on Smaug; no issues seen.

Change-Id: Iaa8f7d53179d254c74abc1a40f1c0ed64c51d60f
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/307104
Reviewed-by: Maneet Singh <mmaneetsingh@nvidia.com>
Reviewed-by: Anatol Pomazau <anatol@google.com>
  • Loading branch information
Andrew Bresticker authored and chrome-bot committed Oct 20, 2015
1 parent 686be12 commit 58148c0
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions drivers/dma/tegra210-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,15 @@ static void tegra_adma_terminate_all(struct dma_chan *dc)
*/
tdc->callback_count = 0;

/* Make sure the tasklet has stopped running before we return. */
if (!in_interrupt()) {
tdc->busy = true;
spin_unlock_irqrestore(&tdc->lock, flags);
tasklet_kill(&tdc->tasklet);
spin_lock_irqsave(&tdc->lock, flags);
tdc->busy = false;
}

spin_unlock_irqrestore(&tdc->lock, flags);
}

Expand Down

0 comments on commit 58148c0

Please sign in to comment.