summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2023-03-20 18:07:49 +0300
committerThomas Zimmermann <tzimmermann@suse.de>2023-03-22 15:32:52 +0300
commit61b5d0072a88cfd8c5fda31a7c19d105187c8841 (patch)
treeb7e6b1409c56a6f41faf72683188f8fa06761e1a
parent8fbc9af55de0b274745e70118e20e0964e98bb05 (diff)
downloadlinux-61b5d0072a88cfd8c5fda31a7c19d105187c8841.tar.xz
drm/fbdev-generic: Clean up after failed probing
Clean up fbdev and client state if the probe function fails. It used to leak allocated resources. Also reorder the individual steps to simplify cleanup. v2: * move screen_size update into separate patches Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Acked-by: Zack Rusin <zackr@vmware.com> Tested-by: Sui Jingfeng <suijingfeng@loongson.cn> Link: https://patchwork.freedesktop.org/patch/msgid/20230320150751.20399-7-tzimmermann@suse.de
-rw-r--r--drivers/gpu/drm/drm_fbdev_generic.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
index 73834a3cc6b0..e7eeba0c44b4 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -77,6 +77,7 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_client_buffer *buffer;
struct fb_info *info;
size_t screen_size;
+ void *screen_buffer;
u32 format;
int ret;
@@ -92,36 +93,51 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->buffer = buffer;
fb_helper->fb = buffer->fb;
+
screen_size = buffer->gem->size;
+ screen_buffer = vzalloc(screen_size);
+ if (!screen_buffer) {
+ ret = -ENOMEM;
+ goto err_drm_client_framebuffer_delete;
+ }
info = drm_fb_helper_alloc_info(fb_helper);
- if (IS_ERR(info))
- return PTR_ERR(info);
+ if (IS_ERR(info)) {
+ ret = PTR_ERR(info);
+ goto err_vfree;
+ }
+
+ drm_fb_helper_fill_info(info, fb_helper, sizes);
info->fbops = &drm_fbdev_fb_ops;
- info->screen_size = screen_size;
- info->fix.smem_len = screen_size;
info->flags = FBINFO_DEFAULT;
- drm_fb_helper_fill_info(info, fb_helper, sizes);
-
- info->screen_buffer = vzalloc(screen_size);
- if (!info->screen_buffer)
- return -ENOMEM;
+ /* screen */
info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
-
+ info->screen_buffer = screen_buffer;
info->fix.smem_start = page_to_phys(vmalloc_to_page(info->screen_buffer));
+ info->fix.smem_len = screen_size;
- /* Set a default deferred I/O handler */
+ /* deferred I/O */
fb_helper->fbdefio.delay = HZ / 20;
fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
info->fbdefio = &fb_helper->fbdefio;
ret = fb_deferred_io_init(info);
if (ret)
- return ret;
+ goto err_drm_fb_helper_release_info;
return 0;
+
+err_drm_fb_helper_release_info:
+ drm_fb_helper_release_info(fb_helper);
+err_vfree:
+ vfree(screen_buffer);
+err_drm_client_framebuffer_delete:
+ fb_helper->fb = NULL;
+ fb_helper->buffer = NULL;
+ drm_client_framebuffer_delete(buffer);
+ return ret;
}
static void drm_fbdev_damage_blit_real(struct drm_fb_helper *fb_helper,