Hi Javier,
On 2014년 11월 18일 22:53, Javier Martinez Canillas wrote:
The Exynos DRM driver register its sub-devices platform drivers in the probe function but after commit 43c0767 ("of/platform: Move platform devices under /sys/devices/platform"), this is causing a deadlock in __driver_attach(). Fix this by moving the platform drivers registration to exynos_drm_init().
Could you re-base this patch on top of exynos-drm-next? I tried to separate sub drivers into independent drivers but it seems that we need more times. So I will merge your patch.
Thanks, Inki Dae
Suggested-by: Andrzej Hajda a.hajda@samsung.com Signed-off-by: Javier Martinez Canillas javier.martinez@collabora.co.uk
This issue was reported by both Krzysztof Kozlowski [0] and Kevin Hilman [1].
Inki Dae said that he will fix it property by separating the Exynos DRM driver in different sub-modules but I post this patch as RFC anyways so others can test if this fixes their boot issue.
drivers/gpu/drm/exynos/exynos_drm_drv.c | 163 ++++++++++++++++---------------- 1 file changed, 79 insertions(+), 84 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index e277d4f..5386fea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -559,15 +559,58 @@ static const struct component_master_ops exynos_drm_ops = { static int exynos_drm_platform_probe(struct platform_device *pdev) { struct component_match *match;
int ret;
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); exynos_drm_driver.num_ioctls = ARRAY_SIZE(exynos_ioctls);
- match = exynos_drm_match_add(&pdev->dev);
- if (IS_ERR(match))
return PTR_ERR(match);
- return component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
match);
+}
+static int exynos_drm_platform_remove(struct platform_device *pdev) +{
- component_master_del(&pdev->dev, &exynos_drm_ops);
- return 0;
+}
+static struct platform_driver exynos_drm_platform_driver = {
- .probe = exynos_drm_platform_probe,
- .remove = exynos_drm_platform_remove,
- .driver = {
.name = "exynos-drm",
.pm = &exynos_drm_pm_ops,
- },
+};
+static int exynos_drm_init(void) +{
- int ret;
- /*
* Register device object only in case of Exynos SoC.
*
* Below codes resolves temporarily infinite loop issue incurred
* by Exynos drm driver when using multi-platform kernel.
* So these codes will be replaced with more generic way later.
*/
- if (!of_machine_is_compatible("samsung,exynos3") &&
!of_machine_is_compatible("samsung,exynos4") &&
!of_machine_is_compatible("samsung,exynos5"))
return -ENODEV;
- exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
NULL, 0);
- if (IS_ERR(exynos_drm_pdev))
return PTR_ERR(exynos_drm_pdev);
#ifdef CONFIG_DRM_EXYNOS_FIMD ret = platform_driver_register(&fimd_driver); if (ret < 0)
return ret;
goto err_unregister_pdev;
#endif
#ifdef CONFIG_DRM_EXYNOS_DP @@ -591,21 +634,10 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) goto err_unregister_mixer_drv; #endif
- match = exynos_drm_match_add(&pdev->dev);
- if (IS_ERR(match)) {
ret = PTR_ERR(match);
goto err_unregister_hdmi_drv;
- }
- ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
match);
- if (ret < 0)
goto err_unregister_hdmi_drv;
#ifdef CONFIG_DRM_EXYNOS_G2D ret = platform_driver_register(&g2d_driver); if (ret < 0)
goto err_del_component_master;
goto err_unregister_hdmi_drv;
#endif
#ifdef CONFIG_DRM_EXYNOS_FIMC @@ -636,9 +668,27 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) goto err_unregister_ipp_drv; #endif
- return ret;
+#ifdef CONFIG_DRM_EXYNOS_VIDI
- ret = exynos_drm_probe_vidi();
- if (ret < 0)
goto err_unregister_ipp_dev;
+#endif
- ret = platform_driver_register(&exynos_drm_platform_driver);
- if (ret)
goto err_remove_vidi;
- return 0;
+err_remove_vidi: +#ifdef CONFIG_DRM_EXYNOS_VIDI
- exynos_drm_remove_vidi();
+err_unregister_pd: +#endif
#ifdef CONFIG_DRM_EXYNOS_IPP +err_unregister_ipp_dev:
- exynos_platform_device_ipp_unregister();
err_unregister_ipp_drv: platform_driver_unregister(&ipp_driver); err_unregister_gsc_drv: @@ -661,11 +711,9 @@ err_unregister_g2d_drv:
#ifdef CONFIG_DRM_EXYNOS_G2D platform_driver_unregister(&g2d_driver); -err_del_component_master: +err_unregister_hdmi_drv: #endif
- component_master_del(&pdev->dev, &exynos_drm_ops);
-err_unregister_hdmi_drv: #ifdef CONFIG_DRM_EXYNOS_HDMI platform_driver_unregister(&hdmi_driver); err_unregister_mixer_drv: @@ -686,11 +734,21 @@ err_unregister_fimd_drv: #ifdef CONFIG_DRM_EXYNOS_FIMD platform_driver_unregister(&fimd_driver); #endif
+err_unregister_pdev:
- platform_device_unregister(exynos_drm_pdev);
- return ret;
}
-static int exynos_drm_platform_remove(struct platform_device *pdev) +static void exynos_drm_exit(void) {
- platform_driver_unregister(&exynos_drm_platform_driver);
+#ifdef CONFIG_DRM_EXYNOS_VIDI
- exynos_drm_remove_vidi();
+#endif
#ifdef CONFIG_DRM_EXYNOS_IPP exynos_platform_device_ipp_unregister(); platform_driver_unregister(&ipp_driver); @@ -721,75 +779,12 @@ static int exynos_drm_platform_remove(struct platform_device *pdev) platform_driver_unregister(&fimd_driver); #endif
-#ifdef CONFIG_DRM_EXYNOS_DSI
- platform_driver_unregister(&dsi_driver);
-#endif
#ifdef CONFIG_DRM_EXYNOS_DP platform_driver_unregister(&dp_driver); #endif
- component_master_del(&pdev->dev, &exynos_drm_ops);
- return 0;
-}
-static struct platform_driver exynos_drm_platform_driver = {
- .probe = exynos_drm_platform_probe,
- .remove = exynos_drm_platform_remove,
- .driver = {
.name = "exynos-drm",
.pm = &exynos_drm_pm_ops,
- },
-};
-static int exynos_drm_init(void) -{
- int ret;
- /*
* Register device object only in case of Exynos SoC.
*
* Below codes resolves temporarily infinite loop issue incurred
* by Exynos drm driver when using multi-platform kernel.
* So these codes will be replaced with more generic way later.
*/
- if (!of_machine_is_compatible("samsung,exynos3") &&
!of_machine_is_compatible("samsung,exynos4") &&
!of_machine_is_compatible("samsung,exynos5"))
return -ENODEV;
- exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
NULL, 0);
- if (IS_ERR(exynos_drm_pdev))
return PTR_ERR(exynos_drm_pdev);
-#ifdef CONFIG_DRM_EXYNOS_VIDI
- ret = exynos_drm_probe_vidi();
- if (ret < 0)
goto err_unregister_pd;
-#endif
- ret = platform_driver_register(&exynos_drm_platform_driver);
- if (ret)
goto err_remove_vidi;
- return 0;
-err_remove_vidi: -#ifdef CONFIG_DRM_EXYNOS_VIDI
- exynos_drm_remove_vidi();
-err_unregister_pd: -#endif
- platform_device_unregister(exynos_drm_pdev);
- return ret;
-}
-static void exynos_drm_exit(void) -{
- platform_driver_unregister(&exynos_drm_platform_driver);
-#ifdef CONFIG_DRM_EXYNOS_VIDI
- exynos_drm_remove_vidi();
+#ifdef CONFIG_DRM_EXYNOS_DSI
- platform_driver_unregister(&dsi_driver);
#endif platform_device_unregister(exynos_drm_pdev); }