Message ID | 20200903165717.1272492-3-m.tretter@pengutronix.de |
---|---|
State | New |
Headers | show |
Series | drm/exynos: Convert driver to drm bridge | expand |
Hi On 04.09.2020 11:04, Marek Szyprowski wrote: > On 03.09.2020 18:57, Michael Tretter wrote: >> As the driver shall be usable with drivers that use the component >> framework and drivers that don't, split the common probing code into a >> separate function that can be called from different locations. >> >> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> > > This is the first patch that causes the crash on Exynos boards: > > exynos4-fb 11c00000.fimd: Adding to iommu group 0 > OF: graph: no port node found in /soc/fimd@11c00000 > [drm] Exynos DRM: using 11c00000.fimd device for DMA mapping operations > exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops) > OF: graph: no port node found in /soc/dsi@11c80000 > 8<--- cut here --- > Unable to handle kernel NULL pointer dereference at virtual address > 00000084 > pgd = (ptrval) > [00000084] *pgd=00000000 > Internal error: Oops: 5 [#1] PREEMPT SMP ARM > Modules linked in: > CPU: 1 PID: 1 Comm: swapper/0 Not tainted > 5.9.0-rc2-next-20200824-00004-g680baccba1c2 #1591 > Hardware name: Samsung Exynos (Flattened Device Tree) > PC is at drm_bridge_attach+0x18/0x164 > LR is at exynos_dsi_bind+0x88/0x9c > pc : [<c0620524>] lr : [<c0644df8>] psr: 20000013 > ... > Process swapper/0 (pid: 1, stack limit = 0x(ptrval)) > ... > [<c0620524>] (drm_bridge_attach) from [<c0644df8>] > (exynos_dsi_bind+0x88/0x9c) > [<c0644df8>] (exynos_dsi_bind) from [<c0661aec>] > (component_bind_all+0xfc/0x290) > [<c0661aec>] (component_bind_all) from [<c06413d0>] > (exynos_drm_bind+0xe4/0x19c) > [<c06413d0>] (exynos_drm_bind) from [<c0662060>] > (try_to_bring_up_master+0x1e4/0x2c4) > [<c0662060>] (try_to_bring_up_master) from [<c06625a0>] > (component_master_add_with_match+0xd4/0x108) > [<c06625a0>] (component_master_add_with_match) from [<c06410f8>] > (exynos_drm_platform_probe+0xe4/0x110) > [<c06410f8>] (exynos_drm_platform_probe) from [<c066c788>] > (platform_drv_probe+0x6c/0xa4) > [<c066c788>] (platform_drv_probe) from [<c0669cc4>] > (really_probe+0x200/0x4fc) > [<c0669cc4>] (really_probe) from [<c066a188>] > (driver_probe_device+0x78/0x1fc) > [<c066a188>] (driver_probe_device) from [<c066a570>] > (device_driver_attach+0x58/0x60) > [<c066a570>] (device_driver_attach) from [<c066a654>] > (__driver_attach+0xdc/0x174) > [<c066a654>] (__driver_attach) from [<c0667a4c>] > (bus_for_each_dev+0x68/0xb4) > [<c0667a4c>] (bus_for_each_dev) from [<c0668d80>] > (bus_add_driver+0x158/0x214) > [<c0668d80>] (bus_add_driver) from [<c066b538>] > (driver_register+0x78/0x110) > [<c066b538>] (driver_register) from [<c06412b8>] > (exynos_drm_init+0xe4/0x118) > [<c06412b8>] (exynos_drm_init) from [<c01023f4>] > (do_one_initcall+0x8c/0x424) > [<c01023f4>] (do_one_initcall) from [<c10011a8>] > (kernel_init_freeable+0x190/0x1dc) > [<c10011a8>] (kernel_init_freeable) from [<c0ae8ab4>] > (kernel_init+0x8/0x118) > [<c0ae8ab4>] (kernel_init) from [<c0100114>] (ret_from_fork+0x14/0x20) > Exception stack(0xef0dffb0 to 0xef0dfff8) > ffa0: 00000000 00000000 00000000 > 00000000 > ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 > 00000000 > ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 > Code: e92d4070 0a00002e e3520000 0a000044 (e592c06c) > ---[ end trace 1c93b26d166070f6 ]--- > Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b > CPU0: stopping > CPU: 0 PID: 0 Comm: swapper/0 Tainted: G D > 5.9.0-rc2-next-20200824-00004-g680baccba1c2 #1591 > Hardware name: Samsung Exynos (Flattened Device Tree) > [<c011160c>] (unwind_backtrace) from [<c010cfc0>] (show_stack+0x10/0x14) > [<c010cfc0>] (show_stack) from [<c0533c3c>] (dump_stack+0xbc/0xe8) > [<c0533c3c>] (dump_stack) from [<c01104e0>] (handle_IPI+0x3e0/0x428) > [<c01104e0>] (handle_IPI) from [<c05511dc>] (gic_handle_irq+0x98/0x9c) > [<c05511dc>] (gic_handle_irq) from [<c0100af0>] (__irq_svc+0x70/0xb0) > Exception stack(0xc1101f08 to 0xc1101f50) > 1f00: c01095d8 00000000 00000000 c1100000 c1108eec > c1108f30 > 1f20: 00000001 c107d068 c1108ec8 00000000 00000000 00000000 00005dc0 > c1101f58 > 1f40: c01095d8 c01095dc 60000013 ffffffff > [<c0100af0>] (__irq_svc) from [<c01095dc>] (arch_cpu_idle+0x24/0x44) > [<c01095dc>] (arch_cpu_idle) from [<c01635dc>] (do_idle+0x1bc/0x2bc) > [<c01635dc>] (do_idle) from [<c0163a90>] (cpu_startup_entry+0x18/0x1c) > [<c0163a90>] (cpu_startup_entry) from [<c1000f88>] > (start_kernel+0x628/0x664) > [<c1000f88>] (start_kernel) from [<00000000>] (0x0) > ---[ end Kernel panic - not syncing: Attempted to kill init! > exitcode=0x0000000b ]--- # arm-linux-gnueabi-addr2line -a c0620524 -e vmlinux 0xc0620524 drivers/gpu/drm/drm_bridge.c:184 (discriminator 1) what is: 184: if (previous && (!previous->dev || previous->encoder != encoder)) Best regards
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index b38e9b592b8a..32f999dfd8c1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1734,7 +1734,7 @@ static const struct component_ops exynos_dsi_component_ops = { .unbind = exynos_dsi_unbind, }; -static int exynos_dsi_probe(struct platform_device *pdev) +static struct exynos_dsi *__exynos_dsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; @@ -1743,7 +1743,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); if (!dsi) - return -ENOMEM; + return ERR_PTR(-ENOMEM); /* To be checked as invalid one */ dsi->te_gpio = -ENOENT; @@ -1766,14 +1766,14 @@ static int exynos_dsi_probe(struct platform_device *pdev) if (ret) { if (ret != -EPROBE_DEFER) dev_info(dev, "failed to get regulators: %d\n", ret); - return ret; + return ERR_PTR(ret); } dsi->clks = devm_kcalloc(dev, dsi->driver_data->num_clks, sizeof(*dsi->clks), GFP_KERNEL); if (!dsi->clks) - return -ENOMEM; + return ERR_PTR(-ENOMEM); for (i = 0; i < dsi->driver_data->num_clks; i++) { dsi->clks[i] = devm_clk_get(dev, clk_names[i]); @@ -1787,7 +1787,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) dev_info(dev, "failed to get the clock: %s\n", clk_names[i]); - return PTR_ERR(dsi->clks[i]); + return ERR_PTR(PTR_ERR(dsi->clks[i])); } } @@ -1795,18 +1795,18 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->reg_base = devm_ioremap_resource(dev, res); if (IS_ERR(dsi->reg_base)) { dev_err(dev, "failed to remap io region\n"); - return PTR_ERR(dsi->reg_base); + return dsi->reg_base; } dsi->phy = devm_phy_get(dev, "dsim"); if (IS_ERR(dsi->phy)) { dev_info(dev, "failed to get dsim phy\n"); - return PTR_ERR(dsi->phy); + return ERR_PTR(PTR_ERR(dsi->phy)); } dsi->irq = platform_get_irq(pdev, 0); if (dsi->irq < 0) - return dsi->irq; + return ERR_PTR(dsi->irq); irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN); ret = devm_request_threaded_irq(dev, dsi->irq, NULL, @@ -1814,37 +1814,43 @@ static int exynos_dsi_probe(struct platform_device *pdev) dev_name(dev), dsi); if (ret) { dev_err(dev, "failed to request dsi irq\n"); - return ret; + return ERR_PTR(ret); } ret = exynos_dsi_parse_dt(dsi); if (ret) - return ret; - - platform_set_drvdata(pdev, &dsi->encoder); + return ERR_PTR(ret); pm_runtime_enable(dev); - ret = component_add(dev, &exynos_dsi_component_ops); - if (ret) - goto err_disable_runtime; - - return 0; + return dsi; +} -err_disable_runtime: - pm_runtime_disable(dev); +static void __exynos_dsi_remove(struct exynos_dsi *dsi) +{ of_node_put(dsi->in_bridge_node); - return ret; + pm_runtime_disable(dsi->dev); } -static int exynos_dsi_remove(struct platform_device *pdev) +static int exynos_dsi_probe(struct platform_device *pdev) { - struct exynos_dsi *dsi = platform_get_drvdata(pdev); + struct exynos_dsi *dsi; - of_node_put(dsi->in_bridge_node); + dsi = __exynos_dsi_probe(pdev); + if (IS_ERR(dsi)) + return PTR_ERR(dsi); + platform_set_drvdata(pdev, &dsi->encoder); + + return component_add(&pdev->dev, &exynos_dsi_component_ops); +} + +static int exynos_dsi_remove(struct platform_device *pdev) +{ + struct drm_encoder *encoder = platform_get_drvdata(pdev); + struct exynos_dsi *dsi = encoder_to_dsi(encoder); - pm_runtime_disable(&pdev->dev); + __exynos_dsi_remove(dsi); component_del(&pdev->dev, &exynos_dsi_component_ops);
As the driver shall be usable with drivers that use the component framework and drivers that don't, split the common probing code into a separate function that can be called from different locations. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 54 ++++++++++++++----------- 1 file changed, 30 insertions(+), 24 deletions(-)