@@ -1411,7 +1411,7 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
EXPORT_SYMBOL(drm_atomic_check_only);
/**
- * drm_atomic_commit - commit configuration atomically
+ * drm_atomic_commit_noflush - commit configuration atomically, without waiting for the commit
* @state: atomic configuration to check
*
* Note that this function can return -EDEADLK if the driver needed to acquire
@@ -1424,7 +1424,7 @@ EXPORT_SYMBOL(drm_atomic_check_only);
* Returns:
* 0 on success, negative error code on failure.
*/
-int drm_atomic_commit(struct drm_atomic_state *state)
+int drm_atomic_commit_noflush(struct drm_atomic_state *state)
{
struct drm_mode_config *config = &state->dev->mode_config;
struct drm_printer p = drm_info_printer(state->dev->dev);
@@ -1441,6 +1441,34 @@ int drm_atomic_commit(struct drm_atomic_state *state)
return config->funcs->atomic_commit(state->dev, state, false);
}
+EXPORT_SYMBOL(drm_atomic_commit_noflush);
+
+/**
+ * drm_atomic_commit - commit configuration atomically, waiting for the commit to finish
+ * @state: atomic configuration to check
+ *
+ * Note that this function can return -EDEADLK if the driver needed to acquire
+ * more locks but encountered a deadlock. The caller must then do the usual w/w
+ * backoff dance and restart. All other errors are fatal.
+ *
+ * This function will take its own reference on @state.
+ * Callers should always release their reference with drm_atomic_state_put().
+ *
+ * Returns:
+ * 0 on success, negative error code on failure.
+ */
+int drm_atomic_commit(struct drm_atomic_state *state)
+{
+ int ret;
+
+ ret = drm_atomic_commit_noflush(state);
+ if (ret)
+ return ret;
+
+ flush_work(&state->commit_work);
+
+ return 0;
+}
EXPORT_SYMBOL(drm_atomic_commit);
/**
@@ -1290,6 +1290,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_atomic_state *state;
struct drm_modeset_acquire_ctx ctx;
struct drm_out_fence_state *fence_state;
+ bool flush = false;
int ret = 0;
unsigned int i, j, num_fences;
@@ -1423,7 +1424,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
ret = drm_atomic_nonblocking_commit(state);
} else {
- ret = drm_atomic_commit(state);
+ ret = drm_atomic_commit_noflush(state);
+ flush = ret == 0;
}
out:
@@ -1436,10 +1438,13 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
goto retry;
}
- drm_atomic_state_put(state);
-
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
+ if (flush)
+ flush_work(&state->commit_work);
+
+ drm_atomic_state_put(state);
+
return ret;
}
@@ -740,6 +740,7 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
struct drm_crtc *crtc);
int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
+int __must_check drm_atomic_commit_noflush(struct drm_atomic_state *state);
int __must_check drm_atomic_commit(struct drm_atomic_state *state);
int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);