aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c39
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h5
4 files changed, 41 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 8afc0dd7de6..e6a11ca85ea 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
317 seq_printf(m, "No flip due on pipe %c (plane %c)\n", 317 seq_printf(m, "No flip due on pipe %c (plane %c)\n",
318 pipe, plane); 318 pipe, plane);
319 } else { 319 } else {
320 if (!work->pending) { 320 if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
321 seq_printf(m, "Flip queued on pipe %c (plane %c)\n", 321 seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
322 pipe, plane); 322 pipe, plane);
323 } else { 323 } else {
@@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
328 seq_printf(m, "Stall check enabled, "); 328 seq_printf(m, "Stall check enabled, ");
329 else 329 else
330 seq_printf(m, "Stall check waiting for page flip ioctl, "); 330 seq_printf(m, "Stall check waiting for page flip ioctl, ");
331 seq_printf(m, "%d prepares\n", work->pending); 331 seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
332 332
333 if (work->old_fb_obj) { 333 if (work->old_fb_obj) {
334 struct drm_i915_gem_object *obj = work->old_fb_obj; 334 struct drm_i915_gem_object *obj = work->old_fb_obj;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 6cd3dc94b47..a4dc97f8b9f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1466,7 +1466,9 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
1466 spin_lock_irqsave(&dev->event_lock, flags); 1466 spin_lock_irqsave(&dev->event_lock, flags);
1467 work = intel_crtc->unpin_work; 1467 work = intel_crtc->unpin_work;
1468 1468
1469 if (work == NULL || work->pending || !work->enable_stall_check) { 1469 if (work == NULL ||
1470 atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE ||
1471 !work->enable_stall_check) {
1470 /* Either the pending flip IRQ arrived, or we're too early. Don't check */ 1472 /* Either the pending flip IRQ arrived, or we're too early. Don't check */
1471 spin_unlock_irqrestore(&dev->event_lock, flags); 1473 spin_unlock_irqrestore(&dev->event_lock, flags);
1472 return; 1474 return;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 78d12c47147..f8ee3d16109 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6929,11 +6929,18 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
6929 6929
6930 spin_lock_irqsave(&dev->event_lock, flags); 6930 spin_lock_irqsave(&dev->event_lock, flags);
6931 work = intel_crtc->unpin_work; 6931 work = intel_crtc->unpin_work;
6932 if (work == NULL || !work->pending) { 6932
6933 /* Ensure we don't miss a work->pending update ... */
6934 smp_rmb();
6935
6936 if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
6933 spin_unlock_irqrestore(&dev->event_lock, flags); 6937 spin_unlock_irqrestore(&dev->event_lock, flags);
6934 return; 6938 return;
6935 } 6939 }
6936 6940
6941 /* and that the unpin work is consistent wrt ->pending. */
6942 smp_rmb();
6943
6937 intel_crtc->unpin_work = NULL; 6944 intel_crtc->unpin_work = NULL;
6938 6945
6939 if (work->event) 6946 if (work->event)
@@ -6977,16 +6984,25 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
6977 to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); 6984 to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
6978 unsigned long flags; 6985 unsigned long flags;
6979 6986
6987 /* NB: An MMIO update of the plane base pointer will also
6988 * generate a page-flip completion irq, i.e. every modeset
6989 * is also accompanied by a spurious intel_prepare_page_flip().
6990 */
6980 spin_lock_irqsave(&dev->event_lock, flags); 6991 spin_lock_irqsave(&dev->event_lock, flags);
6981 if (intel_crtc->unpin_work) { 6992 if (intel_crtc->unpin_work)
6982 if ((++intel_crtc->unpin_work->pending) > 1) 6993 atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
6983 DRM_ERROR("Prepared flip multiple times\n");
6984 } else {
6985 DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
6986 }
6987 spin_unlock_irqrestore(&dev->event_lock, flags); 6994 spin_unlock_irqrestore(&dev->event_lock, flags);
6988} 6995}
6989 6996
6997inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
6998{
6999 /* Ensure that the work item is consistent when activating it ... */
7000 smp_wmb();
7001 atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
7002 /* and that it is marked active as soon as the irq could fire. */
7003 smp_wmb();
7004}
7005
6990static int intel_gen2_queue_flip(struct drm_device *dev, 7006static int intel_gen2_queue_flip(struct drm_device *dev,
6991 struct drm_crtc *crtc, 7007 struct drm_crtc *crtc,
6992 struct drm_framebuffer *fb, 7008 struct drm_framebuffer *fb,
@@ -7020,6 +7036,8 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
7020 intel_ring_emit(ring, fb->pitches[0]); 7036 intel_ring_emit(ring, fb->pitches[0]);
7021 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); 7037 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
7022 intel_ring_emit(ring, 0); /* aux display base address, unused */ 7038 intel_ring_emit(ring, 0); /* aux display base address, unused */
7039
7040 intel_mark_page_flip_active(intel_crtc);
7023 intel_ring_advance(ring); 7041 intel_ring_advance(ring);
7024 return 0; 7042 return 0;
7025 7043
@@ -7060,6 +7078,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
7060 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); 7078 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
7061 intel_ring_emit(ring, MI_NOOP); 7079 intel_ring_emit(ring, MI_NOOP);
7062 7080
7081 intel_mark_page_flip_active(intel_crtc);
7063 intel_ring_advance(ring); 7082 intel_ring_advance(ring);
7064 return 0; 7083 return 0;
7065 7084
@@ -7106,6 +7125,8 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
7106 pf = 0; 7125 pf = 0;
7107 pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; 7126 pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
7108 intel_ring_emit(ring, pf | pipesrc); 7127 intel_ring_emit(ring, pf | pipesrc);
7128
7129 intel_mark_page_flip_active(intel_crtc);
7109 intel_ring_advance(ring); 7130 intel_ring_advance(ring);
7110 return 0; 7131 return 0;
7111 7132
@@ -7148,6 +7169,8 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
7148 pf = 0; 7169 pf = 0;
7149 pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; 7170 pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
7150 intel_ring_emit(ring, pf | pipesrc); 7171 intel_ring_emit(ring, pf | pipesrc);
7172
7173 intel_mark_page_flip_active(intel_crtc);
7151 intel_ring_advance(ring); 7174 intel_ring_advance(ring);
7152 return 0; 7175 return 0;
7153 7176
@@ -7202,6 +7225,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
7202 intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); 7225 intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
7203 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); 7226 intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
7204 intel_ring_emit(ring, (MI_NOOP)); 7227 intel_ring_emit(ring, (MI_NOOP));
7228
7229 intel_mark_page_flip_active(intel_crtc);
7205 intel_ring_advance(ring); 7230 intel_ring_advance(ring);
7206 return 0; 7231 return 0;
7207 7232
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 522061ca068..3915ca9abd4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -401,7 +401,10 @@ struct intel_unpin_work {
401 struct drm_i915_gem_object *old_fb_obj; 401 struct drm_i915_gem_object *old_fb_obj;
402 struct drm_i915_gem_object *pending_flip_obj; 402 struct drm_i915_gem_object *pending_flip_obj;
403 struct drm_pending_vblank_event *event; 403 struct drm_pending_vblank_event *event;
404 int pending; 404 atomic_t pending;
405#define INTEL_FLIP_INACTIVE 0
406#define INTEL_FLIP_PENDING 1
407#define INTEL_FLIP_COMPLETE 2
405 bool enable_stall_check; 408 bool enable_stall_check;
406}; 409};
407 410