From 61b5d0072a88cfd8c5fda31a7c19d105187c8841 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 20 Mar 2023 16:07:49 +0100 Subject: [PATCH] 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 Reviewed-by: Javier Martinez Canillas Acked-by: Zack Rusin Tested-by: Sui Jingfeng Link: https://patchwork.freedesktop.org/patch/msgid/20230320150751.20399-7-tzimmermann@suse.de --- drivers/gpu/drm/drm_fbdev_generic.c | 40 ++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c index 73834a3..e7eeba0 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, -- 2.7.4