summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_client_event.c
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2024-10-14 10:55:21 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2024-10-18 09:23:03 +0200
commitbf17766f108309027aac2bfe184df6088dfd7384 (patch)
tree45291dfe9d14f72c3e47c37105572b41bc91017b /drivers/gpu/drm/drm_client_event.c
parentdf7e8b522a6090162ecb50fd298ebc4db137562b (diff)
drm/client: Move suspend/resume into DRM client callbacks
Suspend and resume is still tied to fbdev emulation. Modeset helpers and several drivers call drm_fb_helper_set_suspend_unlocked() to inform the fbdev client about suspend/resume events. To make it work with arbitrary clients, add per-client callback functions for suspend and resume. Implement them for fbdev emulation with the existing drm_fb_helper_set_suspend_unlocked(). Then update DRM's modeset helpers to call the new interface. Clients that are not fbdev can now implement suspend/resume to their requirements. The callback parameter holds_console_lock is a workaround for i915, radeon and xe, which possibly call the interface while having the console lock acquired. Even though the commit doesn't modify these drivers, it already adds the flag to avoid churn later on. New code should not hold the console lock. v4: - clarify holds_console_lock in commit description (Jonathan) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20241014085740.582287-8-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/drm_client_event.c')
-rw-r--r--drivers/gpu/drm/drm_client_event.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_client_event.c b/drivers/gpu/drm/drm_client_event.c
index d13d44320c5c..c52e93643672 100644
--- a/drivers/gpu/drm/drm_client_event.c
+++ b/drivers/gpu/drm/drm_client_event.c
@@ -107,6 +107,66 @@ void drm_client_dev_restore(struct drm_device *dev)
mutex_unlock(&dev->clientlist_mutex);
}
+static int drm_client_suspend(struct drm_client_dev *client, bool holds_console_lock)
+{
+ struct drm_device *dev = client->dev;
+ int ret = 0;
+
+ if (drm_WARN_ON_ONCE(dev, client->suspended))
+ return 0;
+
+ if (client->funcs && client->funcs->suspend)
+ ret = client->funcs->suspend(client, holds_console_lock);
+ drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
+
+ client->suspended = true;
+
+ return ret;
+}
+
+void drm_client_dev_suspend(struct drm_device *dev, bool holds_console_lock)
+{
+ struct drm_client_dev *client;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry(client, &dev->clientlist, list) {
+ if (!client->suspended)
+ drm_client_suspend(client, holds_console_lock);
+ }
+ mutex_unlock(&dev->clientlist_mutex);
+}
+EXPORT_SYMBOL(drm_client_dev_suspend);
+
+static int drm_client_resume(struct drm_client_dev *client, bool holds_console_lock)
+{
+ struct drm_device *dev = client->dev;
+ int ret = 0;
+
+ if (drm_WARN_ON_ONCE(dev, !client->suspended))
+ return 0;
+
+ if (client->funcs && client->funcs->resume)
+ ret = client->funcs->resume(client, holds_console_lock);
+ drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret);
+
+ client->suspended = false;
+
+ return ret;
+}
+
+void drm_client_dev_resume(struct drm_device *dev, bool holds_console_lock)
+{
+ struct drm_client_dev *client;
+
+ mutex_lock(&dev->clientlist_mutex);
+ list_for_each_entry(client, &dev->clientlist, list) {
+ if (client->suspended)
+ drm_client_resume(client, holds_console_lock);
+ }
+ mutex_unlock(&dev->clientlist_mutex);
+}
+EXPORT_SYMBOL(drm_client_dev_resume);
+
#ifdef CONFIG_DEBUG_FS
static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
{