From 8693a824873a0a97be77c1d5f1e98777f06f7305 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Fri, 3 May 2013 18:48:11 +0100 Subject: drm/i915: Add references to some workaround we implement We did not mention the workaround name when implementing those. This should help us track what we already implement. Signed-off-by: Damien Lespiau Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1d5d613eb6b..3d2c236e15a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -515,6 +515,8 @@ static int init_render_ring(struct intel_ring_buffer *ring) /* We need to disable the AsyncFlip performance optimisations in order * to use MI_WAIT_FOR_EVENT within the CS. It should already be * programmed to '1' on all products. + * + * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv */ if (INTEL_INFO(dev)->gen >= 6) I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); -- cgit v1.2.3-70-g09d2 From 92cab7345131db7af18f630a799ce6b2e8e624c5 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 24 May 2013 17:16:07 +0300 Subject: drm/i915: track ring progression using seqnos Instead of relying in acthd, track ring seqno progression to detect if ring has hung. v2: put hangcheck stuff inside struct (Chris Wilson) v3: initialize hangcheck.seqno (Ben Widawsky) Signed-off-by: Mika Kuoppala Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_irq.c | 30 +++++++++++++----------------- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.h | 6 ++++++ 4 files changed, 20 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e09c54c73a2..e417049ea58 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -842,8 +842,6 @@ struct i915_gpu_error { #define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD) struct timer_list hangcheck_timer; int hangcheck_count; - uint32_t last_acthd[I915_NUM_RINGS]; - uint32_t prev_instdone[I915_NUM_INSTDONE_REG]; /* For reset and error_state handling. */ spinlock_t lock; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0e5c9b0cc5a..004ad345599 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2384,22 +2384,19 @@ void i915_hangcheck_elapsed(unsigned long data) { struct drm_device *dev = (struct drm_device *)data; drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t acthd[I915_NUM_RINGS], instdone[I915_NUM_INSTDONE_REG]; struct intel_ring_buffer *ring; bool err = false, idle; int i; + u32 seqno[I915_NUM_RINGS]; + bool work_done; if (!i915_enable_hangcheck) return; - memset(acthd, 0, sizeof(acthd)); idle = true; for_each_ring(ring, dev_priv, i) { - u32 seqno; - - seqno = ring->get_seqno(ring, false); - idle &= i915_hangcheck_ring_idle(ring, seqno, &err); - acthd[i] = intel_ring_get_active_head(ring); + seqno[i] = ring->get_seqno(ring, false); + idle &= i915_hangcheck_ring_idle(ring, seqno[i], &err); } /* If all work is done then ACTHD clearly hasn't advanced. */ @@ -2415,20 +2412,19 @@ void i915_hangcheck_elapsed(unsigned long data) return; } - i915_get_extra_instdone(dev, instdone); - if (memcmp(dev_priv->gpu_error.last_acthd, acthd, - sizeof(acthd)) == 0 && - memcmp(dev_priv->gpu_error.prev_instdone, instdone, - sizeof(instdone)) == 0) { + work_done = false; + for_each_ring(ring, dev_priv, i) { + if (ring->hangcheck.seqno != seqno[i]) { + work_done = true; + ring->hangcheck.seqno = seqno[i]; + } + } + + if (!work_done) { if (i915_hangcheck_hung(dev)) return; } else { dev_priv->gpu_error.hangcheck_count = 0; - - memcpy(dev_priv->gpu_error.last_acthd, acthd, - sizeof(acthd)); - memcpy(dev_priv->gpu_error.prev_instdone, instdone, - sizeof(instdone)); } repeat: diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 3d2c236e15a..5698faeee6f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1502,6 +1502,7 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) } ring->set_seqno(ring, seqno); + ring->hangcheck.seqno = seqno; } void intel_ring_advance(struct intel_ring_buffer *ring) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index dac1614a1bc..ef374a89210 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -37,6 +37,10 @@ struct intel_hw_status_page { #define I915_READ_SYNC_0(ring) I915_READ(RING_SYNC_0((ring)->mmio_base)) #define I915_READ_SYNC_1(ring) I915_READ(RING_SYNC_1((ring)->mmio_base)) +struct intel_ring_hangcheck { + u32 seqno; +}; + struct intel_ring_buffer { const char *name; enum intel_ring_id { @@ -137,6 +141,8 @@ struct intel_ring_buffer { struct i915_hw_context *default_context; struct i915_hw_context *last_context; + struct intel_ring_hangcheck hangcheck; + void *private; }; -- cgit v1.2.3-70-g09d2 From 56b085a01befc7907d270e9acb349580015e7bad Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 28 May 2013 17:51:44 +0800 Subject: drm/i915: fix error return code in init_pipe_control() Fix to return -ENOMEM in the kmap() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5698faeee6f..9b97cf66a5a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -464,9 +464,11 @@ init_pipe_control(struct intel_ring_buffer *ring) goto err_unref; pc->gtt_offset = obj->gtt_offset; - pc->cpu_page = kmap(sg_page(obj->pages->sgl)); - if (pc->cpu_page == NULL) + pc->cpu_page = kmap(sg_page(obj->pages->sgl)); + if (pc->cpu_page == NULL) { + ret = -ENOMEM; goto err_unpin; + } DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", ring->name, pc->gtt_offset); -- cgit v1.2.3-70-g09d2 From 5586181fce2b2e89a0e281d78ffbdfa103bb0dde Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:17 -0700 Subject: drm/i915: Comments for semaphore clarification Semaphores are tied very closely to the rings in the GPU. Trivial patch adds comments to the existing code so that when we add new rings we can include comments there as well. It also helps distinguish the ring to semaphore mailbox interactions by using the ringname in the semaphore data structures. This patch should have no functional impact. v2: The English parts (as opposed to register names) of the comments were reversed. (Damien) Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 12 ++++++------ drivers/gpu/drm/i915/intel_ringbuffer.c | 18 +++++++++--------- drivers/gpu/drm/i915/intel_ringbuffer.h | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dbd9de5abde..6579d0c0d2f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -265,12 +265,12 @@ #define MI_SEMAPHORE_UPDATE (1<<21) #define MI_SEMAPHORE_COMPARE (1<<20) #define MI_SEMAPHORE_REGISTER (1<<18) -#define MI_SEMAPHORE_SYNC_RV (2<<16) -#define MI_SEMAPHORE_SYNC_RB (0<<16) -#define MI_SEMAPHORE_SYNC_VR (0<<16) -#define MI_SEMAPHORE_SYNC_VB (2<<16) -#define MI_SEMAPHORE_SYNC_BR (2<<16) -#define MI_SEMAPHORE_SYNC_BV (0<<16) +#define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ +#define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ +#define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ +#define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ +#define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ +#define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ #define MI_SEMAPHORE_SYNC_INVALID (1<<0) /* * 3D instructions used by the kernel diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9b97cf66a5a..2d2a3622639 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1671,9 +1671,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_RB; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; ring->signal_mbox[0] = GEN6_VRSYNC; ring->signal_mbox[1] = GEN6_BRSYNC; } else if (IS_GEN5(dev)) { @@ -1830,9 +1830,9 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_VR; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_VB; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; ring->signal_mbox[0] = GEN6_RVSYNC; ring->signal_mbox[1] = GEN6_BVSYNC; } else { @@ -1876,9 +1876,9 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; - ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_BR; - ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_BV; - ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; ring->signal_mbox[0] = GEN6_RBSYNC; ring->signal_mbox[1] = GEN6_VBSYNC; ring->init = init_ring_common; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index ef374a89210..24268fbe685 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -105,8 +105,8 @@ struct intel_ring_buffer { int (*sync_to)(struct intel_ring_buffer *ring, struct intel_ring_buffer *to, u32 seqno); - - u32 semaphore_register[3]; /*our mbox written by others */ + /* our mbox written by others */ + u32 semaphore_register[I915_NUM_RINGS]; u32 signal_mbox[2]; /* mboxes this ring signals to */ /** * List of objects currently involved in rendering from the -- cgit v1.2.3-70-g09d2 From ad776f8b09d66e0145479fdbde2a710e5892441f Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:18 -0700 Subject: drm/i915: Semaphore MBOX update generalization This replaces the existing MBOX update code with a more generalized calculation for emitting mbox updates. We also create a sentinel for doing the updates so we can more abstractly deal with the rings. When doing MBOX updates the code must be aware of the /other/ rings. Until now the platforms which supported semaphores had a fixed number of rings and so it made sense for the code to be very specialized (hardcoded). The patch does contain a functional change, but should have no behavioral changes. Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 43 ++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.h | 5 +++- 3 files changed, 34 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6579d0c0d2f..19f8e51d2bd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -593,6 +593,7 @@ #define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) #define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) #define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define GEN6_NOSYNC 0 #define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) #define RING_MAX_IDLE(base) ((base)+0x54) #define RING_HWS_PGA(base) ((base)+0x80) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 2d2a3622639..5df179127e8 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -582,9 +582,16 @@ static void update_mboxes(struct intel_ring_buffer *ring, u32 mmio_offset) { +/* NB: In order to be able to do semaphore MBOX updates for varying number + * of rings, it's easiest if we round up each individual update to a + * multiple of 2 (since ring updates must always be a multiple of 2) + * even though the actual update only requires 3 dwords. + */ +#define MBOX_UPDATE_DWORDS 4 intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); intel_ring_emit(ring, mmio_offset); intel_ring_emit(ring, ring->outstanding_lazy_request); + intel_ring_emit(ring, MI_NOOP); } /** @@ -599,19 +606,24 @@ update_mboxes(struct intel_ring_buffer *ring, static int gen6_add_request(struct intel_ring_buffer *ring) { - u32 mbox1_reg; - u32 mbox2_reg; - int ret; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *useless; + int i, ret; - ret = intel_ring_begin(ring, 10); + ret = intel_ring_begin(ring, ((I915_NUM_RINGS-1) * + MBOX_UPDATE_DWORDS) + + 4); if (ret) return ret; +#undef MBOX_UPDATE_DWORDS - mbox1_reg = ring->signal_mbox[0]; - mbox2_reg = ring->signal_mbox[1]; + for_each_ring(useless, dev_priv, i) { + u32 mbox_reg = ring->signal_mbox[i]; + if (mbox_reg != GEN6_NOSYNC) + update_mboxes(ring, mbox_reg); + } - update_mboxes(ring, mbox1_reg); - update_mboxes(ring, mbox2_reg); intel_ring_emit(ring, MI_STORE_DWORD_INDEX); intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); intel_ring_emit(ring, ring->outstanding_lazy_request); @@ -1674,8 +1686,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; - ring->signal_mbox[0] = GEN6_VRSYNC; - ring->signal_mbox[1] = GEN6_BRSYNC; + ring->signal_mbox[RCS] = GEN6_NOSYNC; + ring->signal_mbox[VCS] = GEN6_VRSYNC; + ring->signal_mbox[BCS] = GEN6_BRSYNC; } else if (IS_GEN5(dev)) { ring->add_request = pc_render_add_request; ring->flush = gen4_render_ring_flush; @@ -1833,8 +1846,9 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; - ring->signal_mbox[0] = GEN6_RVSYNC; - ring->signal_mbox[1] = GEN6_BVSYNC; + ring->signal_mbox[RCS] = GEN6_RVSYNC; + ring->signal_mbox[VCS] = GEN6_NOSYNC; + ring->signal_mbox[BCS] = GEN6_BVSYNC; } else { ring->mmio_base = BSD_RING_BASE; ring->flush = bsd_ring_flush; @@ -1879,8 +1893,9 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; - ring->signal_mbox[0] = GEN6_RBSYNC; - ring->signal_mbox[1] = GEN6_VBSYNC; + ring->signal_mbox[RCS] = GEN6_RBSYNC; + ring->signal_mbox[VCS] = GEN6_VBSYNC; + ring->signal_mbox[BCS] = GEN6_NOSYNC; ring->init = init_ring_common; return intel_init_ring_buffer(dev, ring); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 24268fbe685..f55d92eb6c2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -105,9 +105,12 @@ struct intel_ring_buffer { int (*sync_to)(struct intel_ring_buffer *ring, struct intel_ring_buffer *to, u32 seqno); + /* our mbox written by others */ u32 semaphore_register[I915_NUM_RINGS]; - u32 signal_mbox[2]; /* mboxes this ring signals to */ + /* mboxes this ring signals to */ + u32 signal_mbox[I915_NUM_RINGS]; + /** * List of objects currently involved in rendering from the * ringbuffer. -- cgit v1.2.3-70-g09d2 From 4a3dd19d94c65323d71b2ffc7e63940f00acfb47 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:19 -0700 Subject: drm/i915: Introduce VECS: the 4th ring The video enhancement command streamer is a new ring on HSW which does what it sounds like it does. This patch provides the most minimal inception of the ring. In order to support a new ring, we need to bump the number. The patch may look trivial to the untrained eye, but bumping the number of rings is a bit scary. As such the patch is not terribly useful by itself, but a pretty nice place to find issues during a bisection. Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5df179127e8..ead979a9410 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -915,6 +915,8 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) case VCS: mmio = BSD_HWS_PGA_GEN7; break; + case VECS: + BUG(); } } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index f55d92eb6c2..73619cb3463 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -47,8 +47,9 @@ struct intel_ring_buffer { RCS = 0x0, VCS, BCS, + VECS, } id; -#define I915_NUM_RINGS 3 +#define I915_NUM_RINGS 4 u32 mmio_base; void __iomem *virtual_start; struct drm_device *dev; -- cgit v1.2.3-70-g09d2 From 1950de14fd1b8ea27a411929156c7eccee2ad7c3 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:20 -0700 Subject: drm/i915: Add VECS semaphore bits Like the other rings, the VECS supports semaphores. The semaphore stuff is a bit wonky so this patch on it's own should be nice for review. This patch should have no functional impact. v2: Fix the English parts of clarification (again, register names were right, text was reversed) (Damien) Restore the still valid invariant. (Damien) The bsd semaphore register should be MI_SEMAPHORE_SYNC_VVE (Damien) Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 40 ++++++++++++++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.c | 6 +++++ 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 19f8e51d2bd..41c5d45362b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -265,13 +265,19 @@ #define MI_SEMAPHORE_UPDATE (1<<21) #define MI_SEMAPHORE_COMPARE (1<<20) #define MI_SEMAPHORE_REGISTER (1<<18) -#define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ -#define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ -#define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ -#define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ -#define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ -#define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ -#define MI_SEMAPHORE_SYNC_INVALID (1<<0) +#define MI_SEMAPHORE_SYNC_VR (0<<16) /* RCS wait for VCS (RVSYNC) */ +#define MI_SEMAPHORE_SYNC_VER (1<<16) /* RCS wait for VECS (RVESYNC) */ +#define MI_SEMAPHORE_SYNC_BR (2<<16) /* RCS wait for BCS (RBSYNC) */ +#define MI_SEMAPHORE_SYNC_BV (0<<16) /* VCS wait for BCS (VBSYNC) */ +#define MI_SEMAPHORE_SYNC_VEV (1<<16) /* VCS wait for VECS (VVESYNC) */ +#define MI_SEMAPHORE_SYNC_RV (2<<16) /* VCS wait for RCS (VRSYNC) */ +#define MI_SEMAPHORE_SYNC_RB (0<<16) /* BCS wait for RCS (BRSYNC) */ +#define MI_SEMAPHORE_SYNC_VEB (1<<16) /* BCS wait for VECS (BVESYNC) */ +#define MI_SEMAPHORE_SYNC_VB (2<<16) /* BCS wait for VCS (BVSYNC) */ +#define MI_SEMAPHORE_SYNC_BVE (0<<16) /* VECS wait for BCS (VEBSYNC) */ +#define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */ +#define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */ +#define MI_SEMAPHORE_SYNC_INVALID (3<<16) /* * 3D instructions used by the kernel */ @@ -581,6 +587,7 @@ #define RENDER_RING_BASE 0x02000 #define BSD_RING_BASE 0x04000 #define GEN6_BSD_RING_BASE 0x12000 +#define VEBOX_RING_BASE 0x1a000 #define BLT_RING_BASE 0x22000 #define RING_TAIL(base) ((base)+0x30) #define RING_HEAD(base) ((base)+0x34) @@ -588,13 +595,20 @@ #define RING_CTL(base) ((base)+0x3c) #define RING_SYNC_0(base) ((base)+0x40) #define RING_SYNC_1(base) ((base)+0x44) -#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) -#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) -#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) -#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) -#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define RING_SYNC_2(base) ((base)+0x48) +#define GEN6_RVSYNC (RING_SYNC_0(RENDER_RING_BASE)) +#define GEN6_RBSYNC (RING_SYNC_1(RENDER_RING_BASE)) +#define GEN6_RVESYNC (RING_SYNC_2(RENDER_RING_BASE)) +#define GEN6_VBSYNC (RING_SYNC_0(GEN6_BSD_RING_BASE)) +#define GEN6_VRSYNC (RING_SYNC_1(GEN6_BSD_RING_BASE)) +#define GEN6_VVESYNC (RING_SYNC_2(GEN6_BSD_RING_BASE)) +#define GEN6_BRSYNC (RING_SYNC_0(BLT_RING_BASE)) +#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) +#define GEN6_BVESYNC (RING_SYNC_2(BLT_RING_BASE)) +#define GEN6_VEBSYNC (RING_SYNC_0(VEBOX_RING_BASE)) +#define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) +#define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) #define GEN6_NOSYNC 0 -#define GEN6_BVSYNC (RING_SYNC_1(BLT_RING_BASE)) #define RING_MAX_IDLE(base) ((base)+0x54) #define RING_HWS_PGA(base) ((base)+0x80) #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ead979a9410..93ccd1e982e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1688,9 +1688,11 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_INVALID; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_RV; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_RB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_RVE; ring->signal_mbox[RCS] = GEN6_NOSYNC; ring->signal_mbox[VCS] = GEN6_VRSYNC; ring->signal_mbox[BCS] = GEN6_BRSYNC; + ring->signal_mbox[VECS] = GEN6_VERSYNC; } else if (IS_GEN5(dev)) { ring->add_request = pc_render_add_request; ring->flush = gen4_render_ring_flush; @@ -1848,9 +1850,11 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_INVALID; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_VVE; ring->signal_mbox[RCS] = GEN6_RVSYNC; ring->signal_mbox[VCS] = GEN6_NOSYNC; ring->signal_mbox[BCS] = GEN6_BVSYNC; + ring->signal_mbox[VECS] = GEN6_VEVSYNC; } else { ring->mmio_base = BSD_RING_BASE; ring->flush = bsd_ring_flush; @@ -1895,9 +1899,11 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_BR; ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_BV; ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_INVALID; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_BVE; ring->signal_mbox[RCS] = GEN6_RBSYNC; ring->signal_mbox[VCS] = GEN6_VBSYNC; ring->signal_mbox[BCS] = GEN6_NOSYNC; + ring->signal_mbox[VECS] = GEN6_VEBSYNC; ring->init = init_ring_common; return intel_init_ring_buffer(dev, ring); -- cgit v1.2.3-70-g09d2 From ea251324cac6c1e0402db073e5193f33aedd94f3 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:21 -0700 Subject: drm/i915: Rename ring flush functions Historically we considered the render ring to have special flush semantics and everything else to fall under a more general umbrella. Probably by coincidence more than anything we decided to make the bsd ring have the default *other* flush. As the new vebox ring exposes, the bsd ring is actually the weird one. Doing this allows us to call gen6_ring_flush for the vebox because calling blt_ring_flush would be weird... This patch should have no functional change. Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 93ccd1e982e..3022e1579e5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1565,8 +1565,8 @@ static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, _MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE)); } -static int gen6_ring_flush(struct intel_ring_buffer *ring, - u32 invalidate, u32 flush) +static int gen6_bsd_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate, u32 flush) { uint32_t cmd; int ret; @@ -1637,8 +1637,8 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, /* Blitter support (SandyBridge+) */ -static int blt_ring_flush(struct intel_ring_buffer *ring, - u32 invalidate, u32 flush) +static int gen6_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate, u32 flush) { uint32_t cmd; int ret; @@ -1838,7 +1838,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) /* gen6 bsd needs a special wa for tail updates */ if (IS_GEN6(dev)) ring->write_tail = gen6_bsd_ring_write_tail; - ring->flush = gen6_ring_flush; + ring->flush = gen6_bsd_ring_flush; ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; @@ -1887,7 +1887,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->mmio_base = BLT_RING_BASE; ring->write_tail = ring_write_tail; - ring->flush = blt_ring_flush; + ring->flush = gen6_ring_flush; ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; -- cgit v1.2.3-70-g09d2 From 9a8a2213a778509b724c8fda04be70528a1f7130 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:23 -0700 Subject: drm/i915: Vebox ringbuffer init v2: Add set_seqno which didn't exist before rebase (Haihao) Signed-off-by: Ben Widawsky Reviewed-by: Damien Lespiau Signed-off-by: Xiang, Haihao Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 11 ++++++++++- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_ringbuffer.c | 35 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 46 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9496fb5f2fe..84d2aa21435 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4013,12 +4013,21 @@ static int i915_gem_init_rings(struct drm_device *dev) goto cleanup_bsd_ring; } + if (HAS_VEBOX(dev)) { + ret = intel_init_vebox_ring_buffer(dev); + if (ret) + goto cleanup_blt_ring; + } + + ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000)); if (ret) - goto cleanup_blt_ring; + goto cleanup_vebox_ring; return 0; +cleanup_vebox_ring: + intel_cleanup_ring_buffer(&dev_priv->ring[VECS]); cleanup_blt_ring: intel_cleanup_ring_buffer(&dev_priv->ring[BCS]); cleanup_bsd_ring: diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 41c5d45362b..a5717f17933 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -620,6 +620,7 @@ #define DONE_REG 0x40b0 #define BSD_HWS_PGA_GEN7 (0x04180) #define BLT_HWS_PGA_GEN7 (0x04280) +#define VEBOX_HWS_PGA_GEN7 (0x04380) #define RING_ACTHD(base) ((base)+0x74) #define RING_NOPID(base) ((base)+0x94) #define RING_IMR(base) ((base)+0xa8) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 3022e1579e5..89dfc63677a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -916,7 +916,8 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) mmio = BSD_HWS_PGA_GEN7; break; case VECS: - BUG(); + mmio = VEBOX_HWS_PGA_GEN7; + break; } } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); @@ -1909,6 +1910,38 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) return intel_init_ring_buffer(dev, ring); } +int intel_init_vebox_ring_buffer(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = &dev_priv->ring[VECS]; + + ring->name = "video enhancement ring"; + ring->id = VECS; + + ring->mmio_base = VEBOX_RING_BASE; + ring->write_tail = ring_write_tail; + ring->flush = gen6_ring_flush; + ring->add_request = gen6_add_request; + ring->get_seqno = gen6_ring_get_seqno; + ring->set_seqno = ring_set_seqno; + ring->irq_enable_mask = 0; + ring->irq_get = NULL; + ring->irq_put = NULL; + ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; + ring->sync_to = gen6_ring_sync; + ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; + ring->semaphore_register[VCS] = MI_SEMAPHORE_SYNC_VEV; + ring->semaphore_register[BCS] = MI_SEMAPHORE_SYNC_VEB; + ring->semaphore_register[VECS] = MI_SEMAPHORE_SYNC_INVALID; + ring->signal_mbox[RCS] = GEN6_RVESYNC; + ring->signal_mbox[VCS] = GEN6_VVESYNC; + ring->signal_mbox[BCS] = GEN6_BVESYNC; + ring->signal_mbox[VECS] = GEN6_NOSYNC; + ring->init = init_ring_common; + + return intel_init_ring_buffer(dev, ring); +} + int intel_ring_flush_all_caches(struct intel_ring_buffer *ring) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 73619cb3463..1c79520c7e4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -234,6 +234,7 @@ int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring); int intel_init_render_ring_buffer(struct drm_device *dev); int intel_init_bsd_ring_buffer(struct drm_device *dev); int intel_init_blt_ring_buffer(struct drm_device *dev); +int intel_init_vebox_ring_buffer(struct drm_device *dev); u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); void intel_ring_setup_status_page(struct intel_ring_buffer *ring); -- cgit v1.2.3-70-g09d2 From aeb0659338793746b8a4e482fa588ba1dd9ee559 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:28 -0700 Subject: drm/i915: Convert irq_refounct to struct It's overkill on older gens, but it's useful for newer gens. Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_ringbuffer.h | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 89dfc63677a..c7a89bb051a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -795,7 +795,7 @@ gen5_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -813,7 +813,7 @@ gen5_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->gt_irq_mask |= ring->irq_enable_mask; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); POSTING_READ(GTIMR); @@ -832,7 +832,7 @@ i9xx_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); @@ -850,7 +850,7 @@ i9xx_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); @@ -869,7 +869,7 @@ i8xx_ring_get_irq(struct intel_ring_buffer *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { dev_priv->irq_mask &= ~ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); @@ -887,7 +887,7 @@ i8xx_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { dev_priv->irq_mask |= ring->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); @@ -980,7 +980,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) gen6_gt_force_wake_get(dev_priv); spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { + if (ring->irq_refcount.gt++ == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | GEN6_RENDER_L3_PARITY_ERROR)); @@ -1003,7 +1003,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { + if (--ring->irq_refcount.gt == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); else diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 1c79520c7e4..153b87f67aa 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -72,7 +72,9 @@ struct intel_ring_buffer { */ u32 last_retired_head; - u32 irq_refcount; /* protected by dev_priv->irq_lock */ + struct { + u32 gt; + } irq_refcount; /* protected by dev_priv->irq_lock */ u32 irq_enable_mask; /* bitmask to enable ring interrupt */ u32 trace_irq_seqno; u32 sync_seqno[I915_NUM_RINGS-1]; -- cgit v1.2.3-70-g09d2 From cc609d5da5c78c92a2e2565604b2603a0965b494 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:29 -0700 Subject: drm/i915: consolidate interrupt naming scheme The motivation here is we're going to add some new interrupt definitions and handling outside of the GT interrupts which is all we've managed so far (with some RPS exceptions). By consolidating the names in the future we can make thing a bit cleaner as we don't need to define register names twice, and we can leverage pretty decent overlap in HW registers since ILK. To explain briefly what is in the comments: there are two sets of interrupt masking/enabling registers. At least so far, the definitions of the two sets overlap. The old code setup distinct names for interrupts in each set, ie. one for global, and one for ring. This made things confusing when using the wrong defines in the wrong places. rebase: Modified VLV bits v2: Renamed GT_RENDER_MASTER to GT_RENDER_CS_MASTER (Damien) Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 61 ++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 101 ++++++++++++++------------------ drivers/gpu/drm/i915/intel_ringbuffer.c | 21 ++++--- 3 files changed, 85 insertions(+), 98 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 953060dc9ff..90ed599611c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -780,7 +780,7 @@ static void ivybridge_parity_work(struct work_struct *work) I915_WRITE(GEN7_MISCCPCTL, misccpctl); spin_lock_irqsave(&dev_priv->irq_lock, flags); - dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + dev_priv->gt_irq_mask &= ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -812,7 +812,7 @@ static void ivybridge_handle_parity_error(struct drm_device *dev) return; spin_lock_irqsave(&dev_priv->irq_lock, flags); - dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + dev_priv->gt_irq_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -824,22 +824,22 @@ static void snb_gt_irq_handler(struct drm_device *dev, u32 gt_iir) { - if (gt_iir & (GEN6_RENDER_USER_INTERRUPT | - GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT)) + if (gt_iir & + (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) notify_ring(dev, &dev_priv->ring[RCS]); - if (gt_iir & GEN6_BSD_USER_INTERRUPT) + if (gt_iir & GT_BSD_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS]); - if (gt_iir & GEN6_BLITTER_USER_INTERRUPT) + if (gt_iir & GT_BLT_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[BCS]); - if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT | - GT_GEN6_BSD_CS_ERROR_INTERRUPT | - GT_RENDER_CS_ERROR_INTERRUPT)) { + if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | + GT_BSD_CS_ERROR_INTERRUPT | + GT_RENDER_CS_MASTER_ERROR_INTERRUPT)) { DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); i915_handle_error(dev, false); } - if (gt_iir & GT_GEN7_L3_PARITY_ERROR_INTERRUPT) + if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT) ivybridge_handle_parity_error(dev); } @@ -1283,9 +1283,10 @@ static void ilk_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 gt_iir) { - if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) + if (gt_iir & + (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) notify_ring(dev, &dev_priv->ring[RCS]); - if (gt_iir & GT_BSD_USER_INTERRUPT) + if (gt_iir & ILK_BSD_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS]); } @@ -2640,7 +2641,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | DE_POISON; - u32 render_irqs; + u32 gt_irqs; dev_priv->irq_mask = ~display_mask; @@ -2655,17 +2656,15 @@ static int ironlake_irq_postinstall(struct drm_device *dev) I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIMR, dev_priv->gt_irq_mask); + gt_irqs = GT_RENDER_USER_INTERRUPT; + if (IS_GEN6(dev)) - render_irqs = - GT_USER_INTERRUPT | - GEN6_BSD_USER_INTERRUPT | - GEN6_BLITTER_USER_INTERRUPT; + gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; else - render_irqs = - GT_USER_INTERRUPT | - GT_PIPE_NOTIFY | - GT_BSD_USER_INTERRUPT; - I915_WRITE(GTIER, render_irqs); + gt_irqs |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT | + ILK_BSD_USER_INTERRUPT; + + I915_WRITE(GTIER, gt_irqs); POSTING_READ(GTIER); ibx_irq_postinstall(dev); @@ -2691,7 +2690,7 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB | DE_ERR_INT_IVB; - u32 render_irqs; + u32 gt_irqs; dev_priv->irq_mask = ~display_mask; @@ -2706,14 +2705,14 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) DE_PIPEA_VBLANK_IVB); POSTING_READ(DEIER); - dev_priv->gt_irq_mask = ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; + dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | - GEN6_BLITTER_USER_INTERRUPT | GT_GEN7_L3_PARITY_ERROR_INTERRUPT; - I915_WRITE(GTIER, render_irqs); + gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT | + GT_BLT_USER_INTERRUPT | GT_RENDER_L3_PARITY_ERROR_INTERRUPT; + I915_WRITE(GTIER, gt_irqs); POSTING_READ(GTIER); /* Power management */ @@ -2729,9 +2728,9 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) static int valleyview_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 gt_irqs; u32 enable_mask; u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; - u32 render_irqs; enable_mask = I915_DISPLAY_PORT_INTERRUPT; enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | @@ -2767,9 +2766,9 @@ static int valleyview_irq_postinstall(struct drm_device *dev) I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | - GEN6_BLITTER_USER_INTERRUPT; - I915_WRITE(GTIER, render_irqs); + gt_irqs = GT_RENDER_USER_INTERRUPT | GT_BSD_USER_INTERRUPT | + GT_BLT_USER_INTERRUPT; + I915_WRITE(GTIER, gt_irqs); POSTING_READ(GTIER); /* ack & enable invalid PTE error interrupts */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8fced191417..bdb2c1734da 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -742,24 +742,6 @@ #define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8) #define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac) #define VLV_PCBR (VLV_DISPLAY_BASE + 0x2120) -#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) -#define I915_DISPLAY_PORT_INTERRUPT (1<<17) -#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) -#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */ -#define I915_HWB_OOM_INTERRUPT (1<<13) -#define I915_SYNC_STATUS_INTERRUPT (1<<12) -#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) -#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) -#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) -#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) -#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) -#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) -#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) -#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) -#define I915_DEBUG_INTERRUPT (1<<2) -#define I915_USER_INTERRUPT (1<<1) -#define I915_ASLE_INTERRUPT (1<<0) -#define I915_BSD_USER_INTERRUPT (1<<25) #define DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */ #define EIR 0x020b0 #define EMR 0x020b4 @@ -871,28 +853,6 @@ #define CACHE_MODE_1 0x7004 /* IVB+ */ #define PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6) -/* GEN6 interrupt control - * Note that the per-ring interrupt bits do alias with the global interrupt bits - * in GTIMR. */ -#define GEN6_RENDER_HWSTAM 0x2098 -#define GEN6_RENDER_IMR 0x20a8 -#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8) -#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7) -#define GEN6_RENDER_TIMEOUT_COUNTER_EXPIRED (1 << 6) -#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5) -#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4) -#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3) -#define GEN6_RENDER_SYNC_STATUS (1 << 2) -#define GEN6_RENDER_DEBUG_INTERRUPT (1 << 1) -#define GEN6_RENDER_USER_INTERRUPT (1 << 0) - -#define GEN6_BLITTER_HWSTAM 0x22098 -#define GEN6_BLITTER_IMR 0x220a8 -#define GEN6_BLITTER_MI_FLUSH_DW_NOTIFY_INTERRUPT (1 << 26) -#define GEN6_BLITTER_COMMAND_PARSER_MASTER_ERROR (1 << 25) -#define GEN6_BLITTER_SYNC_STATUS (1 << 24) -#define GEN6_BLITTER_USER_INTERRUPT (1 << 22) - #define GEN6_BLITTER_ECOSKPD 0x221d0 #define GEN6_BLITTER_LOCK_SHIFT 16 #define GEN6_BLITTER_FBC_NOTIFY (1<<3) @@ -903,9 +863,49 @@ #define GEN6_BSD_SLEEP_INDICATOR (1 << 3) #define GEN6_BSD_GO_INDICATOR (1 << 4) -#define GEN6_BSD_HWSTAM 0x12098 -#define GEN6_BSD_IMR 0x120a8 -#define GEN6_BSD_USER_INTERRUPT (1 << 12) +/* On modern GEN architectures interrupt control consists of two sets + * of registers. The first set pertains to the ring generating the + * interrupt. The second control is for the functional block generating the + * interrupt. These are PM, GT, DE, etc. + * + * Luckily *knocks on wood* all the ring interrupt bits match up with the + * GT interrupt bits, so we don't need to duplicate the defines. + * + * These defines should cover us well from SNB->HSW with minor exceptions + * it can also work on ILK. + */ +#define GT_BLT_FLUSHDW_NOTIFY_INTERRUPT (1 << 26) +#define GT_BLT_CS_ERROR_INTERRUPT (1 << 25) +#define GT_BLT_USER_INTERRUPT (1 << 22) +#define GT_BSD_CS_ERROR_INTERRUPT (1 << 15) +#define GT_BSD_USER_INTERRUPT (1 << 12) +#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */ +#define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4) +#define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3) +#define GT_RENDER_SYNC_STATUS_INTERRUPT (1 << 2) +#define GT_RENDER_DEBUG_INTERRUPT (1 << 1) +#define GT_RENDER_USER_INTERRUPT (1 << 0) + +/* These are all the "old" interrupts */ +#define ILK_BSD_USER_INTERRUPT (1<<5) +#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) +#define I915_DISPLAY_PORT_INTERRUPT (1<<17) +#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) +#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */ +#define I915_HWB_OOM_INTERRUPT (1<<13) +#define I915_SYNC_STATUS_INTERRUPT (1<<12) +#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) +#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) +#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) +#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) +#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) +#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) +#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) +#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) +#define I915_DEBUG_INTERRUPT (1<<2) +#define I915_USER_INTERRUPT (1<<1) +#define I915_ASLE_INTERRUPT (1<<0) +#define I915_BSD_USER_INTERRUPT (1 << 25) #define GEN6_BSD_RNCID 0x12198 @@ -3714,21 +3714,6 @@ #define DEIIR 0x44008 #define DEIER 0x4400c -/* GT interrupt. - * Note that for gen6+ the ring-specific interrupt bits do alias with the - * corresponding bits in the per-ring interrupt control registers. */ -#define GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT (1 << 26) -#define GT_GEN6_BLT_CS_ERROR_INTERRUPT (1 << 25) -#define GT_GEN6_BLT_USER_INTERRUPT (1 << 22) -#define GT_GEN6_BSD_CS_ERROR_INTERRUPT (1 << 15) -#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12) -#define GT_BSD_USER_INTERRUPT (1 << 5) /* ilk only */ -#define GT_GEN7_L3_PARITY_ERROR_INTERRUPT (1 << 5) -#define GT_PIPE_NOTIFY (1 << 4) -#define GT_RENDER_CS_ERROR_INTERRUPT (1 << 3) -#define GT_SYNC_STATUS (1 << 2) -#define GT_USER_INTERRUPT (1 << 0) - #define GTISR 0x44010 #define GTIMR 0x44014 #define GTIIR 0x44018 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c7a89bb051a..5ab8cc2cafe 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -560,7 +560,7 @@ static int init_render_ring(struct intel_ring_buffer *ring) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); if (HAS_L3_GPU_CACHE(dev)) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); return ret; } @@ -982,8 +982,9 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount.gt++ == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | - GEN6_RENDER_L3_PARITY_ERROR)); + I915_WRITE_IMR(ring, + ~(ring->irq_enable_mask | + GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); else I915_WRITE_IMR(ring, ~ring->irq_enable_mask); dev_priv->gt_irq_mask &= ~ring->irq_enable_mask; @@ -1005,7 +1006,8 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount.gt == 0) { if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR); + I915_WRITE_IMR(ring, + ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); else I915_WRITE_IMR(ring, ~0); dev_priv->gt_irq_mask |= ring->irq_enable_mask; @@ -1682,7 +1684,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->flush = gen6_render_ring_flush; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; - ring->irq_enable_mask = GT_USER_INTERRUPT; + ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; ring->sync_to = gen6_ring_sync; @@ -1701,7 +1703,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev) ring->set_seqno = pc_render_set_seqno; ring->irq_get = gen5_ring_get_irq; ring->irq_put = gen5_ring_put_irq; - ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; + ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | + GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; } else { ring->add_request = i9xx_add_request; if (INTEL_INFO(dev)->gen < 4) @@ -1843,7 +1846,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; + ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; @@ -1863,7 +1866,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ring->get_seqno = ring_get_seqno; ring->set_seqno = ring_set_seqno; if (IS_GEN5(dev)) { - ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; + ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; ring->irq_get = gen5_ring_get_irq; ring->irq_put = gen5_ring_put_irq; } else { @@ -1892,7 +1895,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; + ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; -- cgit v1.2.3-70-g09d2 From a19d2933cbc4c7b8e3d72e9fd2d48847c25bb41d Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:30 -0700 Subject: drm/i915: vebox interrupt get/put v2: Use the correct lock to protect PM interrupt regs, this was accidentally lost from earlier (Haihao) Fix return types (Ben) Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 46 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 5 ++-- 2 files changed, 47 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5ab8cc2cafe..8a6a0ee6d35 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1019,6 +1019,48 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring) gen6_gt_force_wake_put(dev_priv); } +static bool +hsw_vebox_get_irq(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + if (!dev->irq_enabled) + return false; + + spin_lock_irqsave(&dev_priv->rps.lock, flags); + if (ring->irq_refcount.pm++ == 0) { + u32 pm_imr = I915_READ(GEN6_PMIMR); + I915_WRITE_IMR(ring, ~ring->irq_enable_mask); + I915_WRITE(GEN6_PMIMR, pm_imr & ~ring->irq_enable_mask); + POSTING_READ(GEN6_PMIMR); + } + spin_unlock_irqrestore(&dev_priv->rps.lock, flags); + + return true; +} + +static void +hsw_vebox_put_irq(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + if (!dev->irq_enabled) + return; + + spin_lock_irqsave(&dev_priv->rps.lock, flags); + if (--ring->irq_refcount.pm == 0) { + u32 pm_imr = I915_READ(GEN6_PMIMR); + I915_WRITE_IMR(ring, ~0); + I915_WRITE(GEN6_PMIMR, pm_imr | ring->irq_enable_mask); + POSTING_READ(GEN6_PMIMR); + } + spin_unlock_irqrestore(&dev_priv->rps.lock, flags); +} + static int i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length, @@ -1928,8 +1970,8 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; ring->irq_enable_mask = 0; - ring->irq_get = NULL; - ring->irq_put = NULL; + ring->irq_get = hsw_vebox_get_irq; + ring->irq_put = hsw_vebox_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; ring->sync_to = gen6_ring_sync; ring->semaphore_register[RCS] = MI_SEMAPHORE_SYNC_VER; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 153b87f67aa..022d07e43d1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -73,8 +73,9 @@ struct intel_ring_buffer { u32 last_retired_head; struct { - u32 gt; - } irq_refcount; /* protected by dev_priv->irq_lock */ + u32 gt; /* protected by dev_priv->irq_lock */ + u32 pm; /* protected by dev_priv->rps.lock (sucks) */ + } irq_refcount; u32 irq_enable_mask; /* bitmask to enable ring interrupt */ u32 trace_irq_seqno; u32 sync_seqno[I915_NUM_RINGS-1]; -- cgit v1.2.3-70-g09d2 From 12638c57f31952127c734c26315e1348fa1334c2 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 28 May 2013 19:22:31 -0700 Subject: drm/i915: Enable vebox interrupts Similar to a patch originally written by: v2: Reversed the meanings of masked and enabled (Haihao) Made non-destructive writes in case enable/disabler rps runs first (Haihao) v3: Reword error message (Damien) Modify postinstall to do the right thing based on previous fixup. (Ben) CC: Xiang, Haihao Reviewed-by: Damien Lespiau Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 31 +++++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 ++- 3 files changed, 30 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 90ed599611c..e17bbe20119 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -944,8 +944,15 @@ static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv, } spin_unlock_irqrestore(&dev_priv->rps.lock, flags); - if (pm_iir & ~GEN6_PM_RPS_EVENTS) - DRM_ERROR("Unexpected PM interrupted\n"); + if (pm_iir & ~GEN6_PM_RPS_EVENTS) { + if (pm_iir & PM_VEBOX_USER_INTERRUPT) + notify_ring(dev_priv->dev, &dev_priv->ring[VECS]); + + if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) { + DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir); + i915_handle_error(dev_priv->dev, false); + } + } } static irqreturn_t valleyview_irq_handler(int irq, void *arg) @@ -2690,6 +2697,7 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB | DE_ERR_INT_IVB; + u32 pm_irqs = GEN6_PM_RPS_EVENTS; u32 gt_irqs; dev_priv->irq_mask = ~display_mask; @@ -2715,10 +2723,21 @@ static int ivybridge_irq_postinstall(struct drm_device *dev) I915_WRITE(GTIER, gt_irqs); POSTING_READ(GTIER); - /* Power management */ - I915_WRITE(GEN6_PMIMR, ~GEN6_PM_RPS_EVENTS); - I915_WRITE(GEN6_PMIER, GEN6_PM_RPS_EVENTS); - POSTING_READ(GEN6_PMIMR); + I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); + if (HAS_VEBOX(dev)) + pm_irqs |= PM_VEBOX_USER_INTERRUPT | + PM_VEBOX_CS_ERROR_INTERRUPT; + + /* Our enable/disable rps functions may touch these registers so + * make sure to set a known state for only the non-RPS bits. + * The RMW is extra paranoia since this should be called after being set + * to a known state in preinstall. + * */ + I915_WRITE(GEN6_PMIMR, + (I915_READ(GEN6_PMIMR) | ~GEN6_PM_RPS_EVENTS) & ~pm_irqs); + I915_WRITE(GEN6_PMIER, + (I915_READ(GEN6_PMIER) & GEN6_PM_RPS_EVENTS) | pm_irqs); + POSTING_READ(GEN6_PMIER); ibx_irq_postinstall(dev); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bdb2c1734da..89fac19d324 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -886,6 +886,9 @@ #define GT_RENDER_DEBUG_INTERRUPT (1 << 1) #define GT_RENDER_USER_INTERRUPT (1 << 0) +#define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ +#define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ + /* These are all the "old" interrupts */ #define ILK_BSD_USER_INTERRUPT (1<<5) #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8a6a0ee6d35..0e72da6ad0f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1969,7 +1969,8 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) ring->add_request = gen6_add_request; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; - ring->irq_enable_mask = 0; + ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT | + PM_VEBOX_CS_ERROR_INTERRUPT; ring->irq_get = hsw_vebox_get_irq; ring->irq_put = hsw_vebox_put_irq; ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; -- cgit v1.2.3-70-g09d2 From fd3da6c95b6d865446fa9b29df6edff4343e385a Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 6 Jun 2013 16:58:16 -0300 Subject: drm/i915: WA: FBC Render Nuke. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WaFbcNukeOn3DBlt for IVB, HSW. According BSPec: "Workaround: Do not enable Render Command Streamer tracking for FBC. Instead insert a LRI to address 0x50380 with data 0x00000004 after the PIPE_CONTROL that follows each render submission." v2: Chris noticed that flush_domains check was missing here and also suggested to do LRI only when fbc is enabled. To avoid do a I915_READ on every flush lets use the module parameter check. v3: Adding Wa name as Damien suggested. v4: Ville noticed VLV doesn't support fbc at all and comment came wrong from spec. v5: Ville noticed than on blt a Cache Clean LRI should be used instead the Nuke one. v6: Check for flush domain on blt (by Ville). Check for scanout dirty (by Chris). v7: Apply proper fbc_dirty implemented by Chris. v8: remove unused variables. Cc: Ville Syrjälä Cc: Chris Wilson Signed-off-by: Rodrigo Vivi Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ff9f71af934..b1fdca9e96b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1020,6 +1020,10 @@ #define IPS_CTL 0x43408 #define IPS_ENABLE (1 << 31) +#define MSG_FBC_REND_STATE 0x50380 +#define FBC_REND_NUKE (1<<2) +#define FBC_REND_CACHE_CLEAN (1<<1) + #define _HSW_PIPE_SLICE_CHICKEN_1_A 0x420B0 #define _HSW_PIPE_SLICE_CHICKEN_1_B 0x420B4 #define HSW_BYPASS_FBC_QUEUE (1<<22) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8faa43fc9bc..adc44e42b23 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -274,7 +274,7 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); + I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset); I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X | IVB_DPFC_CTL_FENCE_EN | diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 0e72da6ad0f..1ef081cd170 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -280,6 +280,27 @@ gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring) return 0; } +static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) +{ + int ret; + + if (!ring->fbc_dirty) + return 0; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + intel_ring_emit(ring, MI_NOOP); + /* WaFbcNukeOn3DBlt:ivb/hsw */ + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, MSG_FBC_REND_STATE); + intel_ring_emit(ring, value); + intel_ring_advance(ring); + + ring->fbc_dirty = false; + return 0; +} + static int gen7_render_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, u32 flush_domains) @@ -336,6 +357,9 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, 0); intel_ring_advance(ring); + if (flush_domains) + return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); + return 0; } @@ -1685,6 +1709,7 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, static int gen6_ring_flush(struct intel_ring_buffer *ring, u32 invalidate, u32 flush) { + struct drm_device *dev = ring->dev; uint32_t cmd; int ret; @@ -1707,6 +1732,10 @@ static int gen6_ring_flush(struct intel_ring_buffer *ring, intel_ring_emit(ring, 0); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); + + if (IS_GEN7(dev) && flush) + return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); + return 0; } -- cgit v1.2.3-70-g09d2 From 50f018dff180942dc40e601de6e97145a4aaeaa9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 10 Jun 2013 11:20:19 +0100 Subject: drm/i915: Initialize ring->hangcheck upon ring init When we reset and restart a ring, we also want to clear any existing hangcheck. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 1ef081cd170..a3cfa35b057 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -453,6 +453,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->last_retired_head = -1; } + memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); + out: if (HAS_FORCE_WAKE(dev)) gen6_gt_force_wake_put(dev_priv); -- cgit v1.2.3-70-g09d2 From 0025c0772de7451c2302fa628f038b213a0783bf Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 12 Jun 2013 12:35:30 +0300 Subject: drm/i915: change i915_add_request to macro Only execbuffer needed all the parameters on i915_add_request(). By putting __i915_add_request behind macro, all current callsites become cleaner. Following patch will introduce a new parameter for __i915_add_request. With this patch, only the relevant callsite will reflect the change making commit smaller and easier to understand. v2: _i915_add_request as function name (Chris Wilson) v3: change name __i915_add_request and fix ordering of params (Ben Widawsky) Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Acked-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 +++++--- drivers/gpu/drm/i915/i915_gem.c | 11 +++++------ drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- 6 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index cfa92864365..425200bc1e4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1756,9 +1756,11 @@ void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_idle(struct drm_device *dev); -int i915_add_request(struct intel_ring_buffer *ring, - struct drm_file *file, - u32 *seqno); +int __i915_add_request(struct intel_ring_buffer *ring, + struct drm_file *file, + u32 *seqno); +#define i915_add_request(ring, seqno) \ + __i915_add_request(ring, NULL, seqno); int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 58048d49256..38e20875c25 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -959,7 +959,7 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno) ret = 0; if (seqno == ring->outstanding_lazy_request) - ret = i915_add_request(ring, NULL, NULL); + ret = i915_add_request(ring, NULL); return ret; } @@ -2000,10 +2000,9 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno) return 0; } -int -i915_add_request(struct intel_ring_buffer *ring, - struct drm_file *file, - u32 *out_seqno) +int __i915_add_request(struct intel_ring_buffer *ring, + struct drm_file *file, + u32 *out_seqno) { drm_i915_private_t *dev_priv = ring->dev->dev_private; struct drm_i915_gem_request *request; @@ -2280,7 +2279,7 @@ i915_gem_retire_work_handler(struct work_struct *work) idle = true; for_each_ring(ring, dev_priv, i) { if (ring->gpu_caches_dirty) - i915_add_request(ring, NULL, NULL); + i915_add_request(ring, NULL); idle &= list_empty(&ring->request_list); } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f5ea3c1351f..ff471454968 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -455,7 +455,7 @@ static int do_switch(struct i915_hw_context *to) from->obj->dirty = 1; BUG_ON(from->obj->ring != ring); - ret = i915_add_request(ring, NULL, NULL); + ret = i915_add_request(ring, NULL); if (ret) { /* Too late, we've already scheduled a context switch. * Try to undo the change so that the hw state is diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c98333d7411..d79ac7aa55d 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -802,7 +802,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, ring->gpu_caches_dirty = true; /* Add a breadcrumb for the completion of the batch buffer */ - (void)i915_add_request(ring, file, NULL); + (void)__i915_add_request(ring, file, NULL); } static int diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 836794b68fc..a3698812e9c 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -217,7 +217,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, int ret; BUG_ON(overlay->last_flip_req); - ret = i915_add_request(ring, NULL, &overlay->last_flip_req); + ret = i915_add_request(ring, &overlay->last_flip_req); if (ret) return ret; @@ -286,7 +286,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, intel_ring_emit(ring, flip_addr); intel_ring_advance(ring); - return i915_add_request(ring, NULL, &overlay->last_flip_req); + return i915_add_request(ring, &overlay->last_flip_req); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a3cfa35b057..e51ab552046 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1512,7 +1512,7 @@ int intel_ring_idle(struct intel_ring_buffer *ring) /* We need to add any requests required to flush the objects and ring */ if (ring->outstanding_lazy_request) { - ret = i915_add_request(ring, NULL, NULL); + ret = i915_add_request(ring, NULL); if (ret) return ret; } -- cgit v1.2.3-70-g09d2 From 035dc1e0f9008b48630e02bf0eaa7cc547416d1d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 3 Jul 2013 12:56:54 +0200 Subject: drm/i915: reinit status page registers after gpu reset This fixes gpu reset on my gm45 - without this patch the bsd thing is forever stuck since the seqno updates never reach the status page. Tbh I have no idea how this ever worked without rewriting the hws registers after a gpu reset. To satisfy my OCD also give the functions a bit more consistent names: - Use status_page everywhere, also for the physical addressed one. - Use init for the allocation part and setup for the register setup part consistently. Long term I'd really like to share the hw init parts completely between gpu reset, resume and driver load, i.e. to call i915_gem_init_hw instead of the individual pieces we might need. v2: Add the missing paragraph to the commit message about what bug exactly this patch here fixes. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65495 Cc: Chris Wilson Reviewed-by: Chris Wilson Tested-by: lu hua Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e51ab552046..18ca76e3e5e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -379,6 +379,17 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) return I915_READ(acthd_reg); } +static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + u32 addr; + + addr = dev_priv->status_page_dmah->busaddr; + if (INTEL_INFO(ring->dev)->gen >= 4) + addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; + I915_WRITE(HWS_PGA, addr); +} + static int init_ring_common(struct intel_ring_buffer *ring) { struct drm_device *dev = ring->dev; @@ -390,6 +401,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) if (HAS_FORCE_WAKE(dev)) gen6_gt_force_wake_get(dev_priv); + if (I915_NEED_GFX_HWS(dev)) + intel_ring_setup_status_page(ring); + else + ring_setup_phys_status_page(ring); + /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -1223,7 +1239,6 @@ static int init_status_page(struct intel_ring_buffer *ring) ring->status_page.obj = obj; memset(ring->status_page.page_addr, 0, PAGE_SIZE); - intel_ring_setup_status_page(ring); DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", ring->name, ring->status_page.gfx_addr); @@ -1237,10 +1252,9 @@ err: return ret; } -static int init_phys_hws_pga(struct intel_ring_buffer *ring) +static int init_phys_status_page(struct intel_ring_buffer *ring) { struct drm_i915_private *dev_priv = ring->dev->dev_private; - u32 addr; if (!dev_priv->status_page_dmah) { dev_priv->status_page_dmah = @@ -1249,11 +1263,6 @@ static int init_phys_hws_pga(struct intel_ring_buffer *ring) return -ENOMEM; } - addr = dev_priv->status_page_dmah->busaddr; - if (INTEL_INFO(ring->dev)->gen >= 4) - addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; - I915_WRITE(HWS_PGA, addr); - ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; memset(ring->status_page.page_addr, 0, PAGE_SIZE); @@ -1281,7 +1290,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, return ret; } else { BUG_ON(ring->id != RCS); - ret = init_phys_hws_pga(ring); + ret = init_phys_status_page(ring); if (ret) return ret; } @@ -1893,7 +1902,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) } if (!I915_NEED_GFX_HWS(dev)) { - ret = init_phys_hws_pga(ring); + ret = init_phys_status_page(ring); if (ret) return ret; } -- cgit v1.2.3-70-g09d2 From aaf8a5167291b65e9116cb8736d862965b57c13a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 5 Jul 2013 23:39:50 +0200 Subject: drm/i915: fix up ring cleanup for the i830/i845 CS tlb w/a It's not a good idea to also run the pipe_control cleanup. This regression has been introduced whith the original cs tlb w/a in commit b45305fce5bb1abec263fcff9d81ebecd6306ede Author: Daniel Vetter Date: Mon Dec 17 16:21:27 2012 +0100 drm/i915: Implement workaround for broken CS tlb on i830/845 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64610 Cc: Chris Wilson Cc: stable@vger.kernel.org Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 18ca76e3e5e..664118d8c1d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -534,9 +534,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring) struct pipe_control *pc = ring->private; struct drm_i915_gem_object *obj; - if (!ring->private) - return; - obj = pc->obj; kunmap(sg_page(obj->pages->sgl)); @@ -544,7 +541,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring) drm_gem_object_unreference(&obj->base); kfree(pc); - ring->private = NULL; } static int init_render_ring(struct intel_ring_buffer *ring) @@ -617,7 +613,10 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring) if (HAS_BROKEN_CS_TLB(dev)) drm_gem_object_unreference(to_gem_object(ring->private)); - cleanup_pipe_control(ring); + if (INTEL_INFO(dev)->gen >= 5) + cleanup_pipe_control(ring); + + ring->private = NULL; } static void -- cgit v1.2.3-70-g09d2