1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-13 20:01:55 +00:00
openmptcprouter/root/target/linux/bcm27xx/patches-5.15/0506-drm-vc4-Release-workaround-buffer-and-DMA-in-error-p.patch
2021-11-24 18:32:01 +01:00

150 lines
4.6 KiB
Diff

From 8fe39ec43ba5d59b6f88d6a17477a2a1a206483d Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Tue, 6 Jul 2021 18:53:28 +0100
Subject: [PATCH 506/634] drm/vc4: Release workaround buffer and DMA in error
paths and unbind
On Pi0-3 the driver allocates a buffer and requests a DMA channel
because the ARM can't write to DSI1's registers directly.
However unbind and the error paths in bind don't release the buffer or
the DMA channel.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/gpu/drm/vc4/vc4_dsi.c | 51 ++++++++++++++++++++++++++---------
1 file changed, 39 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index e433071bf797..abfa19cc9b45 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1616,7 +1616,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
if (ret != -EPROBE_DEFER)
DRM_ERROR("Failed to get DMA channel: %d\n",
ret);
- return ret;
+ goto err_free_dma_mem;
}
/* Get the physical address of the device's registers. The
@@ -1645,7 +1645,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get interrupt: %d\n", ret);
- return ret;
+ goto err_free_dma;
}
dsi->escape_clock = devm_clk_get(dev, "escape");
@@ -1653,7 +1653,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
ret = PTR_ERR(dsi->escape_clock);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get escape clock: %d\n", ret);
- return ret;
+ goto err_free_dma;
}
dsi->pll_phy_clock = devm_clk_get(dev, "phy");
@@ -1661,7 +1661,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
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 err_free_dma;
}
dsi->pixel_clock = devm_clk_get(dev, "pixel");
@@ -1669,7 +1669,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
ret = PTR_ERR(dsi->pixel_clock);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get pixel clock: %d\n", ret);
- return ret;
+ goto err_free_dma;
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
@@ -1684,33 +1684,37 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
if (ret == -ENODEV)
return 0;
- return ret;
+ goto err_free_dma;
}
if (panel) {
dsi->bridge = devm_drm_panel_bridge_add_typed(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 err_free_dma;
+ }
}
/* 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 err_free_dma;
}
ret = vc4_dsi_init_phy_clocks(dsi);
if (ret)
- return ret;
+ goto err_free_dma;
drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
- if (ret)
- return ret;
+ if (ret) {
+ dev_err(dev, "bridge attach failed: %d\n", ret);
+ goto err_free_dma;
+ }
/* Disable the atomic helper calls into the bridge. We
* manually call the bridge pre_enable / enable / etc. calls
* from our driver, since we need to sequence them within the
@@ -1723,6 +1727,19 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
pm_runtime_enable(dev);
return 0;
+
+err_free_dma:
+ if (dsi->reg_dma_chan) {
+ dma_release_channel(dsi->reg_dma_chan);
+ dsi->reg_dma_chan = NULL;
+ }
+err_free_dma_mem:
+ if (dsi->reg_dma_mem) {
+ dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr);
+ dsi->reg_dma_mem = NULL;
+ }
+
+ return ret;
}
static void vc4_dsi_unbind(struct device *dev, struct device *master,
@@ -1739,6 +1756,16 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
*/
list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
drm_encoder_cleanup(dsi->encoder);
+
+ if (dsi->reg_dma_chan) {
+ dma_release_channel(dsi->reg_dma_chan);
+ dsi->reg_dma_chan = NULL;
+ }
+
+ if (dsi->reg_dma_mem) {
+ dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr);
+ dsi->reg_dma_mem = NULL;
+ }
}
static const struct component_ops vc4_dsi_ops = {
--
2.33.1