Commit 4f7b0d26 authored by Laurent Pinchart's avatar Laurent Pinchart

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: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
parent 05ee29e9
...@@ -285,7 +285,6 @@ static int rcar_du_remove(struct platform_device *pdev) ...@@ -285,7 +285,6 @@ static int rcar_du_remove(struct platform_device *pdev)
drm_kms_helper_poll_fini(ddev); drm_kms_helper_poll_fini(ddev);
drm_mode_config_cleanup(ddev); drm_mode_config_cleanup(ddev);
drm_vblank_cleanup(ddev);
drm_dev_unref(ddev); drm_dev_unref(ddev);
...@@ -299,7 +298,7 @@ static int rcar_du_probe(struct platform_device *pdev) ...@@ -299,7 +298,7 @@ static int rcar_du_probe(struct platform_device *pdev)
struct resource *mem; struct resource *mem;
int ret; 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); rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
if (rcdu == NULL) if (rcdu == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -309,31 +308,22 @@ static int rcar_du_probe(struct platform_device *pdev) ...@@ -309,31 +308,22 @@ static int rcar_du_probe(struct platform_device *pdev)
rcdu->dev = &pdev->dev; rcdu->dev = &pdev->dev;
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; 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); platform_set_drvdata(pdev, rcdu);
/* I/O resources */ /* I/O resources */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rcdu->mmio)) { if (IS_ERR(rcdu->mmio))
ret = PTR_ERR(rcdu->mmio); return 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;
/* DRM/KMS objects */ /* 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); ret = rcar_du_modeset_init(rcdu);
if (ret < 0) { if (ret < 0) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
......
...@@ -559,6 +559,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) ...@@ -559,6 +559,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
if (ret < 0) if (ret < 0)
return ret; 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. */ /* Initialize the groups. */
num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment