aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
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
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')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c1
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h8
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c27
5 files changed, 26 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 2909b123baf5..359f6e8b9b00 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -676,6 +676,7 @@ static void i915_ring_error_state(struct seq_file *m,
676 seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); 676 seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
677 seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]); 677 seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
678 if (INTEL_INFO(dev)->gen >= 6) { 678 if (INTEL_INFO(dev)->gen >= 6) {
679 seq_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
679 seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]); 680 seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
680 seq_printf(m, " SYNC_0: 0x%08x\n", 681 seq_printf(m, " SYNC_0: 0x%08x\n",
681 error->semaphore_mboxes[ring][0]); 682 error->semaphore_mboxes[ring][0]);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 476c64c4844c..627fe35781b4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -190,6 +190,7 @@ struct drm_i915_error_state {
190 u32 instdone[I915_NUM_RINGS]; 190 u32 instdone[I915_NUM_RINGS];
191 u32 acthd[I915_NUM_RINGS]; 191 u32 acthd[I915_NUM_RINGS];
192 u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1]; 192 u32 semaphore_mboxes[I915_NUM_RINGS][I915_NUM_RINGS - 1];
193 u32 rc_psmi[I915_NUM_RINGS]; /* sleep state */
193 /* our own tracking of ring head and tail */ 194 /* our own tracking of ring head and tail */
194 u32 cpu_ring_head[I915_NUM_RINGS]; 195 u32 cpu_ring_head[I915_NUM_RINGS];
195 u32 cpu_ring_tail[I915_NUM_RINGS]; 196 u32 cpu_ring_tail[I915_NUM_RINGS];
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 23f2ea0f0651..566f61b9e47c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1067,6 +1067,7 @@ static void i915_record_ring_state(struct drm_device *dev,
1067 struct drm_i915_private *dev_priv = dev->dev_private; 1067 struct drm_i915_private *dev_priv = dev->dev_private;
1068 1068
1069 if (INTEL_INFO(dev)->gen >= 6) { 1069 if (INTEL_INFO(dev)->gen >= 6) {
1070 error->rc_psmi[ring->id] = I915_READ(ring->mmio_base + 0x50);
1070 error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring)); 1071 error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));
1071 error->semaphore_mboxes[ring->id][0] 1072 error->semaphore_mboxes[ring->id][0]
1072 = I915_READ(RING_SYNC_0(ring->mmio_base)); 1073 = I915_READ(RING_SYNC_0(ring->mmio_base));
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ac5688e8b01d..7aa6e97c2c72 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -690,10 +690,10 @@
690#define GEN6_BLITTER_FBC_NOTIFY (1<<3) 690#define GEN6_BLITTER_FBC_NOTIFY (1<<3)
691 691
692#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 692#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
693#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) 693#define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0)
694#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) 694#define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2)
695#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 695#define GEN6_BSD_SLEEP_INDICATOR (1 << 3)
696#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) 696#define GEN6_BSD_GO_INDICATOR (1 << 4)
697 697
698#define GEN6_BSD_HWSTAM 0x12098 698#define GEN6_BSD_HWSTAM 0x12098
699#define GEN6_BSD_IMR 0x120a8 699#define GEN6_BSD_IMR 0x120a8
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,