ASoC: Samsung: Protect the dma pointer position access
authorVikas C Sajjan <vikas.sajjan@samsung.com>
Fri, 14 Sep 2012 09:23:35 +0000 (18:23 +0900)
committerGerrit <chrome-bot@google.com>
Thu, 20 Sep 2012 07:16:31 +0000 (00:16 -0700)
Takes spin lock to protect prtd->dma_pos from
concurrent access by the driver and the tasklet

BUG=chrome-os-partner:12565
TEST=ran multimedia tests for audio, video and webgl

Change-Id: I29054e75d01eb7a10401dbc75a17fca13e24ea0e
Signed-off-by: Abhinav Kochhar <abhinav@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/33298
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Tested-by: Vikas Sajjan <vikas.sajjan@samsung.com>
sound/soc/samsung/dma.c

index 154eac5..30250ef 100644 (file)
@@ -119,9 +119,11 @@ static void audio_buffdone(void *data)
        pr_debug("Entered %s\n", __func__);
 
        if (prtd->state & ST_RUNNING) {
+               spin_lock(&prtd->lock);
                prtd->dma_pos += prtd->dma_period;
                if (prtd->dma_pos >= prtd->dma_end)
                        prtd->dma_pos = prtd->dma_start;
+               spin_unlock(&prtd->lock);
 
                if (substream)
                        snd_pcm_period_elapsed(substream);
@@ -271,6 +273,7 @@ dma_pointer(struct snd_pcm_substream *substream)
        struct runtime_data *prtd = runtime->private_data;
        unsigned long offset;
        unsigned long xfd; /* Number of bytes transfered by current dma. */
+       unsigned int ret = 0;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -278,11 +281,14 @@ dma_pointer(struct snd_pcm_substream *substream)
         * more accurate number.  Otherwise, assume no bytes have been
         * transfered.
         */
-       xfd = prtd->dma_period;
        if (prtd->params->ops->residue)
-               xfd -= prtd->params->ops->residue(prtd->params->ch);
+               ret = prtd->params->ops->residue(prtd->params->ch);
+
+       spin_lock(&prtd->lock);
+       xfd = prtd->dma_period - ret;
 
        offset = prtd->dma_pos + xfd - prtd->dma_start;
+       spin_unlock(&prtd->lock);
 
        /* we seem to be getting the odd error from the pcm library due
         * to out-of-bounds pointers. this is maybe due to the dma engine