Keep track of fbdev users and only restore fbdev in drm_fb_helper_restore_fbdev_mode_unlocked() when in use. This avoids fbdev being restored in drm_driver.last_close when nothing uses it. Additionally fbdev is turned off when the last user is closing. fbcon is a user in this context. Signed-off-by: Noralf Trønnes <noralf@xxxxxxxxxxx> --- drivers/gpu/drm/drm_fb_helper.c | 14 ++++++++++++++ include/drm/drm_fb_helper.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index b080004..12a7675 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -504,6 +504,12 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) if (READ_ONCE(fb_helper->deferred_setup)) return 0; + /* Don't restore if we track opens and it's zero */ + if (fb_helper->fbdev && fb_helper->fbdev->fbops && + fb_helper->fbdev->fbops->fb_open == drm_fb_helper_fb_open && + !atomic_read(&fb_helper->open_count)) + return 0; + mutex_lock(&fb_helper->lock); ret = restore_fbdev_mode(fb_helper); @@ -1041,6 +1047,7 @@ EXPORT_SYMBOL(drm_fb_helper_fb_destroy); * @info: fbdev registered by the helper * @user: 1=userspace, 0=fbcon * + * Increase fbdev use count. * If &fb_ops is wrapped in a library, pin the driver module. */ int drm_fb_helper_fb_open(struct fb_info *info, int user) @@ -1054,6 +1061,8 @@ int drm_fb_helper_fb_open(struct fb_info *info, int user) return -ENODEV; } + atomic_inc(&fb_helper->open_count); + return 0; } EXPORT_SYMBOL(drm_fb_helper_fb_open); @@ -1063,6 +1072,7 @@ EXPORT_SYMBOL(drm_fb_helper_fb_open); * @info: fbdev registered by the helper * @user: 1=userspace, 0=fbcon * + * Decrease fbdev use count and turn off if there are no users left. * If &fb_ops is wrapped in a library, unpin the driver module. */ int drm_fb_helper_fb_release(struct fb_info *info, int user) @@ -1070,6 +1080,10 @@ int drm_fb_helper_fb_release(struct fb_info *info, int user) struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; + if (atomic_dec_and_test(&fb_helper->open_count) && + !drm_dev_is_unplugged(fb_helper->dev)) + drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); + if (user && info->fbops->owner != dev->driver->fops->owner) module_put(dev->driver->fops->owner); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index b44fc62..5a5509c 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -223,6 +223,13 @@ struct drm_fb_helper { * See also: @deferred_setup */ int preferred_bpp; + + /** + * @open_count: + * + * Keeps track of fbdev users to know when to restore fbdev. + */ + atomic_t open_count; }; /** -- 2.7.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel