From: Oarora Etimis <oaroraetimis@gmail.com>
To: Louis Chauvet <louis.chauvet@bootlin.com>,
Haneen Mohammed <hamohammed.sa@gmail.com>,
Simona Vetter <simona@ffwll.ch>,
Melissa Wen <melissa.srw@gmail.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Liviu Dudau <liviu.dudau@arm.com>,
Rodrigo Siqueira <siqueira@igalia.com>
Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org,
Oarora Etimis <oaroraetimis@gmail.com>
Subject: [PATCH] drm/vkms: use a bitmask instead of a bool for composer users
Date: Wed, 11 Nov 2026 14:32:24 +0000 [thread overview]
Message-ID: <20261111-composer-v1-1-9d5fa94656f8@gmail.com> (raw)
The composer has a single on/off switch, shared by the CRC reader and the
writeback job, and no record of who needs it. Either of them turns it off
for both:
- with CRC being captured, cleaning up a writeback job stops the CRC
entries;
- with a writeback job pending, closing the CRC source leaves the frame
uncomposed and its out-fence never signalled.
Replace the switch with a bitmask holding one bit per user, so a user only
clears its own bit and the composer stays active while any bit is set. The
vblank reference follows the bitmask: taken when it becomes non-zero and
dropped when it becomes zero again. vkms_set_composer() becomes
vkms_composer_get() and vkms_composer_put().
Fixes: dbd9d80c1b2e ("drm/vkms: Add support for writeback")
Signed-off-by: Oarora Etimis <oaroraetimis@gmail.com>
---
- Why not use a refcount? Because there are only a few users, and a bit
per user shows the working state of each one. A repeated put() from the
same user does nothing, and it also helps future work that makes the
vblank timeout synchronous.
- Tested with vng: read crc/data and submitted three writeback jobs with a
small libdrm helper. The entries kept coming at the full rate of the
1024x768@60 mode, 235 to 237 of them over the 3.97 s the three jobs
took, where the current code stops at five.
---
Documentation/gpu/vkms.rst | 5 -----
drivers/gpu/drm/vkms/vkms_composer.c | 34 ++++++++++++++++++++++++++--------
drivers/gpu/drm/vkms/vkms_crtc.c | 2 +-
drivers/gpu/drm/vkms/vkms_drv.h | 27 +++++++++++++++++++++++----
drivers/gpu/drm/vkms/vkms_writeback.c | 4 ++--
5 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst
index 1e79e62a6bc4..fe7dc8def44a 100644
--- a/Documentation/gpu/vkms.rst
+++ b/Documentation/gpu/vkms.rst
@@ -246,11 +246,6 @@ module through configfs. Use/Test-cases:
Writeback support
-----------------
-- The writeback and CRC capture operations share the use of composer_enabled
- boolean to ensure vblanks. Probably, when these operations work together,
- composer_enabled needs to refcounting the composer state to proper work.
- [Good to get started]
-
- Add support for cloned writeback outputs and related test cases using a
cloned output in the IGT kms_writeback.
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 0fc915a954ba..59f1dd50b5bd 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -711,19 +711,34 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name,
return 0;
}
-void vkms_set_composer(struct vkms_output *out, bool enabled)
+void vkms_composer_get(struct vkms_output *out, u8 user)
{
- bool old_enabled;
+ bool was_enabled;
- if (enabled)
- drm_crtc_vblank_get(&out->crtc);
+ if (drm_crtc_vblank_get(&out->crtc))
+ return;
+
+ spin_lock_irq(&out->lock);
+ was_enabled = out->composer_users;
+ out->composer_users |= user;
+ spin_unlock_irq(&out->lock);
+
+ /* Another user already holds the reference for the composer. */
+ if (was_enabled)
+ drm_crtc_vblank_put(&out->crtc);
+}
+
+void vkms_composer_put(struct vkms_output *out, u8 user)
+{
+ bool was_set, enabled;
spin_lock_irq(&out->lock);
- old_enabled = out->composer_enabled;
- out->composer_enabled = enabled;
+ was_set = out->composer_users & user;
+ out->composer_users &= ~user;
+ enabled = out->composer_users;
spin_unlock_irq(&out->lock);
- if (old_enabled)
+ if (was_set && !enabled)
drm_crtc_vblank_put(&out->crtc);
}
@@ -735,7 +750,10 @@ int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name)
ret = vkms_crc_parse_source(src_name, &enabled);
- vkms_set_composer(out, enabled);
+ if (enabled)
+ vkms_composer_get(out, VKMS_COMPOSER_CRC);
+ else
+ vkms_composer_put(out, VKMS_COMPOSER_CRC);
return ret;
}
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index fe17f49305a9..4e15abfd92a0 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -29,7 +29,7 @@ static bool vkms_crtc_handle_vblank_timeout(struct drm_crtc *crtc)
state = output->composer_state;
spin_unlock(&output->lock);
- if (state && output->composer_enabled) {
+ if (state && READ_ONCE(output->composer_users)) {
u64 frame = drm_crtc_accurate_vblank_count(crtc);
/* update frame_start only if a queued vkms_composer_worker()
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index dea6cad3f1b9..c3bb3cd46863 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -27,6 +27,9 @@
#define VKMS_LUT_SIZE 256
+#define VKMS_COMPOSER_CRC (1U << 0)
+#define VKMS_COMPOSER_WB (1U << 1)
+
/**
* struct vkms_frame_info - Structure to store the state of a frame
*
@@ -210,8 +213,9 @@ struct vkms_crtc_state {
* vblank timestamps
* @composer_workq: Ordered workqueue for @composer_state.composer_work.
* @lock: Lock used to protect concurrent access to the composer
- * @composer_enabled: Protected by @lock, true when the VKMS composer is active (crc needed or
- * writeback)
+ * @composer_users: Bitmask of the users that need the VKMS composer; the composer is only
+ * active when it is non-zero. Updated under @lock, and read with
+ * READ_ONCE() from the vblank timeout.
* @composer_state: Protected by @lock, current state of this VKMS output
* @composer_lock: Lock used internally to protect @composer_state members
*/
@@ -222,7 +226,7 @@ struct vkms_output {
struct workqueue_struct *composer_workq;
spinlock_t lock;
- bool composer_enabled;
+ u8 composer_users;
struct vkms_crtc_state *composer_state;
spinlock_t composer_lock;
@@ -317,7 +321,22 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
/* Composer Support */
void vkms_composer_worker(struct work_struct *work);
-void vkms_set_composer(struct vkms_output *out, bool enabled);
+
+/**
+ * vkms_composer_get() - Enable the composer for a user
+ * @out: VKMS output
+ * @user: bit of the user that needs the composer (VKMS_COMPOSER_CRC or
+ * VKMS_COMPOSER_WB)
+ */
+void vkms_composer_get(struct vkms_output *out, u8 user);
+
+/**
+ * vkms_composer_put() - Disable the composer for a user
+ * @out: VKMS output
+ * @user: bit of the user that no longer needs the composer
+ */
+void vkms_composer_put(struct vkms_output *out, u8 user);
+
void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y);
/* Writeback */
diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c
index 858df1f89f66..7e2f82e44b39 100644
--- a/drivers/gpu/drm/vkms/vkms_writeback.c
+++ b/drivers/gpu/drm/vkms/vkms_writeback.c
@@ -118,7 +118,7 @@ static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector,
drm_framebuffer_put(vkmsjob->wb_frame_info.fb);
- vkms_set_composer(vkms_output, false);
+ vkms_composer_put(vkms_output, VKMS_COMPOSER_WB);
kfree(vkmsjob);
}
@@ -141,7 +141,7 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn,
if (!conn_state)
return;
- vkms_set_composer(output, true);
+ vkms_composer_get(output, VKMS_COMPOSER_WB);
active_wb = conn_state->writeback_job->priv;
wb_frame_info = &active_wb->wb_frame_info;
---
base-commit: 1116f4aee916ca13d3e40ce87e67835f51576fcb
change-id: 20261111-composer-cc9620515bcd
Best regards,
--
Oarora Etimis <oaroraetimis@gmail.com>
reply other threads:[~2026-11-11 14:32 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261111-composer-v1-1-9d5fa94656f8@gmail.com \
--to=oaroraetimis@gmail.com \
--cc=airlied@gmail.com \
--cc=corbet@lwn.net \
--cc=dri-devel@lists.freedesktop.org \
--cc=hamohammed.sa@gmail.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=louis.chauvet@bootlin.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=melissa.srw@gmail.com \
--cc=mripard@kernel.org \
--cc=rdunlap@infradead.org \
--cc=simona@ffwll.ch \
--cc=siqueira@igalia.com \
--cc=skhan@linuxfoundation.org \
--cc=tzimmermann@suse.de \
/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
all inboxes | Powered by JetHome®