[RFC PATCH 1/1] drm/exynos: Move platform drivers registration to module init
Inki Dae
inki.dae at samsung.com
Thu Nov 20 06:07:20 PST 2014
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 at samsung.com>
> Signed-off-by: Javier Martinez Canillas <javier.martinez at 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.
>
> [0]: https://lkml.org/lkml/2014/11/6/125
> [1]: http://www.spinics.net/lists/linux-samsung-soc/msg39050.html
>
> 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);
> }
>
More information about the dri-devel
mailing list