diff options
| author | YoungJun Cho <yj44.cho@samsung.com> | 2013-02-12 21:23:54 +0900 | 
|---|---|---|
| committer | Inki Dae <inki.dae@samsung.com> | 2013-02-21 15:00:26 +0900 | 
| commit | 979c0c7eb0fb969f0621c7017a6a87e6a0e36a4c (patch) | |
| tree | 6a59898b626301eee3b25a608082163f6a998299 | |
| parent | 5af9f116e6a0e1de675da979a19f95a74ce2aa2e (diff) | |
drm/exynos: release resources properly when fb creation is failed.
This patch releases allocated resources properly when
exynos_user_fb_create() is failed.
Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
| -rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fb.c | 51 | 
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 31d4cb19736e..0e04f4ea441f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -221,23 +221,25 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,  		      struct drm_mode_fb_cmd2 *mode_cmd)  {  	struct drm_gem_object *obj; +	struct exynos_drm_gem_obj *exynos_gem_obj;  	struct exynos_drm_fb *exynos_fb;  	int i, ret;  	DRM_DEBUG_KMS("%s\n", __FILE__); -	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); -	if (!obj) { -		DRM_ERROR("failed to lookup gem object\n"); -		return ERR_PTR(-ENOENT); -	} -  	exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);  	if (!exynos_fb) {  		DRM_ERROR("failed to allocate exynos drm framebuffer\n");  		return ERR_PTR(-ENOMEM);  	} +	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); +	if (!obj) { +		DRM_ERROR("failed to lookup gem object\n"); +		ret = -ENOENT; +		goto err_free; +	} +  	drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd);  	exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj);  	exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); @@ -245,43 +247,44 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,  	DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt);  	for (i = 1; i < exynos_fb->buf_cnt; i++) { -		struct exynos_drm_gem_obj *exynos_gem_obj; -		int ret; -  		obj = drm_gem_object_lookup(dev, file_priv,  				mode_cmd->handles[i]);  		if (!obj) {  			DRM_ERROR("failed to lookup gem object\n"); -			kfree(exynos_fb); -			return ERR_PTR(-ENOENT); +			ret = -ENOENT; +			exynos_fb->buf_cnt = i; +			goto err_unreference;  		}  		exynos_gem_obj = to_exynos_gem_obj(obj); +		exynos_fb->exynos_gem_obj[i] = exynos_gem_obj;  		ret = check_fb_gem_memory_type(dev, exynos_gem_obj);  		if (ret < 0) {  			DRM_ERROR("cannot use this gem memory type for fb.\n"); -			kfree(exynos_fb); -			return ERR_PTR(ret); +			goto err_unreference;  		} - -		exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj);  	}  	ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);  	if (ret) { -		for (i = 0; i < exynos_fb->buf_cnt; i++) { -			struct exynos_drm_gem_obj *gem_obj; - -			gem_obj = exynos_fb->exynos_gem_obj[i]; -			drm_gem_object_unreference_unlocked(&gem_obj->base); -		} - -		kfree(exynos_fb); -		return ERR_PTR(ret); +		DRM_ERROR("failed to init framebuffer.\n"); +		goto err_unreference;  	}  	return &exynos_fb->fb; + +err_unreference: +	for (i = 0; i < exynos_fb->buf_cnt; i++) { +		struct drm_gem_object *obj; + +		obj = &exynos_fb->exynos_gem_obj[i]->base; +		if (obj) +			drm_gem_object_unreference_unlocked(obj); +	} +err_free: +	kfree(exynos_fb); +	return ERR_PTR(ret);  }  struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,  | 
