summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2018-11-28 16:54:08 +0800
committerBryan O'Donoghue <bryan.odonoghue@linaro.org>2019-01-25 16:14:20 +0000
commit69a144f1e8ad111ae9097918f1cc8bf96bcd3bd9 (patch)
tree5a8beb7ac8cf54cc8deb62b6f5ddea72126ad70f
parentcd4ac14fb733d027115cae81c928bd00702f1e60 (diff)
MLK-20486 drm/imx: ldb: Cleanup enc&conn in ->unbind() if necessary
When the master imx-drm-core binding fails, component_bind_all() in imx-drm-core ->bind() callback will unbind all bound components first and then call drm_mode_config_cleanup(). Since the encoder and connector(located in imx_ldb.imx_ldb_channel) are freed after the ldb ->unbind() callback, drm_mode_config_cleanup() would accidentally access the freed encoder and connector again. To fix this issue, we should cleanup the encoder and connector, i.e., remove them from the global encoder and connector lists, in the ->unbind() callback, so that, drm_mode_config_cleanup() won't find them again in the lists. However, we have to make sure they exist before the cleanup in the ->unbind() callback, because imx-drm-core ->unbind() calls drm_mode_config_cleanup() first and then unbinds all components via component_unbind_all(). Moreover, the connector isn't created at the first place if a bridge exists, so the check before the cleanup makes sense for this reason as well. Signed-off-by: Liu Ying <victor.liu@nxp.com> (cherry picked from commit 6d3fd1316d67ff0e62fae4067b61fd3f2809dfa5)
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 72e612a6b07c..aa51b73ddb02 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -1482,6 +1482,14 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
if (channel->panel)
drm_panel_detach(channel->panel);
+ /* make sure the connector exists, and then cleanup */
+ if (channel->connector.dev)
+ imx_drm_connector_destroy(&channel->connector);
+
+ /* make sure the encoder exists, and then cleanup */
+ if (channel->encoder.dev)
+ imx_drm_encoder_destroy(&channel->encoder);
+
kfree(channel->edid);
i2c_put_adapter(channel->ddc);
}