diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch b/target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch new file mode 100644 index 0000000000..9fd796850f --- /dev/null +++ b/target/linux/bcm27xx/patches-5.4/950-0264-drm-vc4_dsi-Fix-DMA-channel-and-memory-leak-in-vc4-3.patch @@ -0,0 +1,135 @@ +From cbda8e6de54f8a0f194e990f53e1cfad642af1be Mon Sep 17 00:00:00 2001 +From: Chris Miller <chris@mesl2.co.uk> +Date: Wed, 26 Jun 2019 10:40:30 +0100 +Subject: [PATCH] drm: vc4_dsi: Fix DMA channel and memory leak in vc4 + (#3012) + +Signed-off-by: Chris G Miller <chris@creative-electronics.net> +--- + drivers/gpu/drm/vc4/vc4_dsi.c | 35 ++++++++++++++++++++++++----------- + 1 file changed, 24 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_dsi.c ++++ b/drivers/gpu/drm/vc4/vc4_dsi.c +@@ -1485,9 +1485,11 @@ static int vc4_dsi_bind(struct device *d + /* DSI1 has a broken AXI slave that doesn't respond to writes + * from the ARM. It does handle writes from the DMA engine, + * so set up a channel for talking to it. ++ * Where possible managed resource providers are used, but the DMA channel ++ * must - if acquired - be explicitly released prior to taking an error exit path. + */ + if (dsi->port == 1) { +- dsi->reg_dma_mem = dma_alloc_coherent(dev, 4, ++ dsi->reg_dma_mem = dmam_alloc_coherent(dev, 4, + &dsi->reg_dma_paddr, + GFP_KERNEL); + if (!dsi->reg_dma_mem) { +@@ -1506,6 +1508,8 @@ static int vc4_dsi_bind(struct device *d + return ret; + } + ++ /* From here on, any error exits must release the dma channel */ ++ + /* Get the physical address of the device's registers. The + * struct resource for the regs gives us the bus address + * instead. +@@ -1532,7 +1536,7 @@ static int vc4_dsi_bind(struct device *d + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get interrupt: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + + dsi->escape_clock = devm_clk_get(dev, "escape"); +@@ -1540,7 +1544,7 @@ static int vc4_dsi_bind(struct device *d + ret = PTR_ERR(dsi->escape_clock); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get escape clock: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + + dsi->pll_phy_clock = devm_clk_get(dev, "phy"); +@@ -1548,7 +1552,7 @@ static int vc4_dsi_bind(struct device *d + ret = PTR_ERR(dsi->pll_phy_clock); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get phy clock: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + + dsi->pixel_clock = devm_clk_get(dev, "pixel"); +@@ -1556,7 +1560,7 @@ static int vc4_dsi_bind(struct device *d + ret = PTR_ERR(dsi->pixel_clock); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get pixel clock: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, +@@ -1571,26 +1575,28 @@ static int vc4_dsi_bind(struct device *d + if (ret == -ENODEV) + return 0; + +- return ret; ++ goto rel_dma_exit; + } + + if (panel) { + dsi->bridge = devm_drm_panel_bridge_add(dev, panel, + DRM_MODE_CONNECTOR_DSI); +- if (IS_ERR(dsi->bridge)) +- return PTR_ERR(dsi->bridge); ++ if (IS_ERR(dsi->bridge)){ ++ ret = PTR_ERR(dsi->bridge); ++ goto rel_dma_exit; ++ } + } + + /* The esc clock rate is supposed to always be 100Mhz. */ + ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); + if (ret) { + dev_err(dev, "Failed to set esc clock: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + + ret = vc4_dsi_init_phy_clocks(dsi); + if (ret) +- return ret; ++ goto rel_dma_exit; + + if (dsi->port == 1) + vc4->dsi1 = dsi; +@@ -1602,7 +1608,7 @@ static int vc4_dsi_bind(struct device *d + ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL); + if (ret) { + dev_err(dev, "bridge attach failed: %d\n", ret); +- return ret; ++ goto rel_dma_exit; + } + /* Disable the atomic helper calls into the bridge. We + * manually call the bridge pre_enable / enable / etc. calls +@@ -1619,6 +1625,11 @@ static int vc4_dsi_bind(struct device *d + pm_runtime_enable(dev); + + return 0; ++ ++rel_dma_exit: ++ dma_release_channel(dsi->reg_dma_chan); ++ ++ return ret; + } + + static void vc4_dsi_unbind(struct device *dev, struct device *master, +@@ -1633,6 +1644,8 @@ static void vc4_dsi_unbind(struct device + + vc4_dsi_encoder_destroy(dsi->encoder); + ++ dma_release_channel(dsi->reg_dma_chan); ++ + if (dsi->port == 1) + vc4->dsi1 = NULL; + } |