MLK-11358-6: dma: imx-sdma: reload context once sdma channel terminated
authorRobin Gong <b38343@freescale.com>
Mon, 17 Aug 2015 09:29:06 +0000 (17:29 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:21:37 +0000 (15:21 -0500)
Some driver may call dmaengine_terminate_all firstly, and then start next by
calling dmaengine_prep_* without dmaengine_slave_config. In this case sdma
transfer failed since no context loaded, take this case in this patch.

Signed-off-by: Robin Gong <b38343@freescale.com>
(cherry picked from commit 51ff948df543dc273fefeb86608e7d6d28ca8090)

drivers/dma/imx-sdma.c

index 7995720..166cff3 100644 (file)
@@ -343,6 +343,7 @@ struct sdma_channel {
        struct imx_dma_data             data;
        unsigned int                    chn_count;
        unsigned int                    chn_real_count;
+       bool                            context_loaded;
        u32                             bd_size_sum;
        bool                            src_dualfifo;
        bool                            dst_dualfifo;
@@ -970,6 +971,9 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        int ret;
        unsigned long flags;
 
+       if (sdmac->context_loaded)
+               return 0;
+
        if (sdmac->direction == DMA_DEV_TO_MEM)
                load_address = sdmac->pc_from_device;
        else if (sdmac->direction == DMA_DEV_TO_DEV)
@@ -1017,6 +1021,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 
        spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
 
+       sdmac->context_loaded = true;
+
        return ret;
 }
 
@@ -1325,6 +1331,7 @@ static int sdma_terminate_all(struct dma_chan *chan)
        spin_unlock_irqrestore(&sdmac->vc.lock, flags);
        vchan_dma_desc_free_list(&sdmac->vc, &head);
        sdma_disable_channel(chan);
+       sdmac->context_loaded = false;
 
        return 0;
 }
@@ -1439,7 +1446,11 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
        if (sdma_alloc_bd(desc))
                goto err_desc_out;
 
+       if (sdma_load_context(sdmac))
+               goto err_desc_out;
+
        return desc;
+
 err_desc_out:
        kfree(desc);
 err_out:
@@ -2200,6 +2211,7 @@ static int sdma_probe(struct platform_device *pdev)
                struct sdma_channel *sdmac = &sdma->channel[i];
 
                sdmac->sdma = sdma;
+               sdmac->context_loaded = false;
                sdmac->channel = i;
                sdmac->status = DMA_IN_PROGRESS;
                sdmac->vc.desc_free = sdma_desc_free;