drm/client: Pass force parameter to client restore

Add force parameter to client restore and pass value through the
layers. The only currently used value is false.

If force is true, the client should restore its display even if it
does not hold the DRM master lock. This is be required for emergency
output, such as sysrq.

While at it, inline drm_fb_helper_lastclose(), which is a trivial
wrapper around drm_fb_helper_restore_fbdev_mode_unlocked().

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patch.msgid.link/20251110154616.539328-2-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann
2025-11-10 16:44:21 +01:00
parent 94124ea5a7
commit 943240d342
7 changed files with 22 additions and 34 deletions

View File

@@ -38,9 +38,11 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client)
}
}
static int drm_fbdev_client_restore(struct drm_client_dev *client)
static int drm_fbdev_client_restore(struct drm_client_dev *client, bool force)
{
drm_fb_helper_lastclose(client->dev);
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force);
return 0;
}

View File

@@ -102,7 +102,7 @@ void drm_client_dev_hotplug(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_client_dev_hotplug);
void drm_client_dev_restore(struct drm_device *dev)
void drm_client_dev_restore(struct drm_device *dev, bool force)
{
struct drm_client_dev *client;
int ret;
@@ -115,7 +115,7 @@ void drm_client_dev_restore(struct drm_device *dev)
if (!client->funcs || !client->funcs->restore)
continue;
ret = client->funcs->restore(client);
ret = client->funcs->restore(client, force);
drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
if (!ret) /* The first one to return zero gets the privilege to restore */
break;

View File

@@ -255,6 +255,7 @@ __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
/**
* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
* @fb_helper: driver-allocated fbdev helper, can be NULL
* @force: ignore present DRM master
*
* This helper should be called from fbdev emulation's &drm_client_funcs.restore
* callback. It ensures that the user isn't greeted with a black screen when the
@@ -263,9 +264,9 @@ __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
* Returns:
* 0 on success, or a negative errno code otherwise.
*/
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper, bool force)
{
return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, false);
return __drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper, force);
}
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
@@ -1328,9 +1329,9 @@ int drm_fb_helper_set_par(struct fb_info *info)
* the KDSET IOCTL with KD_TEXT, and only after that drops the master
* status when exiting.
*
* In the past this was caught by drm_fb_helper_lastclose(), but on
* modern systems where logind always keeps a drm fd open to orchestrate
* the vt switching, this doesn't work.
* In the past this was caught by drm_fb_helper_restore_fbdev_mode_unlocked(),
* but on modern systems where logind always keeps a drm fd open to
* orchestrate the vt switching, this doesn't work.
*
* To not break the userspace ABI we have this special case here, which
* is only used for the above case. Everything else uses the normal
@@ -1955,16 +1956,3 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
return 0;
}
EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
/**
* drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
* @dev: DRM device
*
* This function is obsolete. Call drm_fb_helper_restore_fbdev_mode_unlocked()
* instead.
*/
void drm_fb_helper_lastclose(struct drm_device *dev)
{
drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper);
}
EXPORT_SYMBOL(drm_fb_helper_lastclose);

View File

@@ -405,7 +405,7 @@ EXPORT_SYMBOL(drm_open);
static void drm_lastclose(struct drm_device *dev)
{
drm_client_dev_restore(dev);
drm_client_dev_restore(dev, false);
if (dev_is_pci(dev->dev))
vga_switcheroo_process_delayed_switch();

View File

@@ -57,12 +57,14 @@ struct drm_client_funcs {
*
* Note that the core does not guarantee exclusion against concurrent
* drm_open(). Clients need to ensure this themselves, for example by
* using drm_master_internal_acquire() and
* drm_master_internal_release().
* using drm_master_internal_acquire() and drm_master_internal_release().
*
* If the caller passes force, the client should ignore any present DRM
* master and restore the display anyway.
*
* This callback is optional.
*/
int (*restore)(struct drm_client_dev *client);
int (*restore)(struct drm_client_dev *client, bool force);
/**
* @hotplug:

View File

@@ -10,7 +10,7 @@ struct drm_device;
#if defined(CONFIG_DRM_CLIENT)
void drm_client_dev_unregister(struct drm_device *dev);
void drm_client_dev_hotplug(struct drm_device *dev);
void drm_client_dev_restore(struct drm_device *dev);
void drm_client_dev_restore(struct drm_device *dev, bool force);
void drm_client_dev_suspend(struct drm_device *dev);
void drm_client_dev_resume(struct drm_device *dev);
#else
@@ -18,7 +18,7 @@ static inline void drm_client_dev_unregister(struct drm_device *dev)
{ }
static inline void drm_client_dev_hotplug(struct drm_device *dev)
{ }
static inline void drm_client_dev_restore(struct drm_device *dev)
static inline void drm_client_dev_restore(struct drm_device *dev, bool force)
{ }
static inline void drm_client_dev_suspend(struct drm_device *dev)
{ }

View File

@@ -254,7 +254,8 @@ int drm_fb_helper_set_par(struct fb_info *info);
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
bool force);
struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper);
@@ -283,7 +284,6 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);
int drm_fb_helper_debug_enter(struct fb_info *info);
int drm_fb_helper_debug_leave(struct fb_info *info);
void drm_fb_helper_lastclose(struct drm_device *dev);
#else
static inline void drm_fb_helper_prepare(struct drm_device *dev,
struct drm_fb_helper *helper,
@@ -409,10 +409,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info)
{
return 0;
}
static inline void drm_fb_helper_lastclose(struct drm_device *dev)
{
}
#endif
#endif