Revert "dmaengine: imx-sdma: Fix memory leak"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Feb 2020 09:45:54 +0000 (10:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Feb 2020 16:22:24 +0000 (17:22 +0100)
This reverts commit 8a7aa4feeaeabc12181e1997a298eb73d2ed2d65 which is
commit 02939cd167095f16328a1bd5cab5a90b550606df upstream.

Andreas writes:
This patch breaks our imx6 board with the attached trace.
Reverting the patch makes it boot again.

Reported-by: Andreas Tobler <andreas.tobler@onway.ch>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Robin Gong <yibin.gong@nxp.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/dma/imx-sdma.c

index 66f1b2a..c27e206 100644 (file)
@@ -760,8 +760,12 @@ static void sdma_start_desc(struct sdma_channel *sdmac)
                return;
        }
        sdmac->desc = desc = to_sdma_desc(&vd->tx);
-
-       list_del(&vd->node);
+       /*
+        * Do not delete the node in desc_issued list in cyclic mode, otherwise
+        * the desc allocated will never be freed in vchan_dma_desc_free_list
+        */
+       if (!(sdmac->flags & IMX_DMA_SG_LOOP))
+               list_del(&vd->node);
 
        sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
        sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
@@ -1067,6 +1071,7 @@ static void sdma_channel_terminate_work(struct work_struct *work)
 
        spin_lock_irqsave(&sdmac->vc.lock, flags);
        vchan_get_all_descriptors(&sdmac->vc, &head);
+       sdmac->desc = NULL;
        spin_unlock_irqrestore(&sdmac->vc.lock, flags);
        vchan_dma_desc_free_list(&sdmac->vc, &head);
        sdmac->context_loaded = false;
@@ -1075,19 +1080,11 @@ static void sdma_channel_terminate_work(struct work_struct *work)
 static int sdma_disable_channel_async(struct dma_chan *chan)
 {
        struct sdma_channel *sdmac = to_sdma_chan(chan);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdmac->vc.lock, flags);
 
        sdma_disable_channel(chan);
 
-       if (sdmac->desc) {
-               vchan_terminate_vdesc(&sdmac->desc->vd);
-               sdmac->desc = NULL;
+       if (sdmac->desc)
                schedule_work(&sdmac->terminate_worker);
-       }
-
-       spin_unlock_irqrestore(&sdmac->vc.lock, flags);
 
        return 0;
 }