From: Thomas Zimmermann <tzimmermann@suse.de>
To: simona@ffwll.ch, airlied@gmail.com, javierm@redhat.com,
jfalempe@redhat.com
Cc: dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org,
Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH v3 07/12] drm/client: Move suspend/resume into DRM client callbacks
Date: Tue, 8 Oct 2024 13:59:26 +0200 [thread overview]
Message-ID: <20241008120652.159190-8-tzimmermann@suse.de> (raw)
In-Reply-To: <20241008120652.159190-1-tzimmermann@suse.de>
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.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/drm/drm_client_event.c | 60 ++++++++++++++++++++++++++++
drivers/gpu/drm/drm_fbdev_client.c | 30 +++++++++++++-
drivers/gpu/drm/drm_modeset_helper.c | 14 ++++---
include/drm/drm_client.h | 35 ++++++++++++++++
include/drm/drm_client_event.h | 2 +
5 files changed, 133 insertions(+), 8 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)
{
diff --git a/drivers/gpu/drm/drm_fbdev_client.c b/drivers/gpu/drm/drm_fbdev_client.c
index a09382afe2fb..246fb63ab250 100644
--- a/drivers/gpu/drm/drm_fbdev_client.c
+++ b/drivers/gpu/drm/drm_fbdev_client.c
@@ -61,11 +61,37 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
return ret;
}
+static int drm_fbdev_client_suspend(struct drm_client_dev *client, bool holds_console_lock)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (holds_console_lock)
+ drm_fb_helper_set_suspend(fb_helper, true);
+ else
+ drm_fb_helper_set_suspend_unlocked(fb_helper, true);
+
+ return 0;
+}
+
+static int drm_fbdev_client_resume(struct drm_client_dev *client, bool holds_console_lock)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (holds_console_lock)
+ drm_fb_helper_set_suspend(fb_helper, false);
+ else
+ drm_fb_helper_set_suspend_unlocked(fb_helper, false);
+
+ return 0;
+}
+
static const struct drm_client_funcs drm_fbdev_client_funcs = {
.owner = THIS_MODULE,
.unregister = drm_fbdev_client_unregister,
.restore = drm_fbdev_client_restore,
.hotplug = drm_fbdev_client_hotplug,
+ .suspend = drm_fbdev_client_suspend,
+ .resume = drm_fbdev_client_resume,
};
/**
@@ -76,8 +102,8 @@ static const struct drm_client_funcs drm_fbdev_client_funcs = {
*
* This function sets up fbdev emulation. Restore, hotplug events and
* teardown are all taken care of. Drivers that do suspend/resume need
- * to call drm_fb_helper_set_suspend_unlocked() themselves. Simple
- * drivers might use drm_mode_config_helper_suspend().
+ * to call drm_client_dev_suspend() and drm_client_dev_resume() by
+ * themselves. Simple drivers might use drm_mode_config_helper_suspend().
*
* This function is safe to call even when there are no connectors present.
* Setup will be retried on the next hotplug event.
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
index 2c582020cb42..5565464c1734 100644
--- a/drivers/gpu/drm/drm_modeset_helper.c
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -21,7 +21,7 @@
*/
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_client_event.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_modeset_helper.h>
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(drm_crtc_init);
* Zero on success, negative error code on error.
*
* See also:
- * drm_kms_helper_poll_disable() and drm_fb_helper_set_suspend_unlocked().
+ * drm_kms_helper_poll_disable() and drm_client_dev_suspend().
*/
int drm_mode_config_helper_suspend(struct drm_device *dev)
{
@@ -199,10 +199,11 @@ int drm_mode_config_helper_suspend(struct drm_device *dev)
if (dev->mode_config.poll_enabled)
drm_kms_helper_poll_disable(dev);
- drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
+ drm_client_dev_suspend(dev, false);
state = drm_atomic_helper_suspend(dev);
if (IS_ERR(state)) {
- drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
+ drm_client_dev_resume(dev, false);
+
/*
* Don't enable polling if it was never initialized
*/
@@ -230,7 +231,7 @@ EXPORT_SYMBOL(drm_mode_config_helper_suspend);
* Zero on success, negative error code on error.
*
* See also:
- * drm_fb_helper_set_suspend_unlocked() and drm_kms_helper_poll_enable().
+ * drm_client_dev_resume() and drm_kms_helper_poll_enable().
*/
int drm_mode_config_helper_resume(struct drm_device *dev)
{
@@ -247,7 +248,8 @@ int drm_mode_config_helper_resume(struct drm_device *dev)
DRM_ERROR("Failed to resume (%d)\n", ret);
dev->mode_config.suspend_state = NULL;
- drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
+ drm_client_dev_resume(dev, false);
+
/*
* Don't enable polling if it is not initialized
*/
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index dfd5afcc9463..c03c4b0f3e94 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -63,6 +63,34 @@ struct drm_client_funcs {
* This callback is optional.
*/
int (*hotplug)(struct drm_client_dev *client);
+
+ /**
+ * @suspend:
+ *
+ * Called when suspending the device.
+ *
+ * This callback is optional.
+ *
+ * FIXME: Some callers hold the console lock when invoking this
+ * function. This interferes with fbdev emulation, which
+ * also tries to acquire the lock. Push the console lock
+ * into the callback and remove 'holds_console_lock'.
+ */
+ int (*suspend)(struct drm_client_dev *client, bool holds_console_lock);
+
+ /**
+ * @resume:
+ *
+ * Called when resuming the device from suspend.
+ *
+ * This callback is optional.
+ *
+ * FIXME: Some callers hold the console lock when invoking this
+ * function. This interferes with fbdev emulation, which
+ * also tries to acquire the lock. Push the console lock
+ * into the callback and remove 'holds_console_lock'.
+ */
+ int (*resume)(struct drm_client_dev *client, bool holds_console_lock);
};
/**
@@ -107,6 +135,13 @@ struct drm_client_dev {
*/
struct drm_mode_set *modesets;
+ /**
+ * @suspended:
+ *
+ * The client has been suspended.
+ */
+ bool suspended;
+
/**
* @hotplug_failed:
*
diff --git a/include/drm/drm_client_event.h b/include/drm/drm_client_event.h
index 2c8915241120..72c97d111169 100644
--- a/include/drm/drm_client_event.h
+++ b/include/drm/drm_client_event.h
@@ -8,5 +8,7 @@ struct drm_device;
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_suspend(struct drm_device *dev, bool holds_console_lock);
+void drm_client_dev_resume(struct drm_device *dev, bool holds_console_lock);
#endif
--
2.46.0
next prev parent reply other threads:[~2024-10-08 12:07 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-08 11:59 [PATCH v3 00/12] drm: Introduce DRM client library Thomas Zimmermann
2024-10-08 11:59 ` [PATCH v3 01/12] drm/i915: Select DRM_CLIENT_SELECTION Thomas Zimmermann
2024-10-08 20:54 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 02/12] drm/xe: " Thomas Zimmermann
2024-10-08 20:54 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 03/12] drm/fbdev-dma: Select FB_DEFERRED_IO Thomas Zimmermann
2024-10-08 20:55 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 04/12] drm/fbdev: Select fbdev I/O helpers from modules that require them Thomas Zimmermann
2024-10-08 20:55 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 05/12] drm/fbdev: Store fbdev module parameters in separate file Thomas Zimmermann
2024-10-08 20:56 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 06/12] drm/client: Move client event handlers to drm_client_event.c Thomas Zimmermann
2024-10-08 21:11 ` Cavitt, Jonathan
2024-10-08 11:59 ` Thomas Zimmermann [this message]
2024-10-08 21:21 ` [PATCH v3 07/12] drm/client: Move suspend/resume into DRM client callbacks Cavitt, Jonathan
2024-10-14 7:07 ` Thomas Zimmermann
2024-10-08 11:59 ` [PATCH v3 08/12] drm/amdgpu: Suspend and resume internal clients with client helpers Thomas Zimmermann
2024-10-08 21:37 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 09/12] drm/nouveau: Suspend and resume " Thomas Zimmermann
2024-10-08 21:38 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 10/12] drm/radeon: " Thomas Zimmermann
2024-10-08 21:40 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 11/12] drm/client: Make client support optional Thomas Zimmermann
2024-10-08 21:41 ` Cavitt, Jonathan
2024-10-08 11:59 ` [PATCH v3 12/12] drm/client: Add client-lib module Thomas Zimmermann
2024-10-08 21:42 ` Cavitt, Jonathan
2024-10-08 12:12 ` ✓ CI.Patch_applied: success for drm: Introduce DRM client library (rev3) Patchwork
2024-10-08 12:13 ` ✗ CI.checkpatch: warning " Patchwork
2024-10-08 12:14 ` ✓ CI.KUnit: success " Patchwork
2024-10-08 12:27 ` ✓ CI.Build: " Patchwork
2024-10-08 12:29 ` ✓ CI.Hooks: " Patchwork
2024-10-08 12:30 ` ✗ CI.checksparse: warning " Patchwork
2024-10-08 12:58 ` ✓ CI.BAT: success " Patchwork
2024-10-08 19:04 ` ✗ CI.FULL: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241008120652.159190-8-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=airlied@gmail.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=javierm@redhat.com \
--cc=jfalempe@redhat.com \
--cc=simona@ffwll.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox