summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_fbdev_generic.c
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 /drivers/gpu/drm/drm_fbdev_generic.c
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
Diffstat (limited to 'drivers/gpu/drm/drm_fbdev_generic.c')
-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,