Commit 63c971af authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

drm/fb-helper: Allocate and release fb_info in single place



Move the calls to drm_fb_helper_alloc_info() from drivers into a
single place in fbdev helpers. Allocates struct fb_info for a new
framebuffer device. Then call drm_fb_helper_single_fb_probe() to
create an fbdev screen buffer. Also release the instance on errors
by calling drm_fb_helper_release_info().

Simplifies the code and fixes the error cleanup for some of the
drivers.

Regular release of the struct fb_info instance still happens in
drm_fb_helper_fini() as before.

v2:
- remove error rollback in driver implementations (kernel test robot)
- initialize info in TTM implementation (kernel test robot)

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: Christian König <christian.koenig@amd.com> # radeon
Acked-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> # msm
Acked-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://patch.msgid.link/20251027081245.80262-1-tzimmermann@suse.de
parent ac364014
Loading
Loading
Loading
Loading
+1 −11
Original line number Diff line number Diff line
@@ -44,10 +44,10 @@ int armada_fbdev_driver_fbdev_probe(struct drm_fb_helper *fbh,
				    struct drm_fb_helper_surface_size *sizes)
{
	struct drm_device *dev = fbh->dev;
	struct fb_info *info = fbh->info;
	struct drm_mode_fb_cmd2 mode;
	struct armada_framebuffer *dfb;
	struct armada_gem_object *obj;
	struct fb_info *info;
	int size, ret;
	void *ptr;

@@ -91,12 +91,6 @@ int armada_fbdev_driver_fbdev_probe(struct drm_fb_helper *fbh,
	if (IS_ERR(dfb))
		return PTR_ERR(dfb);

	info = drm_fb_helper_alloc_info(fbh);
	if (IS_ERR(info)) {
		ret = PTR_ERR(info);
		goto err_fballoc;
	}

	info->fbops = &armada_fb_ops;
	info->fix.smem_start = obj->phys_addr;
	info->fix.smem_len = obj->obj.size;
@@ -112,8 +106,4 @@ int armada_fbdev_driver_fbdev_probe(struct drm_fb_helper *fbh,
		(unsigned long long)obj->phys_addr);

	return 0;

 err_fballoc:
	dfb->fb.funcs->destroy(&dfb->fb);
	return ret;
}
+12 −27
Original line number Diff line number Diff line
@@ -459,20 +459,7 @@ int drm_fb_helper_init(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_fb_helper_init);

/**
 * drm_fb_helper_alloc_info - allocate fb_info and some of its members
 * @fb_helper: driver-allocated fbdev helper
 *
 * A helper to alloc fb_info and the member cmap. Called by the driver
 * within the struct &drm_driver.fbdev_probe callback function. Drivers do
 * not need to release the allocated fb_info structure themselves, this is
 * automatically done when calling drm_fb_helper_fini().
 *
 * RETURNS:
 * fb_info pointer if things went okay, pointer containing error code
 * otherwise
 */
struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
static struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
{
	struct device *dev = fb_helper->dev->dev;
	struct fb_info *info;
@@ -499,17 +486,8 @@ struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
	framebuffer_release(info);
	return ERR_PTR(ret);
}
EXPORT_SYMBOL(drm_fb_helper_alloc_info);

/**
 * drm_fb_helper_release_info - release fb_info and its members
 * @fb_helper: driver-allocated fbdev helper
 *
 * A helper to release fb_info and the member cmap.  Drivers do not
 * need to release the allocated fb_info structure themselves, this is
 * automatically done when calling drm_fb_helper_fini().
 */
void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
static void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
{
	struct fb_info *info = fb_helper->info;

@@ -522,7 +500,6 @@ void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
		fb_dealloc_cmap(&info->cmap);
	framebuffer_release(info);
}
EXPORT_SYMBOL(drm_fb_helper_release_info);

/**
 * drm_fb_helper_unregister_info - unregister fb_info framebuffer device
@@ -1770,6 +1747,11 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
	height = dev->mode_config.max_height;

	drm_client_modeset_probe(&fb_helper->client, width, height);

	info = drm_fb_helper_alloc_info(fb_helper);
	if (IS_ERR(info))
		return PTR_ERR(info);

	ret = drm_fb_helper_single_fb_probe(fb_helper);
	if (ret < 0) {
		if (ret == -EAGAIN) {
@@ -1778,13 +1760,12 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
		}
		mutex_unlock(&fb_helper->lock);

		return ret;
		goto err_drm_fb_helper_release_info;
	}
	drm_setup_crtcs_fb(fb_helper);

	fb_helper->deferred_setup = false;

	info = fb_helper->info;
	info->var.pixclock = 0;

	/* Need to drop locks to avoid recursive deadlock in
@@ -1804,6 +1785,10 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
	mutex_unlock(&kernel_fb_helper_lock);

	return 0;

err_drm_fb_helper_release_info:
	drm_fb_helper_release_info(fb_helper);
	return ret;
}

/**
+2 −10
Original line number Diff line number Diff line
@@ -269,9 +269,9 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
{
	struct drm_client_dev *client = &fb_helper->client;
	struct drm_device *dev = fb_helper->dev;
	struct fb_info *info = fb_helper->info;
	struct drm_client_buffer *buffer;
	struct drm_framebuffer *fb;
	struct fb_info *info;
	u32 format;
	struct iosys_map map;
	int ret;
@@ -301,12 +301,6 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
	fb_helper->buffer = buffer;
	fb_helper->fb = fb;

	info = drm_fb_helper_alloc_info(fb_helper);
	if (IS_ERR(info)) {
		ret = PTR_ERR(info);
		goto err_drm_client_buffer_vunmap;
	}

	drm_fb_helper_fill_info(info, fb_helper, sizes);

	if (fb->funcs->dirty)
@@ -314,12 +308,10 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
	else
		ret = drm_fbdev_dma_driver_fbdev_probe_tail(fb_helper, sizes);
	if (ret)
		goto err_drm_fb_helper_release_info;
		goto err_drm_client_buffer_vunmap;

	return 0;

err_drm_fb_helper_release_info:
	drm_fb_helper_release_info(fb_helper);
err_drm_client_buffer_vunmap:
	fb_helper->fb = NULL;
	fb_helper->buffer = NULL;
+2 −10
Original line number Diff line number Diff line
@@ -135,10 +135,10 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
{
	struct drm_client_dev *client = &fb_helper->client;
	struct drm_device *dev = fb_helper->dev;
	struct fb_info *info = fb_helper->info;
	struct drm_client_buffer *buffer;
	struct drm_gem_shmem_object *shmem;
	struct drm_framebuffer *fb;
	struct fb_info *info;
	u32 format;
	struct iosys_map map;
	int ret;
@@ -168,12 +168,6 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
	fb_helper->buffer = buffer;
	fb_helper->fb = fb;

	info = drm_fb_helper_alloc_info(fb_helper);
	if (IS_ERR(info)) {
		ret = PTR_ERR(info);
		goto err_drm_client_buffer_vunmap;
	}

	drm_fb_helper_fill_info(info, fb_helper, sizes);

	info->fbops = &drm_fbdev_shmem_fb_ops;
@@ -194,12 +188,10 @@ int drm_fbdev_shmem_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
	info->fbdefio = &fb_helper->fbdefio;
	ret = fb_deferred_io_init(info);
	if (ret)
		goto err_drm_fb_helper_release_info;
		goto err_drm_client_buffer_vunmap;

	return 0;

err_drm_fb_helper_release_info:
	drm_fb_helper_release_info(fb_helper);
err_drm_client_buffer_vunmap:
	fb_helper->fb = NULL;
	fb_helper->buffer = NULL;
+2 −10
Original line number Diff line number Diff line
@@ -174,8 +174,8 @@ int drm_fbdev_ttm_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
{
	struct drm_client_dev *client = &fb_helper->client;
	struct drm_device *dev = fb_helper->dev;
	struct fb_info *info = fb_helper->info;
	struct drm_client_buffer *buffer;
	struct fb_info *info;
	size_t screen_size;
	void *screen_buffer;
	u32 format;
@@ -203,12 +203,6 @@ int drm_fbdev_ttm_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
		goto err_drm_client_buffer_delete;
	}

	info = drm_fb_helper_alloc_info(fb_helper);
	if (IS_ERR(info)) {
		ret = PTR_ERR(info);
		goto err_vfree;
	}

	drm_fb_helper_fill_info(info, fb_helper, sizes);

	info->fbops = &drm_fbdev_ttm_fb_ops;
@@ -225,12 +219,10 @@ int drm_fbdev_ttm_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
	info->fbdefio = &fb_helper->fbdefio;
	ret = fb_deferred_io_init(info);
	if (ret)
		goto err_drm_fb_helper_release_info;
		goto err_vfree;

	return 0;

err_drm_fb_helper_release_info:
	drm_fb_helper_release_info(fb_helper);
err_vfree:
	vfree(screen_buffer);
err_drm_client_buffer_delete:
Loading