| From 37d328371b31dc50f6ee3d511c232cccc6effe97 Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Wed, 19 Oct 2016 00:51:35 +0300 |
| Subject: [PATCH 049/299] drm: rcar-du: Simplify and fix probe error handling |
| |
| It isn't safe to call drm_dev_unregister() without first initializing |
| mode setting with drm_mode_config_init(). This leads to a crash if |
| either IO memory can't be remapped or vblank initialization fails. |
| |
| Fix this by reordering the initialization sequence. Move vblank |
| initialization after the drm_mode_config_init() call, and move IO |
| remapping before drm_dev_alloc() to avoid the need to perform clean up |
| in case of failure. |
| |
| While at it remove the explicit drm_vblank_cleanup() call from |
| rcar_du_remove() as the drm_dev_unregister() function already cleans up |
| vblank. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| (cherry picked from commit 4f7b0d263833928e947e172eff2d2997179c5cb9) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 ++++++++++-------------------- |
| drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 +++++++ |
| 2 files changed, 17 insertions(+), 20 deletions(-) |
| |
| --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c |
| +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c |
| @@ -283,7 +283,6 @@ static int rcar_du_remove(struct platfor |
| |
| drm_kms_helper_poll_fini(ddev); |
| drm_mode_config_cleanup(ddev); |
| - drm_vblank_cleanup(ddev); |
| |
| drm_dev_unref(ddev); |
| |
| @@ -297,7 +296,7 @@ static int rcar_du_probe(struct platform |
| struct resource *mem; |
| int ret; |
| |
| - /* Allocate and initialize the DRM and R-Car device structures. */ |
| + /* Allocate and initialize the R-Car device structure. */ |
| rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); |
| if (rcdu == NULL) |
| return -ENOMEM; |
| @@ -307,31 +306,22 @@ static int rcar_du_probe(struct platform |
| rcdu->dev = &pdev->dev; |
| rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; |
| |
| - ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); |
| - if (IS_ERR(ddev)) |
| - return PTR_ERR(ddev); |
| - |
| - rcdu->ddev = ddev; |
| - ddev->dev_private = rcdu; |
| - |
| platform_set_drvdata(pdev, rcdu); |
| |
| /* I/O resources */ |
| mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); |
| - if (IS_ERR(rcdu->mmio)) { |
| - ret = PTR_ERR(rcdu->mmio); |
| - goto error; |
| - } |
| - |
| - /* Initialize vertical blanking interrupts handling. Start with vblank |
| - * disabled for all CRTCs. |
| - */ |
| - ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1); |
| - if (ret < 0) |
| - goto error; |
| + if (IS_ERR(rcdu->mmio)) |
| + return PTR_ERR(rcdu->mmio); |
| |
| /* DRM/KMS objects */ |
| + ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); |
| + if (IS_ERR(ddev)) |
| + return PTR_ERR(ddev); |
| + |
| + rcdu->ddev = ddev; |
| + ddev->dev_private = rcdu; |
| + |
| ret = rcar_du_modeset_init(rcdu); |
| if (ret < 0) { |
| if (ret != -EPROBE_DEFER) |
| --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c |
| +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c |
| @@ -568,6 +568,13 @@ int rcar_du_modeset_init(struct rcar_du_ |
| if (ret < 0) |
| return ret; |
| |
| + /* Initialize vertical blanking interrupts handling. Start with vblank |
| + * disabled for all CRTCs. |
| + */ |
| + ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); |
| + if (ret < 0) |
| + return ret; |
| + |
| /* Initialize the groups. */ |
| num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); |
| |