diff options
author | Dave Airlie <airlied@redhat.com> | 2014-11-12 18:09:29 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-11-12 18:09:29 -0500 |
commit | 3b548f4a69b02091031ee60c9a477463f7145963 (patch) | |
tree | 0aabea2387ef8f9e297410e083eb51963fcf1b23 | |
parent | 03dca708521d30153fc5c7e2ff136f780a7372c9 (diff) | |
parent | 7afbfcc9ae6af259351e6fa6b931b1a38b62d9ab (diff) |
Merge branch 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes
Now exynos drm driver incurs infinite loop issue on multi-platform
reported by Matwey V.Korniliv like below,
http://comments.gmane.org/gmane.comp.video.dri.devel/117622
This issue is because non kms drivers enabled are probed before
a component master tries to bring up. This patch set resolves
the infinite loop issue and also includes fixups relevant to exynos
drm internal issues.
* 'exynos-drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
drm/exynos: fix possible infinite loop issue
drm/exynos: g2d: fix null pointer dereference
drm/exynos: resolve infinite loop issue on non multi-platform
drm/exynos: resolve infinite loop issue on multi-platform
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_g2d.c | 9 |
2 files changed, 39 insertions, 19 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index c57466edf45b..e5c4c6c8c967 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -495,6 +495,12 @@ static struct component_match *exynos_drm_match_add(struct device *dev) | |||
495 | 495 | ||
496 | mutex_lock(&drm_component_lock); | 496 | mutex_lock(&drm_component_lock); |
497 | 497 | ||
498 | /* Do not retry to probe if there is no any kms driver regitered. */ | ||
499 | if (list_empty(&drm_component_list)) { | ||
500 | mutex_unlock(&drm_component_lock); | ||
501 | return ERR_PTR(-ENODEV); | ||
502 | } | ||
503 | |||
498 | list_for_each_entry(cdev, &drm_component_list, list) { | 504 | list_for_each_entry(cdev, &drm_component_list, list) { |
499 | /* | 505 | /* |
500 | * Add components to master only in case that crtc and | 506 | * Add components to master only in case that crtc and |
@@ -585,10 +591,21 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) | |||
585 | goto err_unregister_mixer_drv; | 591 | goto err_unregister_mixer_drv; |
586 | #endif | 592 | #endif |
587 | 593 | ||
594 | match = exynos_drm_match_add(&pdev->dev); | ||
595 | if (IS_ERR(match)) { | ||
596 | ret = PTR_ERR(match); | ||
597 | goto err_unregister_hdmi_drv; | ||
598 | } | ||
599 | |||
600 | ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops, | ||
601 | match); | ||
602 | if (ret < 0) | ||
603 | goto err_unregister_hdmi_drv; | ||
604 | |||
588 | #ifdef CONFIG_DRM_EXYNOS_G2D | 605 | #ifdef CONFIG_DRM_EXYNOS_G2D |
589 | ret = platform_driver_register(&g2d_driver); | 606 | ret = platform_driver_register(&g2d_driver); |
590 | if (ret < 0) | 607 | if (ret < 0) |
591 | goto err_unregister_hdmi_drv; | 608 | goto err_del_component_master; |
592 | #endif | 609 | #endif |
593 | 610 | ||
594 | #ifdef CONFIG_DRM_EXYNOS_FIMC | 611 | #ifdef CONFIG_DRM_EXYNOS_FIMC |
@@ -619,23 +636,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) | |||
619 | goto err_unregister_ipp_drv; | 636 | goto err_unregister_ipp_drv; |
620 | #endif | 637 | #endif |
621 | 638 | ||
622 | match = exynos_drm_match_add(&pdev->dev); | ||
623 | if (IS_ERR(match)) { | ||
624 | ret = PTR_ERR(match); | ||
625 | goto err_unregister_resources; | ||
626 | } | ||
627 | |||
628 | ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops, | ||
629 | match); | ||
630 | if (ret < 0) | ||
631 | goto err_unregister_resources; | ||
632 | |||
633 | return ret; | 639 | return ret; |
634 | 640 | ||
635 | err_unregister_resources: | ||
636 | |||
637 | #ifdef CONFIG_DRM_EXYNOS_IPP | 641 | #ifdef CONFIG_DRM_EXYNOS_IPP |
638 | exynos_platform_device_ipp_unregister(); | ||
639 | err_unregister_ipp_drv: | 642 | err_unregister_ipp_drv: |
640 | platform_driver_unregister(&ipp_driver); | 643 | platform_driver_unregister(&ipp_driver); |
641 | err_unregister_gsc_drv: | 644 | err_unregister_gsc_drv: |
@@ -658,9 +661,11 @@ err_unregister_g2d_drv: | |||
658 | 661 | ||
659 | #ifdef CONFIG_DRM_EXYNOS_G2D | 662 | #ifdef CONFIG_DRM_EXYNOS_G2D |
660 | platform_driver_unregister(&g2d_driver); | 663 | platform_driver_unregister(&g2d_driver); |
661 | err_unregister_hdmi_drv: | 664 | err_del_component_master: |
662 | #endif | 665 | #endif |
666 | component_master_del(&pdev->dev, &exynos_drm_ops); | ||
663 | 667 | ||
668 | err_unregister_hdmi_drv: | ||
664 | #ifdef CONFIG_DRM_EXYNOS_HDMI | 669 | #ifdef CONFIG_DRM_EXYNOS_HDMI |
665 | platform_driver_unregister(&hdmi_driver); | 670 | platform_driver_unregister(&hdmi_driver); |
666 | err_unregister_mixer_drv: | 671 | err_unregister_mixer_drv: |
@@ -741,6 +746,18 @@ static int exynos_drm_init(void) | |||
741 | { | 746 | { |
742 | int ret; | 747 | int ret; |
743 | 748 | ||
749 | /* | ||
750 | * Register device object only in case of Exynos SoC. | ||
751 | * | ||
752 | * Below codes resolves temporarily infinite loop issue incurred | ||
753 | * by Exynos drm driver when using multi-platform kernel. | ||
754 | * So these codes will be replaced with more generic way later. | ||
755 | */ | ||
756 | if (!of_machine_is_compatible("samsung,exynos3") && | ||
757 | !of_machine_is_compatible("samsung,exynos4") && | ||
758 | !of_machine_is_compatible("samsung,exynos5")) | ||
759 | return -ENODEV; | ||
760 | |||
744 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, | 761 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, |
745 | NULL, 0); | 762 | NULL, 0); |
746 | if (IS_ERR(exynos_drm_pdev)) | 763 | if (IS_ERR(exynos_drm_pdev)) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index df7a77d3eff8..6ff8599f6cbf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -302,9 +302,12 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d) | |||
302 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; | 302 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; |
303 | 303 | ||
304 | kfree(g2d->cmdlist_node); | 304 | kfree(g2d->cmdlist_node); |
305 | dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE, | 305 | |
306 | g2d->cmdlist_pool_virt, | 306 | if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) { |
307 | g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs); | 307 | dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE, |
308 | g2d->cmdlist_pool_virt, | ||
309 | g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs); | ||
310 | } | ||
308 | } | 311 | } |
309 | 312 | ||
310 | static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d) | 313 | static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d) |