[PATCH 1/4] drm/atomic: Treat a nonblocking commit following a blocking commit as blocking commit
Ville Syrjala
ville.syrjala at linux.intel.com
Fri Sep 16 16:33:28 UTC 2022
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
Currently a nonblocking commit will actually block if it is
preceded by a blocking commit. It just happens block on the
mutex rather than on the completion. I shall call these as
not-actually-nonblocking commits.
I would like to make blocking commits execute locklessly,
just as nonblocking commits already do. The main benefit
would that parallel TEST_ONLY commits would not get blocked
on the mutexes until the parallel blocking commit is done.
To achieve that without a significant change in behaviour
for the not-actually-nonblocking commits let's treat them
exactly the same as blocking commit, ie. instead of
returning -EBUSY they will just block.
Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Rob Clark <robdclark at gmail.com>
Cc: Simon Ser <contact at emersion.fr>
Cc: Pekka Paalanen <pekka.paalanen at collabora.com>
Cc: Jonas Ådahl <jadahl at gmail.com>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 19 ++++++++++++-------
include/drm/drm_atomic.h | 7 +++++++
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index ee5fea48b5cb..bff087674cb5 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2109,7 +2109,7 @@ static int stall_checks(struct drm_crtc *crtc, bool nonblock)
* Userspace is not allowed to get ahead of the previous
* commit with nonblocking ones.
*/
- if (!completed && nonblock) {
+ if (!completed && nonblock && commit->nonblock) {
spin_unlock(&crtc->commit_lock);
drm_dbg_atomic(crtc->dev,
"[CRTC:%d:%s] busy with a previous commit\n",
@@ -2152,7 +2152,7 @@ static void release_crtc_commit(struct completion *completion)
drm_crtc_commit_put(commit);
}
-static void init_commit(struct drm_crtc_commit *commit, struct drm_crtc *crtc)
+static void init_commit(struct drm_crtc_commit *commit, struct drm_crtc *crtc, bool nonblock)
{
init_completion(&commit->flip_done);
init_completion(&commit->hw_done);
@@ -2160,10 +2160,11 @@ static void init_commit(struct drm_crtc_commit *commit, struct drm_crtc *crtc)
INIT_LIST_HEAD(&commit->commit_entry);
kref_init(&commit->ref);
commit->crtc = crtc;
+ commit->nonblock = nonblock;
}
static struct drm_crtc_commit *
-crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc)
+crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc, bool nonblock)
{
if (crtc) {
struct drm_crtc_state *new_crtc_state;
@@ -2178,7 +2179,7 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc)
if (!state->fake_commit)
return NULL;
- init_commit(state->fake_commit, NULL);
+ init_commit(state->fake_commit, NULL, nonblock);
}
return state->fake_commit;
@@ -2250,7 +2251,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
if (!commit)
return -ENOMEM;
- init_commit(commit, crtc);
+ init_commit(commit, crtc, nonblock);
new_crtc_state->commit = commit;
@@ -2299,6 +2300,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
* commit with nonblocking ones.
*/
if (nonblock && old_conn_state->commit &&
+ old_conn_state->commit->nonblock &&
!try_wait_for_completion(&old_conn_state->commit->flip_done)) {
drm_dbg_atomic(conn->dev,
"[CONNECTOR:%d:%s] busy with a previous commit\n",
@@ -2308,7 +2310,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
}
/* Always track connectors explicitly for e.g. link retraining. */
- commit = crtc_or_fake_commit(state, new_conn_state->crtc ?: old_conn_state->crtc);
+ commit = crtc_or_fake_commit(state, new_conn_state->crtc ?: old_conn_state->crtc,
+ nonblock);
if (!commit)
return -ENOMEM;
@@ -2321,6 +2324,7 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
* commit with nonblocking ones.
*/
if (nonblock && old_plane_state->commit &&
+ old_plane_state->commit->nonblock &&
!try_wait_for_completion(&old_plane_state->commit->flip_done)) {
drm_dbg_atomic(plane->dev,
"[PLANE:%d:%s] busy with a previous commit\n",
@@ -2330,7 +2334,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
}
/* Always track planes explicitly for async pageflip support. */
- commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc);
+ commit = crtc_or_fake_commit(state, new_plane_state->crtc ?: old_plane_state->crtc,
+ nonblock);
if (!commit)
return -ENOMEM;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 10b1990bc1f6..0924c322ddfb 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -155,6 +155,13 @@ struct drm_crtc_commit {
* used by the free code to remove the second reference if commit fails.
*/
bool abort_completion;
+
+ /**
+ * @nonblock:
+ *
+ * Nonblocking commit?
+ */
+ bool nonblock;
};
struct __drm_planes_state {
--
2.35.1
More information about the dri-devel
mailing list