MLK-12372: ASoC: fsl_asrc: fix dma task timeout after suspend/resume
authorShengjiu Wang <shengjiu.wang@freescale.com>
Mon, 1 Feb 2016 06:44:44 +0000 (14:44 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:50:00 +0000 (14:50 -0500)
commit 743cead0f8c4ac6311ffb500efd6146c40124310 is not a complete fix.
There is low possibility that this issue still occur.

Last commit add init_completion() in the suspend function, but if the
dma callback function is called after convert error, the complete is
done, the init_completion will not be called, so the complete state is
not correct in the next conversion.

This patch is to move init_completion to the beginning of conversion
to fix the issue.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
sound/soc/fsl/fsl_asrc_m2m.c

index 0e5db3d..9ee0f50 100644 (file)
@@ -329,8 +329,6 @@ int fsl_asrc_process_buffer_pre(struct completion *complete,
                return -EBUSY;
        }
 
-       init_completion(complete);
-
        return 0;
 }
 
@@ -351,14 +349,14 @@ int fsl_asrc_process_buffer(struct fsl_asrc_pair *pair,
        int ret;
 
        /* Check input task first */
-       ret = fsl_asrc_process_buffer_pre(&m2m->complete[IN], index, OUT);
+       ret = fsl_asrc_process_buffer_pre(&m2m->complete[IN], index, IN);
        if (ret) {
                mxc_asrc_dma_umap(m2m);
                return ret;
        }
 
        /* ...then output task*/
-       ret = fsl_asrc_process_buffer_pre(&m2m->complete[OUT], index, IN);
+       ret = fsl_asrc_process_buffer_pre(&m2m->complete[OUT], index, OUT);
        if (ret) {
                mxc_asrc_dma_umap(m2m);
                return ret;
@@ -631,6 +629,7 @@ static long fsl_asrc_ioctl_release_pair(struct fsl_asrc_pair *pair,
 static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
                                   void __user *user)
 {
+       struct fsl_asrc_m2m *m2m = pair->private;
        struct fsl_asrc *asrc_priv = pair->asrc_priv;
        enum asrc_pair_index index = pair->index;
        struct asrc_convert_buffer buf;
@@ -648,6 +647,9 @@ static long fsl_asrc_ioctl_convert(struct fsl_asrc_pair *pair,
                return ret;
        }
 
+       init_completion(&m2m->complete[IN]);
+       init_completion(&m2m->complete[OUT]);
+
 #ifdef ASRC_POLLING_WITHOUT_DMA
        fsl_asrc_polling_debug(pair);
 #else
@@ -738,13 +740,9 @@ static long fsl_asrc_ioctl_status(struct fsl_asrc_pair *pair, void __user *user)
 
 static long fsl_asrc_ioctl_flush(struct fsl_asrc_pair *pair, void __user *user)
 {
-       struct fsl_asrc_m2m *m2m = pair->private;
        struct fsl_asrc *asrc_priv = pair->asrc_priv;
        enum asrc_pair_index index = pair->index;
 
-       init_completion(&m2m->complete[IN]);
-       init_completion(&m2m->complete[OUT]);
-
        /* Release DMA and request again */
        dma_release_channel(pair->dma_chan[IN]);
        dma_release_channel(pair->dma_chan[OUT]);
@@ -834,9 +832,6 @@ static int fsl_asrc_open(struct inode *inode, struct file *file)
        pair->private = m2m;
        pair->asrc_priv = asrc_priv;
 
-       init_completion(&m2m->complete[IN]);
-       init_completion(&m2m->complete[OUT]);
-
        spin_lock_init(&m2m->lock);
 
        file->private_data = pair;
@@ -954,13 +949,11 @@ static void fsl_asrc_m2m_suspend(struct fsl_asrc *asrc_priv)
                        if (pair->dma_chan[IN])
                                dmaengine_terminate_all(pair->dma_chan[IN]);
                        fsl_asrc_input_dma_callback((void *)pair);
-                       init_completion(&m2m->complete[IN]);
                }
                if (!completion_done(&m2m->complete[OUT])) {
                        if (pair->dma_chan[OUT])
                                dmaengine_terminate_all(pair->dma_chan[OUT]);
                        fsl_asrc_output_dma_callback((void *)pair);
-                       init_completion(&m2m->complete[OUT]);
                }
 
                spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);