diff options
author | YoungJun Cho <yj44.cho@samsung.com> | 2013-02-12 07:23:54 -0500 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2013-02-21 01:00:26 -0500 |
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, | |||
221 | struct drm_mode_fb_cmd2 *mode_cmd) | 221 | struct drm_mode_fb_cmd2 *mode_cmd) |
222 | { | 222 | { |
223 | struct drm_gem_object *obj; | 223 | struct drm_gem_object *obj; |
224 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
224 | struct exynos_drm_fb *exynos_fb; | 225 | struct exynos_drm_fb *exynos_fb; |
225 | int i, ret; | 226 | int i, ret; |
226 | 227 | ||
227 | DRM_DEBUG_KMS("%s\n", __FILE__); | 228 | DRM_DEBUG_KMS("%s\n", __FILE__); |
228 | 229 | ||
229 | obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); | ||
230 | if (!obj) { | ||
231 | DRM_ERROR("failed to lookup gem object\n"); | ||
232 | return ERR_PTR(-ENOENT); | ||
233 | } | ||
234 | |||
235 | exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); | 230 | exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); |
236 | if (!exynos_fb) { | 231 | if (!exynos_fb) { |
237 | DRM_ERROR("failed to allocate exynos drm framebuffer\n"); | 232 | DRM_ERROR("failed to allocate exynos drm framebuffer\n"); |
238 | return ERR_PTR(-ENOMEM); | 233 | return ERR_PTR(-ENOMEM); |
239 | } | 234 | } |
240 | 235 | ||
236 | obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); | ||
237 | if (!obj) { | ||
238 | DRM_ERROR("failed to lookup gem object\n"); | ||
239 | ret = -ENOENT; | ||
240 | goto err_free; | ||
241 | } | ||
242 | |||
241 | drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); | 243 | drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); |
242 | exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); | 244 | exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); |
243 | exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); | 245 | 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, | |||
245 | DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); | 247 | DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); |
246 | 248 | ||
247 | for (i = 1; i < exynos_fb->buf_cnt; i++) { | 249 | for (i = 1; i < exynos_fb->buf_cnt; i++) { |
248 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
249 | int ret; | ||
250 | |||
251 | obj = drm_gem_object_lookup(dev, file_priv, | 250 | obj = drm_gem_object_lookup(dev, file_priv, |
252 | mode_cmd->handles[i]); | 251 | mode_cmd->handles[i]); |
253 | if (!obj) { | 252 | if (!obj) { |
254 | DRM_ERROR("failed to lookup gem object\n"); | 253 | DRM_ERROR("failed to lookup gem object\n"); |
255 | kfree(exynos_fb); | 254 | ret = -ENOENT; |
256 | return ERR_PTR(-ENOENT); | 255 | exynos_fb->buf_cnt = i; |
256 | goto err_unreference; | ||
257 | } | 257 | } |
258 | 258 | ||
259 | exynos_gem_obj = to_exynos_gem_obj(obj); | 259 | exynos_gem_obj = to_exynos_gem_obj(obj); |
260 | exynos_fb->exynos_gem_obj[i] = exynos_gem_obj; | ||
260 | 261 | ||
261 | ret = check_fb_gem_memory_type(dev, exynos_gem_obj); | 262 | ret = check_fb_gem_memory_type(dev, exynos_gem_obj); |
262 | if (ret < 0) { | 263 | if (ret < 0) { |
263 | DRM_ERROR("cannot use this gem memory type for fb.\n"); | 264 | DRM_ERROR("cannot use this gem memory type for fb.\n"); |
264 | kfree(exynos_fb); | 265 | goto err_unreference; |
265 | return ERR_PTR(ret); | ||
266 | } | 266 | } |
267 | |||
268 | exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); | ||
269 | } | 267 | } |
270 | 268 | ||
271 | ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); | 269 | ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); |
272 | if (ret) { | 270 | if (ret) { |
273 | for (i = 0; i < exynos_fb->buf_cnt; i++) { | 271 | DRM_ERROR("failed to init framebuffer.\n"); |
274 | struct exynos_drm_gem_obj *gem_obj; | 272 | goto err_unreference; |
275 | |||
276 | gem_obj = exynos_fb->exynos_gem_obj[i]; | ||
277 | drm_gem_object_unreference_unlocked(&gem_obj->base); | ||
278 | } | ||
279 | |||
280 | kfree(exynos_fb); | ||
281 | return ERR_PTR(ret); | ||
282 | } | 273 | } |
283 | 274 | ||
284 | return &exynos_fb->fb; | 275 | return &exynos_fb->fb; |
276 | |||
277 | err_unreference: | ||
278 | for (i = 0; i < exynos_fb->buf_cnt; i++) { | ||
279 | struct drm_gem_object *obj; | ||
280 | |||
281 | obj = &exynos_fb->exynos_gem_obj[i]->base; | ||
282 | if (obj) | ||
283 | drm_gem_object_unreference_unlocked(obj); | ||
284 | } | ||
285 | err_free: | ||
286 | kfree(exynos_fb); | ||
287 | return ERR_PTR(ret); | ||
285 | } | 288 | } |
286 | 289 | ||
287 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, | 290 | struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, |