diff options
Diffstat (limited to 'kernel/drivers/gpu/drm/msm/msm_atomic.c')
-rw-r--r-- | kernel/drivers/gpu/drm/msm/msm_atomic.c | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/kernel/drivers/gpu/drm/msm/msm_atomic.c b/kernel/drivers/gpu/drm/msm/msm_atomic.c index 5b192128c..7eb253bc2 100644 --- a/kernel/drivers/gpu/drm/msm/msm_atomic.c +++ b/kernel/drivers/gpu/drm/msm/msm_atomic.c @@ -84,6 +84,33 @@ static void commit_destroy(struct msm_commit *c) kfree(c); } +static void msm_atomic_wait_for_commit_done(struct drm_device *dev, + struct drm_atomic_state *old_state) +{ + struct drm_crtc *crtc; + struct msm_drm_private *priv = old_state->dev->dev_private; + struct msm_kms *kms = priv->kms; + int ncrtcs = old_state->dev->mode_config.num_crtc; + int i; + + for (i = 0; i < ncrtcs; i++) { + crtc = old_state->crtcs[i]; + + if (!crtc) + continue; + + if (!crtc->state->enable) + continue; + + /* Legacy cursor ioctls are completely unsynced, and userspace + * relies on that (by doing tons of cursor updates). */ + if (old_state->legacy_cursor_update) + continue; + + kms->funcs->wait_for_crtc_commit_done(kms, crtc); + } +} + /* The (potentially) asynchronous part of the commit. At this point * nothing can fail short of armageddon. */ @@ -98,7 +125,7 @@ static void complete_commit(struct msm_commit *c) drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, state); + drm_atomic_helper_commit_planes(dev, state, false); drm_atomic_helper_commit_modeset_enables(dev, state); @@ -115,7 +142,7 @@ static void complete_commit(struct msm_commit *c) * not be critical path) */ - drm_atomic_helper_wait_for_vblanks(dev, state); + msm_atomic_wait_for_commit_done(dev, state); drm_atomic_helper_cleanup_planes(dev, state); @@ -139,7 +166,6 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb) c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ)); } - int msm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -178,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev, { int nplanes = dev->mode_config.num_total_plane; int ncrtcs = dev->mode_config.num_crtc; - struct timespec timeout; + ktime_t timeout; struct msm_commit *c; int i, ret; @@ -187,8 +213,10 @@ int msm_atomic_commit(struct drm_device *dev, return ret; c = commit_init(state); - if (!c) - return -ENOMEM; + if (!c) { + ret = -ENOMEM; + goto error; + } /* * Figure out what crtcs we have: @@ -221,7 +249,7 @@ int msm_atomic_commit(struct drm_device *dev, ret = start_atomic(dev->dev_private, c->crtc_mask); if (ret) { kfree(c); - return ret; + goto error; } /* @@ -253,16 +281,16 @@ int msm_atomic_commit(struct drm_device *dev, return 0; } - jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout); + timeout = ktime_add_ms(ktime_get(), 1000); - ret = msm_wait_fence_interruptable(dev, c->fence, &timeout); - if (ret) { - WARN_ON(ret); // TODO unswap state back? or?? - commit_destroy(c); - return ret; - } + /* uninterruptible wait */ + msm_wait_fence(dev, c->fence, &timeout, false); complete_commit(c); return 0; + +error: + drm_atomic_helper_cleanup_planes(dev, state); + return ret; } |