Browse Source

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>
Laurent Pinchart 9 years ago
parent
commit
4f7b0d2638
2 changed files with 17 additions and 20 deletions
  1. 10 20
      drivers/gpu/drm/rcar-du/rcar_du_drv.c
  2. 7 0
      drivers/gpu/drm/rcar-du/rcar_du_kms.c

+ 10 - 20
drivers/gpu/drm/rcar-du/rcar_du_drv.c

@@ -285,7 +285,6 @@ static int rcar_du_remove(struct platform_device *pdev)
 
 	drm_kms_helper_poll_fini(ddev);
 	drm_mode_config_cleanup(ddev);
-	drm_vblank_cleanup(ddev);
 
 	drm_dev_unref(ddev);
 
@@ -299,7 +298,7 @@ static int rcar_du_probe(struct platform_device *pdev)
 	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;
@@ -309,31 +308,22 @@ static int rcar_du_probe(struct platform_device *pdev)
 	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)

+ 7 - 0
drivers/gpu/drm/rcar-du/rcar_du_kms.c

@@ -559,6 +559,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 	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);