aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2016-09-12 15:08:11 -0400
committerSean Paul <seanpaul@chromium.org>2016-09-12 16:59:15 -0400
commitf6ce410a59a48aff47bb7e18ab40497e4e80d275 (patch)
tree22f63f7c4569b421ccb5cef731170c38ca1a13f2
parentf92f053bb60924297afb8a1bd9166712c0fe5e88 (diff)
drm/fence: allow fence waiting to be interrupted by userspace
If userspace is running an synchronously atomic commit and interrupts the atomic operation during fence_wait() it will hang until the timer expires, so here we change the wait to be interruptible so it stop immediately when userspace wants to quit. Also adds the necessary error checking for fence_wait(). v2: Comment by Daniel Vetter - Add error checking for fence_wait() v3: Rebase on top of new atomic noblocking support v4: Comment by Maarten Lankhorst - remove 'swapped' bitfield as it was duplicating information v5: Comments by Maarten Lankhorst - assign plane->state to plane_state if !intr - squash previous patch into this one v6: Comment by Sean Paul - rename intr to pre_swap Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> [seanpaul fixed a couple checkpatch warnings and moved the preswap comment] Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1473707291-14781-1-git-send-email-gustavo@padovan.org
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c41
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c2
-rw-r--r--include/drm/drm_atomic_helper.h5
3 files changed, 36 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 6fdd7ba47896..ea78d70de9f3 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1009,29 +1009,46 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
1009 * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state 1009 * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
1010 * @dev: DRM device 1010 * @dev: DRM device
1011 * @state: atomic state object with old state structures 1011 * @state: atomic state object with old state structures
1012 * @pre_swap: if true, do an interruptible wait
1012 * 1013 *
1013 * For implicit sync, driver should fish the exclusive fence out from the 1014 * For implicit sync, driver should fish the exclusive fence out from the
1014 * incoming fb's and stash it in the drm_plane_state. This is called after 1015 * incoming fb's and stash it in the drm_plane_state. This is called after
1015 * drm_atomic_helper_swap_state() so it uses the current plane state (and 1016 * drm_atomic_helper_swap_state() so it uses the current plane state (and
1016 * just uses the atomic state to find the changed planes) 1017 * just uses the atomic state to find the changed planes)
1018 *
1019 * Returns zero if success or < 0 if fence_wait() fails.
1017 */ 1020 */
1018void drm_atomic_helper_wait_for_fences(struct drm_device *dev, 1021int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
1019 struct drm_atomic_state *state) 1022 struct drm_atomic_state *state,
1023 bool pre_swap)
1020{ 1024{
1021 struct drm_plane *plane; 1025 struct drm_plane *plane;
1022 struct drm_plane_state *plane_state; 1026 struct drm_plane_state *plane_state;
1023 int i; 1027 int i, ret;
1024 1028
1025 for_each_plane_in_state(state, plane, plane_state, i) { 1029 for_each_plane_in_state(state, plane, plane_state, i) {
1026 if (!plane->state->fence) 1030 if (!pre_swap)
1031 plane_state = plane->state;
1032
1033 if (!plane_state->fence)
1027 continue; 1034 continue;
1028 1035
1029 WARN_ON(!plane->state->fb); 1036 WARN_ON(!plane_state->fb);
1037
1038 /*
1039 * If waiting for fences pre-swap (ie: nonblock), userspace can
1040 * still interrupt the operation. Instead of blocking until the
1041 * timer expires, make the wait interruptible.
1042 */
1043 ret = fence_wait(plane_state->fence, pre_swap);
1044 if (ret)
1045 return ret;
1030 1046
1031 fence_wait(plane->state->fence, false); 1047 fence_put(plane_state->fence);
1032 fence_put(plane->state->fence); 1048 plane_state->fence = NULL;
1033 plane->state->fence = NULL;
1034 } 1049 }
1050
1051 return 0;
1035} 1052}
1036EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); 1053EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
1037 1054
@@ -1179,7 +1196,7 @@ static void commit_tail(struct drm_atomic_state *state)
1179 1196
1180 funcs = dev->mode_config.helper_private; 1197 funcs = dev->mode_config.helper_private;
1181 1198
1182 drm_atomic_helper_wait_for_fences(dev, state); 1199 drm_atomic_helper_wait_for_fences(dev, state, false);
1183 1200
1184 drm_atomic_helper_wait_for_dependencies(state); 1201 drm_atomic_helper_wait_for_dependencies(state);
1185 1202
@@ -1238,6 +1255,12 @@ int drm_atomic_helper_commit(struct drm_device *dev,
1238 if (ret) 1255 if (ret)
1239 return ret; 1256 return ret;
1240 1257
1258 if (!nonblock) {
1259 ret = drm_atomic_helper_wait_for_fences(dev, state, true);
1260 if (ret)
1261 return ret;
1262 }
1263
1241 /* 1264 /*
1242 * This is the point of no return - everything below never fails except 1265 * This is the point of no return - everything below never fails except
1243 * when the hw goes bonghits. Which means we can commit the new state on 1266 * when the hw goes bonghits. Which means we can commit the new state on
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 5df252cebf1c..73bae382eac3 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -112,7 +112,7 @@ static void complete_commit(struct msm_commit *c, bool async)
112 struct msm_drm_private *priv = dev->dev_private; 112 struct msm_drm_private *priv = dev->dev_private;
113 struct msm_kms *kms = priv->kms; 113 struct msm_kms *kms = priv->kms;
114 114
115 drm_atomic_helper_wait_for_fences(dev, state); 115 drm_atomic_helper_wait_for_fences(dev, state, false);
116 116
117 kms->funcs->prepare_commit(kms, state); 117 kms->funcs->prepare_commit(kms, state);
118 118
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index f86682825d68..7ff92b09fd9c 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -45,8 +45,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
45 struct drm_atomic_state *state, 45 struct drm_atomic_state *state,
46 bool nonblock); 46 bool nonblock);
47 47
48void drm_atomic_helper_wait_for_fences(struct drm_device *dev, 48int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
49 struct drm_atomic_state *state); 49 struct drm_atomic_state *state,
50 bool pre_swap);
50bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, 51bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev,
51 struct drm_atomic_state *old_state, 52 struct drm_atomic_state *old_state,
52 struct drm_crtc *crtc); 53 struct drm_crtc *crtc);