dmaengine i.MX SDMA: lock channel 0
[firefly-linux-kernel-4.4.55.git] / drivers / dma / imx-sdma.c
index 7bd7e98548cd34e495910f093ee44e821c1de67b..f50c87c303dd5164fd115c0d94db9e2b6b7f49b1 100644 (file)
@@ -318,6 +318,7 @@ struct sdma_engine {
        dma_addr_t                      context_phys;
        struct dma_device               dma_device;
        struct clk                      *clk;
+       struct mutex                    channel_0_lock;
        struct sdma_script_start_addrs  *script_addrs;
 };
 
@@ -415,11 +416,15 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
        dma_addr_t buf_phys;
        int ret;
 
+       mutex_lock(&sdma->channel_0_lock);
+
        buf_virt = dma_alloc_coherent(NULL,
                        size,
                        &buf_phys, GFP_KERNEL);
-       if (!buf_virt)
-               return -ENOMEM;
+       if (!buf_virt) {
+               ret = -ENOMEM;
+               goto err_out;
+       }
 
        bd0->mode.command = C0_SETPM;
        bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
@@ -433,6 +438,9 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
 
        dma_free_coherent(NULL, size, buf_virt, buf_phys);
 
+err_out:
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -656,6 +664,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
        dev_dbg(sdma->dev, "event_mask0 = 0x%08x\n", sdmac->event_mask0);
        dev_dbg(sdma->dev, "event_mask1 = 0x%08x\n", sdmac->event_mask1);
 
+       mutex_lock(&sdma->channel_0_lock);
+
        memset(context, 0, sizeof(*context));
        context->channel_state.pc = load_address;
 
@@ -676,6 +686,8 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 
        ret = sdma_run_channel(&sdma->channel[0]);
 
+       mutex_unlock(&sdma->channel_0_lock);
+
        return ret;
 }
 
@@ -1274,6 +1286,8 @@ static int __init sdma_probe(struct platform_device *pdev)
        if (!sdma)
                return -ENOMEM;
 
+       mutex_init(&sdma->channel_0_lock);
+
        sdma->dev = &pdev->dev;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);