diff mbox series

[02/16] drm/exynos: extract helper functions for probe

Message ID 20200903165717.1272492-3-m.tretter@pengutronix.de (mailing list archive)
State Not Applicable
Headers show
Series drm/exynos: Convert driver to drm bridge | expand

Commit Message

Michael Tretter Sept. 3, 2020, 4:57 p.m. UTC
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(-)

Comments

Marek Szyprowski Sept. 4, 2020, 9:04 a.m. UTC | #1
Hi Michael,

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 ]---

> ---
>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 54 ++++++++++++++-----------
>   1 file changed, 30 insertions(+), 24 deletions(-)
>
> 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);
>   

Best regards
Marek Szyprowski Sept. 4, 2020, 9:21 a.m. UTC | #2
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 mbox series

Patch

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);