457d3d097457ba0bb340cd424e74f54c4dfa3332
[openwrt/staging/blocktrron.git] /
1 From 51f5523151d8de2b1476482e575bb5989e55ba16 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Tue, 6 Jul 2021 18:53:28 +0100
4 Subject: [PATCH] drm/vc4: Release workaround buffer and DMA in error
5 paths and unbind
6
7 On Pi0-3 the driver allocates a buffer and requests a DMA channel
8 because the ARM can't write to DSI1's registers directly.
9 However unbind and the error paths in bind don't release the buffer or
10 the DMA channel.
11
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
13 ---
14 drivers/gpu/drm/vc4/vc4_dsi.c | 51 ++++++++++++++++++++++++++---------
15 1 file changed, 39 insertions(+), 12 deletions(-)
16
17 --- a/drivers/gpu/drm/vc4/vc4_dsi.c
18 +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
19 @@ -1612,7 +1612,7 @@ static int vc4_dsi_bind(struct device *d
20 if (ret != -EPROBE_DEFER)
21 DRM_ERROR("Failed to get DMA channel: %d\n",
22 ret);
23 - return ret;
24 + goto err_free_dma_mem;
25 }
26
27 /* Get the physical address of the device's registers. The
28 @@ -1641,7 +1641,7 @@ static int vc4_dsi_bind(struct device *d
29 if (ret) {
30 if (ret != -EPROBE_DEFER)
31 dev_err(dev, "Failed to get interrupt: %d\n", ret);
32 - return ret;
33 + goto err_free_dma;
34 }
35
36 dsi->escape_clock = devm_clk_get(dev, "escape");
37 @@ -1649,7 +1649,7 @@ static int vc4_dsi_bind(struct device *d
38 ret = PTR_ERR(dsi->escape_clock);
39 if (ret != -EPROBE_DEFER)
40 dev_err(dev, "Failed to get escape clock: %d\n", ret);
41 - return ret;
42 + goto err_free_dma;
43 }
44
45 dsi->pll_phy_clock = devm_clk_get(dev, "phy");
46 @@ -1657,7 +1657,7 @@ static int vc4_dsi_bind(struct device *d
47 ret = PTR_ERR(dsi->pll_phy_clock);
48 if (ret != -EPROBE_DEFER)
49 dev_err(dev, "Failed to get phy clock: %d\n", ret);
50 - return ret;
51 + goto err_free_dma;
52 }
53
54 dsi->pixel_clock = devm_clk_get(dev, "pixel");
55 @@ -1665,7 +1665,7 @@ static int vc4_dsi_bind(struct device *d
56 ret = PTR_ERR(dsi->pixel_clock);
57 if (ret != -EPROBE_DEFER)
58 dev_err(dev, "Failed to get pixel clock: %d\n", ret);
59 - return ret;
60 + goto err_free_dma;
61 }
62
63 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
64 @@ -1680,33 +1680,37 @@ static int vc4_dsi_bind(struct device *d
65 if (ret == -ENODEV)
66 return 0;
67
68 - return ret;
69 + goto err_free_dma;
70 }
71
72 if (panel) {
73 dsi->bridge = devm_drm_panel_bridge_add_typed(dev, panel,
74 DRM_MODE_CONNECTOR_DSI);
75 - if (IS_ERR(dsi->bridge))
76 - return PTR_ERR(dsi->bridge);
77 + if (IS_ERR(dsi->bridge)) {
78 + ret = PTR_ERR(dsi->bridge);
79 + goto err_free_dma;
80 + }
81 }
82
83 /* The esc clock rate is supposed to always be 100Mhz. */
84 ret = clk_set_rate(dsi->escape_clock, 100 * 1000000);
85 if (ret) {
86 dev_err(dev, "Failed to set esc clock: %d\n", ret);
87 - return ret;
88 + goto err_free_dma;
89 }
90
91 ret = vc4_dsi_init_phy_clocks(dsi);
92 if (ret)
93 - return ret;
94 + goto err_free_dma;
95
96 drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
97 drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
98
99 ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
100 - if (ret)
101 - return ret;
102 + if (ret) {
103 + dev_err(dev, "bridge attach failed: %d\n", ret);
104 + goto err_free_dma;
105 + }
106 /* Disable the atomic helper calls into the bridge. We
107 * manually call the bridge pre_enable / enable / etc. calls
108 * from our driver, since we need to sequence them within the
109 @@ -1719,6 +1723,19 @@ static int vc4_dsi_bind(struct device *d
110 pm_runtime_enable(dev);
111
112 return 0;
113 +
114 +err_free_dma:
115 + if (dsi->reg_dma_chan) {
116 + dma_release_channel(dsi->reg_dma_chan);
117 + dsi->reg_dma_chan = NULL;
118 + }
119 +err_free_dma_mem:
120 + if (dsi->reg_dma_mem) {
121 + dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr);
122 + dsi->reg_dma_mem = NULL;
123 + }
124 +
125 + return ret;
126 }
127
128 static void vc4_dsi_unbind(struct device *dev, struct device *master,
129 @@ -1735,6 +1752,16 @@ static void vc4_dsi_unbind(struct device
130 */
131 list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
132 drm_encoder_cleanup(dsi->encoder);
133 +
134 + if (dsi->reg_dma_chan) {
135 + dma_release_channel(dsi->reg_dma_chan);
136 + dsi->reg_dma_chan = NULL;
137 + }
138 +
139 + if (dsi->reg_dma_mem) {
140 + dma_free_coherent(dev, 4, dsi->reg_dma_mem, dsi->reg_dma_paddr);
141 + dsi->reg_dma_mem = NULL;
142 + }
143 }
144
145 static const struct component_ops vc4_dsi_ops = {