[PATCH] drm/fb-helper/generic: Only restore when in use
Daniel Vetter
daniel at ffwll.ch
Thu Nov 22 09:05:36 UTC 2018
On Wed, Nov 21, 2018 at 05:56:42PM +0100, Noralf Trønnes wrote:
> On drm_driver->last_close the generic fbdev emulation will restore fbdev
> regardless of it being used or not. This is a problem for e-ink displays
> which don't want to be overwritten with zeroes when DRM userspace closes.
>
> Amend this by adding an open counter to track fbdev use to know when to
> restore. Make use of it in the generic fbdev emulation.
>
> It wasn't possible to add this funtionality to say all the drivers that
> use the DRM_FB_HELPER_DEFAULT_OPS macro, because some of its users set
> .fb_open and .fb_release.
>
> If some driver wants this functionality it can export drm_fbdev_fb_open()
> and drm_fbdev_fb_release() and use them.
>
> Signed-off-by: Noralf Trønnes <noralf at tronnes.org>
Hm, the special-casing is a bit annoying. I think it'd be much nicer to
roll out calls to the helper open/releas implementations to all the
drivers which have an fb_open/release already. And then make this work for
everyone. Quick grep says that there's only radeon/amdgpu, nouveau and udl
doing that.
-Daniel
> ---
> drivers/gpu/drm/drm_fb_helper.c | 25 +++++++++++++++++++++++--
> include/drm/drm_fb_helper.h | 14 ++++++++++++++
> 2 files changed, 37 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 9a69ad7e9f3b..24ffaee11f5a 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -530,7 +530,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
> {
> bool do_delayed;
> - int ret;
> + int ret = 0;
>
> if (!drm_fbdev_emulation || !fb_helper)
> return -ENODEV;
> @@ -539,7 +539,8 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
> return 0;
>
> mutex_lock(&fb_helper->lock);
> - ret = restore_fbdev_mode(fb_helper);
> + if (fb_helper->fb_open_count)
> + ret = restore_fbdev_mode(fb_helper);
>
> do_delayed = fb_helper->delayed_hotplug;
> if (do_delayed)
> @@ -888,6 +889,8 @@ int drm_fb_helper_init(struct drm_device *dev,
> i++;
> }
>
> + fb_helper->fb_open_count = 1;
> +
> dev->fb_helper = fb_helper;
>
> return 0;
> @@ -2942,16 +2945,32 @@ EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
> static int drm_fbdev_fb_open(struct fb_info *info, int user)
> {
> struct drm_fb_helper *fb_helper = info->par;
> + unsigned int fb_open_count;
>
> if (!try_module_get(fb_helper->dev->driver->fops->owner))
> return -ENODEV;
>
> + mutex_lock(&fb_helper->lock);
> + fb_open_count = fb_helper->fb_open_count++;
> + mutex_unlock(&fb_helper->lock);
> +
> + if (!fb_open_count)
> + drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
> +
> return 0;
> }
>
> static int drm_fbdev_fb_release(struct fb_info *info, int user)
> {
> struct drm_fb_helper *fb_helper = info->par;
> + unsigned int fb_open_count;
> +
> + mutex_lock(&fb_helper->lock);
> + fb_open_count = --fb_helper->fb_open_count;
> + mutex_unlock(&fb_helper->lock);
> +
> + if (!fb_open_count)
> + drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
>
> module_put(fb_helper->dev->driver->fops->owner);
>
> @@ -3050,6 +3069,8 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
> sizes->surface_width, sizes->surface_height,
> sizes->surface_bpp);
>
> + fb_helper->fb_open_count = 0;
> +
> format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
> buffer = drm_client_framebuffer_create(client, sizes->surface_width,
> sizes->surface_height, format);
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index bb9acea61369..846ca8509427 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -247,6 +247,20 @@ struct drm_fb_helper {
> * See also: @deferred_setup
> */
> int preferred_bpp;
> +
> + /**
> + * @fb_open_count:
> + *
> + * Used to track userspace/fbcon opens to know when to restore fbdev in
> + * drm_fb_helper_restore_fbdev_mode_unlocked(). The value is set to 1 by
> + * default which means it will always restore. Drivers that want to
> + * track this can set this to zero in their
> + * &drm_fb_helper_funcs.fb_probe function. Additionally the value must
> + * be increased in &fb_ops.fb_open and decreased in &fb_ops.fb_release.
> + *
> + * The value is protected by @lock.
> + */
> + unsigned int fb_open_count;
> };
>
> static inline struct drm_fb_helper *
> --
> 2.15.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list