Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 345651
b: refs/heads/master
c: e7d841c
h: refs/heads/master
i:
  345649: fc8b345
  345647: e1a113f
v: v3
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Dec 6, 2012
1 parent d6b8477 commit f5d2bfb
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ebf69cb8331d7336e4bcd442a2ca69bb61739a58
refs/heads/master: e7d841ca03b7ab668620045cd7b428eda9f41601
4 changes: 2 additions & 2 deletions trunk/drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
seq_printf(m, "No flip due on pipe %c (plane %c)\n",
pipe, plane);
} else {
if (!work->pending) {
if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
pipe, plane);
} else {
Expand All @@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
seq_printf(m, "Stall check enabled, ");
else
seq_printf(m, "Stall check waiting for page flip ioctl, ");
seq_printf(m, "%d prepares\n", work->pending);
seq_printf(m, "%d prepares\n", atomic_read(&work->pending));

if (work->old_fb_obj) {
struct drm_i915_gem_object *obj = work->old_fb_obj;
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,9 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;

if (work == NULL || work->pending || !work->enable_stall_check) {
if (work == NULL ||
atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE ||
!work->enable_stall_check) {
/* Either the pending flip IRQ arrived, or we're too early. Don't check */
spin_unlock_irqrestore(&dev->event_lock, flags);
return;
Expand Down
39 changes: 32 additions & 7 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -6929,11 +6929,18 @@ static void do_intel_finish_page_flip(struct drm_device *dev,

spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
if (work == NULL || !work->pending) {

/* Ensure we don't miss a work->pending update ... */
smp_rmb();

if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
spin_unlock_irqrestore(&dev->event_lock, flags);
return;
}

/* and that the unpin work is consistent wrt ->pending. */
smp_rmb();

intel_crtc->unpin_work = NULL;

if (work->event)
Expand Down Expand Up @@ -6977,16 +6984,25 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
unsigned long flags;

/* NB: An MMIO update of the plane base pointer will also
* generate a page-flip completion irq, i.e. every modeset
* is also accompanied by a spurious intel_prepare_page_flip().
*/
spin_lock_irqsave(&dev->event_lock, flags);
if (intel_crtc->unpin_work) {
if ((++intel_crtc->unpin_work->pending) > 1)
DRM_ERROR("Prepared flip multiple times\n");
} else {
DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
}
if (intel_crtc->unpin_work)
atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
spin_unlock_irqrestore(&dev->event_lock, flags);
}

inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
{
/* Ensure that the work item is consistent when activating it ... */
smp_wmb();
atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
/* and that it is marked active as soon as the irq could fire. */
smp_wmb();
}

static int intel_gen2_queue_flip(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
Expand Down Expand Up @@ -7020,6 +7036,8 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, fb->pitches[0]);
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
intel_ring_emit(ring, 0); /* aux display base address, unused */

intel_mark_page_flip_active(intel_crtc);
intel_ring_advance(ring);
return 0;

Expand Down Expand Up @@ -7060,6 +7078,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
intel_ring_emit(ring, MI_NOOP);

intel_mark_page_flip_active(intel_crtc);
intel_ring_advance(ring);
return 0;

Expand Down Expand Up @@ -7106,6 +7125,8 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
pf = 0;
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);

intel_mark_page_flip_active(intel_crtc);
intel_ring_advance(ring);
return 0;

Expand Down Expand Up @@ -7148,6 +7169,8 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
pf = 0;
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
intel_ring_emit(ring, pf | pipesrc);

intel_mark_page_flip_active(intel_crtc);
intel_ring_advance(ring);
return 0;

Expand Down Expand Up @@ -7202,6 +7225,8 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
intel_ring_emit(ring, (MI_NOOP));

intel_mark_page_flip_active(intel_crtc);
intel_ring_advance(ring);
return 0;

Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,10 @@ struct intel_unpin_work {
struct drm_i915_gem_object *old_fb_obj;
struct drm_i915_gem_object *pending_flip_obj;
struct drm_pending_vblank_event *event;
int pending;
atomic_t pending;
#define INTEL_FLIP_INACTIVE 0
#define INTEL_FLIP_PENDING 1
#define INTEL_FLIP_COMPLETE 2
bool enable_stall_check;
};

Expand Down

0 comments on commit f5d2bfb

Please sign in to comment.