diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-01-14 16:18:02 -0500 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-01-26 01:01:12 -0500 |
commit | de3f440f8c9922afe8770dd16c84f1c87d779b59 (patch) | |
tree | 3f5eafaeb3e90a92b3ca503592d99277fe60816b /drivers/gpu | |
parent | 8a6c77d645d9111f7bc01f908464301f5c3e0a05 (diff) |
drm/i915: handle non-flip pending case when unpinning the scanout buffer
The first page flip queued will replace the current front buffer, which
should have a 0 pending flip count. So at finish time we need to handle
that case (i.e. if the flip count is 0 *or* dec_and_test is 0 we need to
wake the waiters).
Also fix up an error path in the queue function and add some debug
output (only enabled with driver debugging).
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2cc489b6629e..5f14dfbf715c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3985,6 +3985,12 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
3985 | spin_lock_irqsave(&dev->event_lock, flags); | 3985 | spin_lock_irqsave(&dev->event_lock, flags); |
3986 | work = intel_crtc->unpin_work; | 3986 | work = intel_crtc->unpin_work; |
3987 | if (work == NULL || !work->pending) { | 3987 | if (work == NULL || !work->pending) { |
3988 | if (work && !work->pending) { | ||
3989 | obj_priv = work->obj->driver_private; | ||
3990 | DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n", | ||
3991 | obj_priv, | ||
3992 | atomic_read(&obj_priv->pending_flip)); | ||
3993 | } | ||
3988 | spin_unlock_irqrestore(&dev->event_lock, flags); | 3994 | spin_unlock_irqrestore(&dev->event_lock, flags); |
3989 | return; | 3995 | return; |
3990 | } | 3996 | } |
@@ -4006,7 +4012,10 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
4006 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4012 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4007 | 4013 | ||
4008 | obj_priv = work->obj->driver_private; | 4014 | obj_priv = work->obj->driver_private; |
4009 | if (atomic_dec_and_test(&obj_priv->pending_flip)) | 4015 | |
4016 | /* Initial scanout buffer will have a 0 pending flip count */ | ||
4017 | if ((atomic_read(&obj_priv->pending_flip) == 0) || | ||
4018 | atomic_dec_and_test(&obj_priv->pending_flip)) | ||
4010 | DRM_WAKEUP(&dev_priv->pending_flip_queue); | 4019 | DRM_WAKEUP(&dev_priv->pending_flip_queue); |
4011 | schedule_work(&work->work); | 4020 | schedule_work(&work->work); |
4012 | } | 4021 | } |
@@ -4019,8 +4028,11 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) | |||
4019 | unsigned long flags; | 4028 | unsigned long flags; |
4020 | 4029 | ||
4021 | spin_lock_irqsave(&dev->event_lock, flags); | 4030 | spin_lock_irqsave(&dev->event_lock, flags); |
4022 | if (intel_crtc->unpin_work) | 4031 | if (intel_crtc->unpin_work) { |
4023 | intel_crtc->unpin_work->pending = 1; | 4032 | intel_crtc->unpin_work->pending = 1; |
4033 | } else { | ||
4034 | DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); | ||
4035 | } | ||
4024 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4036 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4025 | } | 4037 | } |
4026 | 4038 | ||
@@ -4054,6 +4066,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4054 | /* We borrow the event spin lock for protecting unpin_work */ | 4066 | /* We borrow the event spin lock for protecting unpin_work */ |
4055 | spin_lock_irqsave(&dev->event_lock, flags); | 4067 | spin_lock_irqsave(&dev->event_lock, flags); |
4056 | if (intel_crtc->unpin_work) { | 4068 | if (intel_crtc->unpin_work) { |
4069 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); | ||
4057 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4070 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4058 | kfree(work); | 4071 | kfree(work); |
4059 | mutex_unlock(&dev->struct_mutex); | 4072 | mutex_unlock(&dev->struct_mutex); |
@@ -4067,7 +4080,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4067 | 4080 | ||
4068 | ret = intel_pin_and_fence_fb_obj(dev, obj); | 4081 | ret = intel_pin_and_fence_fb_obj(dev, obj); |
4069 | if (ret != 0) { | 4082 | if (ret != 0) { |
4083 | DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n", | ||
4084 | obj->driver_private); | ||
4070 | kfree(work); | 4085 | kfree(work); |
4086 | intel_crtc->unpin_work = NULL; | ||
4071 | mutex_unlock(&dev->struct_mutex); | 4087 | mutex_unlock(&dev->struct_mutex); |
4072 | return ret; | 4088 | return ret; |
4073 | } | 4089 | } |