summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/drm.c
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-11-06 14:12:08 +0100
committerThierry Reding <treding@nvidia.com>2014-11-13 16:14:48 +0100
commit1d1e6fe9b5cd9e51c0b064b60f673a973cac38ba (patch)
tree404e5b43d88a459e749d0a749ff41b6eebf5b9fc /drivers/gpu/drm/tegra/drm.c
parent53ea72132df8dd62bb77b28df7b05074dcea96fe (diff)
downloadop-kernel-dev-1d1e6fe9b5cd9e51c0b064b60f673a973cac38ba.zip
op-kernel-dev-1d1e6fe9b5cd9e51c0b064b60f673a973cac38ba.tar.gz
drm/tegra: Fix error handling cleanup
The DRM driver's ->load() implementation didn't do a good job (no job at all really) cleaning up on failure. Fix that by undoing any prior setup when an error occurs. This requires a bit of rework to make it possible to clean up fbdev midway. This was tested by injecting errors at various points during the initialization sequence and verifying that error cleanup didn't crash and no memory leaked (using kmemleak). Reported-by: Stéphane Marchesin <marcheu@chromium.org> Reported-by: Sean Paul <seanpaul@chromium.org> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra/drm.c')
-rw-r--r--drivers/gpu/drm/tegra/drm.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 59736bb..e1632fb 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -42,13 +42,13 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
err = tegra_drm_fb_prepare(drm);
if (err < 0)
- return err;
+ goto config;
drm_kms_helper_poll_init(drm);
err = host1x_device_init(device);
if (err < 0)
- return err;
+ goto fbdev;
/*
* We don't use the drm_irq_install() helpers provided by the DRM
@@ -59,13 +59,25 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
err = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (err < 0)
- return err;
+ goto device;
err = tegra_drm_fb_init(drm);
if (err < 0)
- return err;
+ goto vblank;
return 0;
+
+vblank:
+ drm_vblank_cleanup(drm);
+device:
+ host1x_device_exit(device);
+fbdev:
+ drm_kms_helper_poll_fini(drm);
+ tegra_drm_fb_free(drm);
+config:
+ drm_mode_config_cleanup(drm);
+ kfree(tegra);
+ return err;
}
static int tegra_drm_unload(struct drm_device *drm)
OpenPOWER on IntegriCloud