summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2024-02-13 15:51:49 +0100
committerFrancesco Dolcini <francesco.dolcini@toradex.com>2024-02-14 14:05:26 +0000
commit8e1756b1ff622f221235c9235ee59c28dff80a9f (patch)
treee79d9c4a8c79687881fa4041b4b89ee81971e8de
parent67b6c2999005d53a64d97ac79538e3d6d23db2c0 (diff)
drm/imx: imx8qm-ldb: return EPROBE_DEFER in probe
Return EPROBE_DEFER in the probe function if the LDB bridge is missing some of its child bridges. The current implementation returns EPROBE_DEFER in the bind function, which is incorrect because the kernel assumes the driver is fully functional when bind is called. When both HDMI and LVDS is configured the above actually happens in about 20% of the boots, resulting in a kernel backtrace and neither of the two graphical outputs being functional. drm_mode_config_cleanup tries to cleanup a not instantiated device, if one fixes that the next hickup occurs... This commit assures to not take this code path. [ 7.130956] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 7.142436] Modules linked in: crct10dif_ce snd_soc_imx_spdif snd_soc_imx_hdmi mwifiex panel_lvds cfg80211 rfkill ahci_imx atmel_ mxt_ts flexcan can_dev mxc_jpeg_encdec snd_soc_fsl_audmix v4l2_jpeg imx8_media_dev(C) snd_soc_fsl_spdif snd_soc_fsl_asrc snd_soc_fsl _sai cdns_mhdp_imx(+) cdns_mhdp_drmcore caam error galcore fuse [ 7.171161] CPU: 1 PID: 277 Comm: systemd-udevd Tainted: G C 5.15.129-6.5.0-06970-gdc84adb6e1b2-dirty #31 [ 7.182073] Hardware name: Toradex Apalis iMX8QP V1.1 on Apalis Evaluation Board (DT) [ 7.189932] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 7.196905] pc : drm_mode_config_cleanup+0x54/0x300 [ 7.201815] lr : drm_mode_config_init_release+0x10/0x20 [ 7.207079] sp : ffff800009ffb710 [ 7.210411] x29: ffff800009ffb770 x28: ffff000003210550 x27: ffff00001af06a00 [ 7.217582] x26: ffff80000812cdd0 x25: dead000000000122 x24: dead000000000100 [ 7.224748] x23: ffff8000094b7250 x22: ffff00001a9c7810 x21: ffff00001a9c7800 [ 7.231907] x20: ffff00001a9c7aa8 x19: fffffffffffffff8 x18: 0000000000000000 [ 7.239065] x17: ffff8000763e6000 x16: ffff800009c18000 x15: 0000000000000000 [ 7.246222] x14: 0000000000000000 x13: 0000000000000010 x12: 0000000000000001 [ 7.253373] x11: 0000000000000001 x10: 00000000000009e0 x9 : ffff800009bda000 [ 7.260531] x8 : ffff00001ae41c80 x7 : ffff00001a9a9e00 x6 : 0000000000000000 [ 7.267690] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 [ 7.274839] x2 : ffff8000087b58e0 x1 : 0000000000000000 x0 : ffff00001b13a120 [ 7.282000] Call trace: [ 7.284456] drm_mode_config_cleanup+0x54/0x300 [ 7.289008] drm_mode_config_init_release+0x10/0x20 [ 7.293900] drm_managed_release+0xa4/0x13c [ 7.298097] drm_dev_put.part.0+0x90/0xc0 [ 7.302127] drm_dev_put+0x14/0x2c [ 7.305541] imx_drm_bind+0xbc/0x200 [ 7.309129] try_to_bring_up_master+0x214/0x2e0 [ 7.313714] __component_add+0xa0/0x18c ... Upstream-Status: Inappropriate [Other] The upstream imx8qm-ldb driver is a complete rewrite, the bind() calls are not present as part of the driver. Upstream: drivers/gpu/drm/bridge/imx/{imx8qm-ldb-drv.c|imx8qm-ldb.c} Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com>
-rw-r--r--drivers/gpu/drm/imx/imx8qm-ldb.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/imx8qm-ldb.c b/drivers/gpu/drm/imx/imx8qm-ldb.c
index 383c80014fdf..05751505f3de 100644
--- a/drivers/gpu/drm/imx/imx8qm-ldb.c
+++ b/drivers/gpu/drm/imx/imx8qm-ldb.c
@@ -14,6 +14,7 @@
#include <drm/bridge/fsl_imx_ldb.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
@@ -503,6 +504,28 @@ static int imx8qm_ldb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx8qm_ldb *imx8qm_ldb;
+ struct device_node *np = dev->of_node;
+ struct device_node *child;
+ int ret;
+
+ /*
+ * Make sure we can defer already in the probe function else we will
+ * have an issue in the bind function. It is expected that in the bind
+ * function the driver is functional.
+ */
+ for_each_child_of_node(np, child) {
+ struct drm_panel *panel;
+ struct drm_bridge *next_bridge;
+
+ ret = drm_of_find_panel_or_bridge(child, 1, 0,
+ &panel, &next_bridge);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ /*
+ * We can continue even if there is an error, this is most
+ * likely because this driver has not loaded yet
+ */
+ }
imx8qm_ldb = devm_kzalloc(dev, sizeof(*imx8qm_ldb), GFP_KERNEL);
if (!imx8qm_ldb)