aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-07-05 12:14:01 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-07-20 06:21:37 -0400
commit12f55818bac7b89c00e43504d12a45c47e49d282 (patch)
tree154db5ac0bc118101c97404d658c2827f004cfcd /drivers/gpu/drm/i915/intel_ringbuffer.c
parent67b1b57182972f3c89c1ff9a58951582cb6bcca7 (diff)
drm/i915: Add comments to explain the BSD tail write workaround
Having had to dive into the bspec to understand what each stage of the workaround meant, and how that the ring broadcasting IDLE corresponded with the GT powering down the ring (i.e. rc6) add comments to aide the next reader. And since the register "is used to control all aspects of PSMI and power saving functions" that makes it quite interesting to inspect with regards to RC6 hangs, so add it to the error-state. v2: Rediscover the piece of magic, set the RNCID to 0 before waiting for the ring to wake up. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> 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.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index d42d821c64d6..ddc48590ea60 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1270,20 +1270,31 @@ static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
1270 drm_i915_private_t *dev_priv = ring->dev->dev_private; 1270 drm_i915_private_t *dev_priv = ring->dev->dev_private;
1271 1271
1272 /* Every tail move must follow the sequence below */ 1272 /* Every tail move must follow the sequence below */
1273
1274 /* Disable notification that the ring is IDLE. The GT
1275 * will then assume that it is busy and bring it out of rc6.
1276 */
1273 I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1277 I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1274 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | 1278 _MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
1275 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); 1279
1276 I915_WRITE(GEN6_BSD_RNCID, 0x0); 1280 /* Clear the context id. Here be magic! */
1281 I915_WRITE64(GEN6_BSD_RNCID, 0x0);
1277 1282
1283 /* Wait for the ring not to be idle, i.e. for it to wake up. */
1278 if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & 1284 if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
1279 GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, 1285 GEN6_BSD_SLEEP_INDICATOR) == 0,
1280 50)) 1286 50))
1281 DRM_ERROR("timed out waiting for IDLE Indicator\n"); 1287 DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
1282 1288
1289 /* Now that the ring is fully powered up, update the tail */
1283 I915_WRITE_TAIL(ring, value); 1290 I915_WRITE_TAIL(ring, value);
1291 POSTING_READ(RING_TAIL(ring->mmio_base));
1292
1293 /* Let the ring send IDLE messages to the GT again,
1294 * and so let it sleep to conserve power when idle.
1295 */
1284 I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, 1296 I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
1285 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | 1297 _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
1286 GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
1287} 1298}
1288 1299
1289static int gen6_ring_flush(struct intel_ring_buffer *ring, 1300static int gen6_ring_flush(struct intel_ring_buffer *ring,