@@ -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;
@@ -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 {