summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 15:52:55 (GMT)
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 16:14:49 (GMT)
commit9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch)
treed19670de2256f8187321de3a41fa4a10d3c8e402 /drivers/gpu/drm/i915/intel_ringbuffer.c
parente21af88d39796c907c38648c824be3d646ffbe35 (diff)
parent28a4d5675857f6386930a324317281cb8ed1e5d0 (diff)
downloadlinux-fsl-qoriq-9edd576d89a5b6d3e136d7dcab654d887c0d25b7.tar.xz
Merge remote-tracking branch 'airlied/drm-fixes' into drm-intel-next-queued
Back-merge from drm-fixes into drm-intel-next to sort out two things: - interlaced support: -fixes contains a bugfix to correctly clear interlaced configuration bits in case the bios sets up an interlaced mode and we want to set up the progressive mode (current kernels don't support interlaced). The actual feature work to support interlaced depends upon (and conflicts with) this bugfix. - forcewake voodoo to workaround missed IRQ issues: -fixes only enabled this for ivybridge, but some recent bug reports indicate that we need this on Sandybridge, too. But in a slightly different flavour and with other fixes and reworks on top. Additionally there are some forcewake cleanup patches heading to -next that would conflict with currrent -fixes. Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6e80f83..4956f1b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -634,6 +634,19 @@ render_ring_add_request(struct intel_ring_buffer *ring,
}
static u32
+gen6_ring_get_seqno(struct intel_ring_buffer *ring)
+{
+ struct drm_device *dev = ring->dev;
+
+ /* Workaround to force correct ordering between irq and seqno writes on
+ * ivb (and maybe also on snb) by reading from a CS register (like
+ * ACTHD) before reading the status page. */
+ if (IS_GEN7(dev))
+ intel_ring_get_active_head(ring);
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static u32
ring_get_seqno(struct intel_ring_buffer *ring)
{
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
@@ -790,17 +803,6 @@ ring_add_request(struct intel_ring_buffer *ring,
}
static bool
-gen7_blt_ring_get_irq(struct intel_ring_buffer *ring)
-{
- /* The BLT ring on IVB appears to have broken synchronization
- * between the seqno write and the interrupt, so that the
- * interrupt appears first. Returning false here makes
- * i915_wait_request() do a polling loop, instead.
- */
- return false;
-}
-
-static bool
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
{
struct drm_device *dev = ring->dev;
@@ -809,6 +811,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
if (!dev->irq_enabled)
return false;
+ /* It looks like we need to prevent the gt from suspending while waiting
+ * for an notifiy irq, otherwise irqs seem to get lost on at least the
+ * blt/bsd rings on ivb. */
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_get(dev_priv);
+
spin_lock(&ring->irq_lock);
if (ring->irq_refcount++ == 0) {
ring->irq_mask &= ~rflag;
@@ -833,6 +841,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
ironlake_disable_irq(dev_priv, gflag);
}
spin_unlock(&ring->irq_lock);
+
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_put(dev_priv);
}
static bool
@@ -1339,7 +1350,7 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
.write_tail = gen6_bsd_ring_write_tail,
.flush = gen6_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = gen6_bsd_ring_get_irq,
.irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
@@ -1398,7 +1409,7 @@ static const struct intel_ring_buffer gen6_blt_ring = {
.write_tail = ring_write_tail,
.flush = blt_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = blt_ring_get_irq,
.irq_put = blt_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
@@ -1420,6 +1431,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
+ ring->get_seqno = gen6_ring_get_seqno;
} else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request;
ring->get_seqno = pc_render_get_seqno;
@@ -1498,8 +1510,5 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
*ring = gen6_blt_ring;
- if (IS_GEN7(dev))
- ring->irq_get = gen7_blt_ring_get_irq;
-
return intel_init_ring_buffer(dev, ring);
}