From 675f7ff35bd256e65d3d0f52718d8babf5d1002a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Nov 2017 18:02:15 +0200 Subject: drm/i915: Fix init_clock_gating for resume MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving the init_clock_gating() call from intel_modeset_init_hw() to intel_modeset_gem_init() had an unintended effect of not applying some workarounds on resume. This, for example, cause some kind of corruption to appear at the top of my IVB Thinkpad X1 Carbon LVDS screen after hibernation. Fix the problem by explicitly calling init_clock_gating() from the resume path. I really hope this doesn't break something else again. At least the problems reported at https://bugs.freedesktop.org/show_bug.cgi?id=103549 didn't make a comeback, even after a hibernate cycle. v2: Reorder the init_clock_gating vs. modeset_init_hw to match the display reset path (Rodrigo) Cc: stable@vger.kernel.org Cc: Chris Wilson Cc: Rodrigo Vivi Fixes: 6ac43272768c ("drm/i915: Move init_clock_gating() back to where it was") Reviewed-by: Rodrigo Vivi Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171116160215.25715-1-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8ea6ce7027d4..87452c5558d3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1714,6 +1714,7 @@ static int i915_drm_resume(struct drm_device *dev) i915_gem_resume(dev_priv); intel_modeset_init_hw(dev); + intel_init_clock_gating(dev_priv); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display.hpd_irq_setup) -- cgit From e40dd226246d2a0fb463a04bd4c6f1b9e0a650ed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 12:34:55 +0000 Subject: drm/i915/execlists: Listen to COMPLETE context event not ACTIVE_IDLE Since commit e1fee72c2ea2e9c0c6e6743d32a6832f21337d6c Author: Oscar Mateo Date: Thu Jul 24 17:04:40 2014 +0100 drm/i915/bdw: Avoid non-lite-restore preemptions execlists has listened to (ACTIVE_IDLE | ELEMENT_SWITCH) for detecting when one context completed and it either continued onto the next (in port 1) or idled. We would always see COMPLETE | ACTIVE_IDLE on the final context-switch event, but on recent gen it appears that we now get separate ACTIVE_IDLE and COMPLETE events. In particular, the ACTIVE_IDLE events may not be coupled to a context (since it is a general state rather than a specific context completion event). v2: Update the history, execlists did originally start out by listening to the COMPLETE event not ACTIVE_IDLE. v3: Update preempt completion test to also use COMPLETE not ACTIVE_IDLE. References: bspec/12255 References: https://bugs.freedesktop.org/show_bug.cgi?id=103800 Signed-off-by: Chris Wilson Cc: Oscar Mateo Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Michal Winiarski Cc: Michel Thierry Acked-by: Michel Thierry Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171120123458.23242-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index be6c39adebdf..c2cfdfdc0722 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -154,7 +154,7 @@ #define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15) #define GEN8_CTX_STATUS_COMPLETED_MASK \ - (GEN8_CTX_STATUS_ACTIVE_IDLE | \ + (GEN8_CTX_STATUS_COMPLETE | \ GEN8_CTX_STATUS_PREEMPTED | \ GEN8_CTX_STATUS_ELEMENT_SWITCH) @@ -876,7 +876,7 @@ static void execlists_submission_tasklet(unsigned long data) if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) continue; - if (status & GEN8_CTX_STATUS_ACTIVE_IDLE && + if (status & GEN8_CTX_STATUS_COMPLETE && buf[2*head + 1] == PREEMPT_ID) { execlists_cancel_port_requests(execlists); execlists_unwind_incomplete_requests(execlists); -- cgit From d8747afb115f4967c4e900919d631c84ad58f573 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 12:34:56 +0000 Subject: drm/i915/execlists: Reduce completed event mask to COMPLETE | PREEMPTED Since we get a COMPLETE event when the context switch occurs on RING_HEAD == RING_TAIL and a PREEMPTED event when a switch occurs before that point, COMPLETE | PREEMPTED should cover all possible context switch completion events. We can move the ELEMENT_SWITCH info message from the COMPLETED_MASK into an assertion for when we are performing a switch to port[1]. Suggested-by: Joonas Lahtinen Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Michal Winiarski Cc: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20171120123458.23242-2-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/intel_lrc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c2cfdfdc0722..a2c7fc7bf4a4 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -154,9 +154,7 @@ #define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15) #define GEN8_CTX_STATUS_COMPLETED_MASK \ - (GEN8_CTX_STATUS_COMPLETE | \ - GEN8_CTX_STATUS_PREEMPTED | \ - GEN8_CTX_STATUS_ELEMENT_SWITCH) + (GEN8_CTX_STATUS_COMPLETE | GEN8_CTX_STATUS_PREEMPTED) #define CTX_LRI_HEADER_0 0x01 #define CTX_CONTEXT_CONTROL 0x02 @@ -907,6 +905,8 @@ static void execlists_submission_tasklet(unsigned long data) GEM_BUG_ON(count == 0); if (--count == 0) { GEM_BUG_ON(status & GEN8_CTX_STATUS_PREEMPTED); + GEM_BUG_ON(port_isset(&port[1]) && + !(status & GEN8_CTX_STATUS_ELEMENT_SWITCH)); GEM_BUG_ON(!i915_gem_request_completed(rq)); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); -- cgit From 1f5f9edb44ca9fd7255cdc60a1880241d2d17e48 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 12:34:57 +0000 Subject: drm/i915/execlists: Assert that we don't get mixed IDLE_ACTIVE | COMPLETE events If IDLE_ACTIVE is set, then all other bits are invalid. For us, we can assert that if we see a COMPLETE | PREEMPTED event, then it should be impossible for it to also contain an IDLE_ACTIVE flag. Suggested-by: Joonas Lahtinen Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Michal Winiarski Cc: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/20171120123458.23242-3-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/intel_lrc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a2c7fc7bf4a4..4aed00323780 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -874,6 +874,9 @@ static void execlists_submission_tasklet(unsigned long data) if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) continue; + /* We should never get a COMPLETED | IDLE_ACTIVE! */ + GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE); + if (status & GEN8_CTX_STATUS_COMPLETE && buf[2*head + 1] == PREEMPT_ID) { execlists_cancel_port_requests(execlists); -- cgit From 7c52a2219da1e551e19af6a4c50619952c6d7bde Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 13 Nov 2017 23:34:52 +0000 Subject: drm/i915/perf: replace .reg accesses with i915_mmio_reg_offset This replaces accesses to the reg field of the i915_reg_t structure with the i915_mmio_reg_offset() inline function. Suggested-by: Chris Wilson Signed-off-by: Lionel Landwerlin Reviewed-by: Ewelina Musial Link: https://patchwork.freedesktop.org/patch/msgid/20171113233455.12085-2-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_perf.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 00be015e01df..0f48e666098d 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -3007,7 +3007,7 @@ static bool gen8_is_valid_flex_addr(struct drm_i915_private *dev_priv, u32 addr) int i; for (i = 0; i < ARRAY_SIZE(flex_eu_regs); i++) { - if (flex_eu_regs[i].reg == addr) + if (i915_mmio_reg_offset(flex_eu_regs[i]) == addr) return true; } return false; @@ -3015,38 +3015,47 @@ static bool gen8_is_valid_flex_addr(struct drm_i915_private *dev_priv, u32 addr) static bool gen7_is_valid_b_counter_addr(struct drm_i915_private *dev_priv, u32 addr) { - return (addr >= OASTARTTRIG1.reg && addr <= OASTARTTRIG8.reg) || - (addr >= OAREPORTTRIG1.reg && addr <= OAREPORTTRIG8.reg) || - (addr >= OACEC0_0.reg && addr <= OACEC7_1.reg); + return (addr >= i915_mmio_reg_offset(OASTARTTRIG1) && + addr <= i915_mmio_reg_offset(OASTARTTRIG8)) || + (addr >= i915_mmio_reg_offset(OAREPORTTRIG1) && + addr <= i915_mmio_reg_offset(OAREPORTTRIG8)) || + (addr >= i915_mmio_reg_offset(OACEC0_0) && + addr <= i915_mmio_reg_offset(OACEC7_1)); } static bool gen7_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) { - return addr == HALF_SLICE_CHICKEN2.reg || - (addr >= MICRO_BP0_0.reg && addr <= NOA_WRITE.reg) || - (addr >= OA_PERFCNT1_LO.reg && addr <= OA_PERFCNT2_HI.reg) || - (addr >= OA_PERFMATRIX_LO.reg && addr <= OA_PERFMATRIX_HI.reg); + return addr == i915_mmio_reg_offset(HALF_SLICE_CHICKEN2) || + (addr >= i915_mmio_reg_offset(MICRO_BP0_0) && + addr <= i915_mmio_reg_offset(NOA_WRITE)) || + (addr >= i915_mmio_reg_offset(OA_PERFCNT1_LO) && + addr <= i915_mmio_reg_offset(OA_PERFCNT2_HI)) || + (addr >= i915_mmio_reg_offset(OA_PERFMATRIX_LO) && + addr <= i915_mmio_reg_offset(OA_PERFMATRIX_HI)); } static bool gen8_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) { return gen7_is_valid_mux_addr(dev_priv, addr) || - addr == WAIT_FOR_RC6_EXIT.reg || - (addr >= RPM_CONFIG0.reg && addr <= NOA_CONFIG(8).reg); + addr == i915_mmio_reg_offset(WAIT_FOR_RC6_EXIT) || + (addr >= i915_mmio_reg_offset(RPM_CONFIG0) && + addr <= i915_mmio_reg_offset(NOA_CONFIG(8))); } static bool gen10_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) { return gen8_is_valid_mux_addr(dev_priv, addr) || - (addr >= OA_PERFCNT3_LO.reg && addr <= OA_PERFCNT4_HI.reg); + (addr >= i915_mmio_reg_offset(OA_PERFCNT3_LO) && + addr <= i915_mmio_reg_offset(OA_PERFCNT4_HI)); } static bool hsw_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) { return gen7_is_valid_mux_addr(dev_priv, addr) || (addr >= 0x25100 && addr <= 0x2FF90) || - (addr >= HSW_MBVID2_NOA0.reg && addr <= HSW_MBVID2_NOA9.reg) || - addr == HSW_MBVID2_MISR0.reg; + (addr >= i915_mmio_reg_offset(HSW_MBVID2_NOA0) && + addr <= i915_mmio_reg_offset(HSW_MBVID2_NOA9)) || + addr == i915_mmio_reg_offset(HSW_MBVID2_MISR0); } static bool chv_is_valid_mux_addr(struct drm_i915_private *dev_priv, u32 addr) @@ -3061,14 +3070,14 @@ static uint32_t mask_reg_value(u32 reg, u32 val) * WaDisableSTUnitPowerOptimization workaround. Make sure the value * programmed by userspace doesn't change this. */ - if (HALF_SLICE_CHICKEN2.reg == reg) + if (i915_mmio_reg_offset(HALF_SLICE_CHICKEN2) == reg) val = val & ~_MASKED_BIT_ENABLE(GEN8_ST_PO_DISABLE); /* WAIT_FOR_RC6_EXIT has only one bit fullfilling the function * indicated by its name and a bunch of selection fields used by OA * configs. */ - if (WAIT_FOR_RC6_EXIT.reg == reg) + if (i915_mmio_reg_offset(WAIT_FOR_RC6_EXIT) == reg) val = val & ~_MASKED_BIT_ENABLE(HSW_WAIT_FOR_RC6_EXIT_ENABLE); return val; -- cgit From 2113184c6f6749f6e4e86a42894f67a50ead6775 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 10:20:01 +0000 Subject: drm/i915: Pull the unconditional GPU cache invalidation into request construction As the request will, in the following patch, implicitly invoke a context-switch on construction, we should precede that with a GPU TLB invalidation. Also, even before using GGTT, we always want to invalidate the TLBs for any updates (as well as the ppgtt invalidates that are unconditionally applied by execbuf). Since we almost always require the TLB invalidate, do it unconditionally on request allocation and so we can remove it from all other paths. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171120102002.22254-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 +------ drivers/gpu/drm/i915/i915_gem_render_state.c | 4 ---- drivers/gpu/drm/i915/i915_gem_request.c | 24 ++++++++++++++++++----- drivers/gpu/drm/i915/selftests/huge_pages.c | 4 ---- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 4 ---- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 10 ---------- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 4 ---- 7 files changed, 20 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 53ccb27bfe91..b7895788bc75 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1111,10 +1111,6 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto err_request; - err = eb->engine->emit_flush(rq, EMIT_INVALIDATE); - if (err) - goto err_request; - err = i915_switch_context(rq); if (err) goto err_request; @@ -1818,8 +1814,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) /* Unconditionally flush any chipset caches (for streaming writes). */ i915_gem_chipset_flush(eb->i915); - /* Unconditionally invalidate GPU caches and TLBs. */ - return eb->engine->emit_flush(eb->request, EMIT_INVALIDATE); + return 0; } static bool i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index c2723a06fbb4..f7fc0df251ac 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -208,10 +208,6 @@ int i915_gem_render_state_emit(struct drm_i915_gem_request *rq) if (err) goto err_unpin; - err = engine->emit_flush(rq, EMIT_INVALIDATE); - if (err) - goto err_unpin; - err = engine->emit_bb_start(rq, so.batch_offset, so.batch_size, I915_DISPATCH_SECURE); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index e0d6221022a8..91eae1b20c42 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -703,17 +703,31 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, req->reserved_space = MIN_SPACE_FOR_ADD_REQUEST; GEM_BUG_ON(req->reserved_space < engine->emit_breadcrumb_sz); - ret = engine->request_alloc(req); - if (ret) - goto err_ctx; - - /* Record the position of the start of the request so that + /* + * Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the head. */ req->head = req->ring->emit; + /* Unconditionally invalidate GPU caches and TLBs. */ + ret = engine->emit_flush(req, EMIT_INVALIDATE); + if (ret) + goto err_ctx; + + ret = engine->request_alloc(req); + if (ret) { + /* + * Past the point-of-no-return. Since we may have updated + * global state after partially completing the request alloc, + * we need to commit any commands so far emitted in the + * request to the HW. + */ + __i915_add_request(req, false); + return ERR_PTR(ret); + } + /* Check that we didn't interrupt ourselves with a new request */ GEM_BUG_ON(req->timeline->seqno != req->fence.seqno); return req; diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 01af540b6ef9..159a2cb68765 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -989,10 +989,6 @@ static int gpu_write(struct i915_vma *vma, i915_vma_unpin(batch); i915_vma_close(batch); - err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); - if (err) - goto err_request; - err = i915_switch_context(rq); if (err) goto err_request; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index c82780a9d455..4ff30b9af1fe 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -158,10 +158,6 @@ static int gpu_fill(struct drm_i915_gem_object *obj, goto err_batch; } - err = engine->emit_flush(rq, EMIT_INVALIDATE); - if (err) - goto err_request; - err = i915_switch_context(rq); if (err) goto err_request; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 6bce99050e94..d7bf53ff8f84 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -459,10 +459,6 @@ empty_request(struct intel_engine_cs *engine, if (IS_ERR(request)) return request; - err = engine->emit_flush(request, EMIT_INVALIDATE); - if (err) - goto out_request; - err = i915_switch_context(request); if (err) goto out_request; @@ -675,9 +671,6 @@ static int live_all_engines(void *arg) goto out_request; } - err = engine->emit_flush(request[id], EMIT_INVALIDATE); - GEM_BUG_ON(err); - err = i915_switch_context(request[id]); GEM_BUG_ON(err); @@ -797,9 +790,6 @@ static int live_sequential_engines(void *arg) } } - err = engine->emit_flush(request[id], EMIT_INVALIDATE); - GEM_BUG_ON(err); - err = i915_switch_context(request[id]); GEM_BUG_ON(err); diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 71ce06680d66..145bdc26553c 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -114,10 +114,6 @@ static int emit_recurse_batch(struct hang *h, if (err) goto unpin_vma; - err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); - if (err) - goto unpin_hws; - err = i915_switch_context(rq); if (err) goto unpin_hws; -- cgit From 3fef5cda970124a15c553c1672d800e40fc08a9e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 10:20:02 +0000 Subject: drm/i915: Automatic i915_switch_context for legacy During request construction, after pinning the context we know whether or not we have to emit a context switch. So move this common operation from every caller into i915_gem_request_alloc() itself. v2: Always submit the request if we emitted some commands during request construction, as typically it also involves changes in global state. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171120102002.22254-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 7 +------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 -------- drivers/gpu/drm/i915/i915_gem_request.c | 4 ++++ drivers/gpu/drm/i915/i915_perf.c | 3 +-- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ++++ drivers/gpu/drm/i915/selftests/huge_pages.c | 10 +++------- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 4 ---- drivers/gpu/drm/i915/selftests/i915_gem_request.c | 10 ---------- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 5 ----- 10 files changed, 14 insertions(+), 43 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 61ba321e9970..e07eb0beef13 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5045,7 +5045,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) goto out_ctx; } - err = i915_switch_context(rq); + err = 0; if (engine->init_context) err = engine->init_context(rq); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2db040695035..c1efbaf02bf2 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -842,8 +842,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) struct intel_engine_cs *engine = req->engine; lockdep_assert_held(&req->i915->drm.struct_mutex); - if (i915_modparams.enable_execlists) - return 0; + GEM_BUG_ON(i915_modparams.enable_execlists); if (!req->ctx->engine[engine->id].state) { struct i915_gem_context *to = req->ctx; @@ -899,7 +898,6 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) { struct drm_i915_gem_request *req; - int ret; if (engine_has_idle_kernel_context(engine)) continue; @@ -922,10 +920,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) GFP_KERNEL); } - ret = i915_switch_context(req); i915_add_request(req); - if (ret) - return ret; } return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b7895788bc75..14d9e61a1e06 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1111,10 +1111,6 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto err_request; - err = i915_switch_context(rq); - if (err) - goto err_request; - err = eb->engine->emit_bb_start(rq, batch->node.start, PAGE_SIZE, cache->gen > 5 ? 0 : I915_DISPATCH_SECURE); @@ -1960,10 +1956,6 @@ static int eb_submit(struct i915_execbuffer *eb) if (err) return err; - err = i915_switch_context(eb->request); - if (err) - return err; - if (eb->args->flags & I915_EXEC_GEN7_SOL_RESET) { err = i915_reset_gen7_sol_offsets(eb->request); if (err) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 91eae1b20c42..86e2346357cf 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -624,6 +624,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, if (ret) goto err_unpin; + ret = intel_ring_wait_for_space(ring, MIN_SPACE_FOR_ADD_REQUEST); + if (ret) + goto err_unreserve; + /* Move the oldest request to the slab-cache (if not in use!) */ req = list_first_entry_or_null(&engine->timeline->requests, typeof(*req), link); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0f48e666098d..fd150099978c 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1726,10 +1726,9 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr GFP_KERNEL); } - ret = i915_switch_context(req); i915_add_request(req); - return ret; + return 0; } /* diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 12e734b29463..be98868115bf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1592,6 +1592,10 @@ static int ring_request_alloc(struct drm_i915_gem_request *request) if (ret) return ret; + ret = i915_switch_context(request); + if (ret) + return ret; + request->reserved_space -= LEGACY_REQUEST_SIZE; return 0; } diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 159a2cb68765..db7a0a1f2960 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -989,13 +989,9 @@ static int gpu_write(struct i915_vma *vma, i915_vma_unpin(batch); i915_vma_close(batch); - err = i915_switch_context(rq); - if (err) - goto err_request; - - err = rq->engine->emit_bb_start(rq, - batch->node.start, batch->node.size, - flags); + err = engine->emit_bb_start(rq, + batch->node.start, batch->node.size, + flags); if (err) goto err_request; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 4ff30b9af1fe..09340b3c1156 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -158,10 +158,6 @@ static int gpu_fill(struct drm_i915_gem_object *obj, goto err_batch; } - err = i915_switch_context(rq); - if (err) - goto err_request; - flags = 0; if (INTEL_GEN(vm->i915) <= 5) flags |= I915_DISPATCH_SECURE; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index d7bf53ff8f84..647bf2bbd799 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -459,10 +459,6 @@ empty_request(struct intel_engine_cs *engine, if (IS_ERR(request)) return request; - err = i915_switch_context(request); - if (err) - goto out_request; - err = engine->emit_bb_start(request, batch->node.start, batch->node.size, @@ -671,9 +667,6 @@ static int live_all_engines(void *arg) goto out_request; } - err = i915_switch_context(request[id]); - GEM_BUG_ON(err); - err = engine->emit_bb_start(request[id], batch->node.start, batch->node.size, @@ -790,9 +783,6 @@ static int live_sequential_engines(void *arg) } } - err = i915_switch_context(request[id]); - GEM_BUG_ON(err); - err = engine->emit_bb_start(request[id], batch->node.start, batch->node.size, diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 145bdc26553c..1bbb8c46e2d9 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -114,10 +114,6 @@ static int emit_recurse_batch(struct hang *h, if (err) goto unpin_vma; - err = i915_switch_context(rq); - if (err) - goto unpin_hws; - i915_vma_move_to_active(vma, rq, 0); if (!i915_gem_object_has_active_reference(vma->obj)) { i915_gem_object_get(vma->obj); @@ -169,7 +165,6 @@ static int emit_recurse_batch(struct hang *h, err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, flags); -unpin_hws: i915_vma_unpin(hws); unpin_vma: i915_vma_unpin(vma); -- cgit From 9f9b2792b6d38fbc8028f31b41ebd38a3f28a401 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 27 Oct 2017 15:59:31 +0100 Subject: drm/i915/perf: reuse timestamp frequency from device info Now that we have this stored in the device info, we can drop it from perf part of the driver. Note that this requires to init perf after we've computed the frequency, hence why we move i915_perf_init() from i915_driver_init_early() to after intel_device_info_runtime_init(). v2: Use div_u64 (Chris) v3: Drop u64 divs by switching to kHz (Chris/Ville) Move i915_perf_fini to i915_driver_cleanup_hw (Matthew) Signed-off-by: Lionel Landwerlin Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20171113181902.12411-2-lionel.g.landwerlin@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 7 ++++--- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_perf.c | 36 +++++------------------------------- 3 files changed, 9 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 87452c5558d3..2b4ced93011b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -936,8 +936,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_detect_preproduction_hw(dev_priv); - i915_perf_init(dev_priv); - return 0; err_irq: @@ -954,7 +952,6 @@ err_engines: */ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) { - i915_perf_fini(dev_priv); i915_gem_load_cleanup(dev_priv); intel_irq_fini(dev_priv); i915_workqueues_cleanup(dev_priv); @@ -1101,6 +1098,8 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) intel_sanitize_options(dev_priv); + i915_perf_init(dev_priv); + ret = i915_ggtt_probe_hw(dev_priv); if (ret) return ret; @@ -1206,6 +1205,8 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = dev_priv->drm.pdev; + i915_perf_fini(dev_priv); + if (pdev->msi_enabled) pci_disable_msi(pdev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 36bb4927484a..2b766253f970 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2619,7 +2619,6 @@ struct drm_i915_private { bool periodic; int period_exponent; - int timestamp_frequency; struct i915_oa_config test_config; diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index fd150099978c..adbce839a918 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -2690,8 +2690,8 @@ err: static u64 oa_exponent_to_ns(struct drm_i915_private *dev_priv, int exponent) { - return div_u64(1000000000ULL * (2ULL << exponent), - dev_priv->perf.oa.timestamp_frequency); + return div64_u64(1000000000ULL * (2ULL << exponent), + 1000ULL * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz); } /** @@ -3423,8 +3423,6 @@ static struct ctl_table dev_root[] = { */ void i915_perf_init(struct drm_i915_private *dev_priv) { - dev_priv->perf.oa.timestamp_frequency = 0; - if (IS_HASWELL(dev_priv)) { dev_priv->perf.oa.ops.is_valid_b_counter_reg = gen7_is_valid_b_counter_addr; @@ -3440,8 +3438,6 @@ void i915_perf_init(struct drm_i915_private *dev_priv) dev_priv->perf.oa.ops.oa_hw_tail_read = gen7_oa_hw_tail_read; - dev_priv->perf.oa.timestamp_frequency = 12500000; - dev_priv->perf.oa.oa_formats = hsw_oa_formats; } else if (i915_modparams.enable_execlists) { /* Note: that although we could theoretically also support the @@ -3485,23 +3481,6 @@ void i915_perf_init(struct drm_i915_private *dev_priv) dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); } - - switch (dev_priv->info.platform) { - case INTEL_BROADWELL: - dev_priv->perf.oa.timestamp_frequency = 12500000; - break; - case INTEL_BROXTON: - case INTEL_GEMINILAKE: - dev_priv->perf.oa.timestamp_frequency = 19200000; - break; - case INTEL_SKYLAKE: - case INTEL_KABYLAKE: - case INTEL_COFFEELAKE: - dev_priv->perf.oa.timestamp_frequency = 12000000; - break; - default: - break; - } } else if (IS_GEN10(dev_priv)) { dev_priv->perf.oa.ops.is_valid_b_counter_reg = gen7_is_valid_b_counter_addr; @@ -3517,15 +3496,10 @@ void i915_perf_init(struct drm_i915_private *dev_priv) dev_priv->perf.oa.ctx_flexeu0_offset = 0x3de; dev_priv->perf.oa.gen8_valid_ctx_bit = (1<<16); - - /* Default frequency, although we need to read it from - * the register as it might vary between parts. - */ - dev_priv->perf.oa.timestamp_frequency = 12000000; } } - if (dev_priv->perf.oa.timestamp_frequency) { + if (dev_priv->perf.oa.ops.enable_metric_set) { hrtimer_init(&dev_priv->perf.oa.poll_check_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); dev_priv->perf.oa.poll_check_timer.function = oa_poll_check_timer_cb; @@ -3535,8 +3509,8 @@ void i915_perf_init(struct drm_i915_private *dev_priv) mutex_init(&dev_priv->perf.lock); spin_lock_init(&dev_priv->perf.oa.oa_buffer.ptr_lock); - oa_sample_rate_hard_limit = - dev_priv->perf.oa.timestamp_frequency / 2; + oa_sample_rate_hard_limit = 1000 * + (INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz / 2); dev_priv->perf.sysctl_header = register_sysctl_table(dev_root); mutex_init(&dev_priv->perf.metrics_lock); -- cgit From 2a6c4241fcc3d942a0a6b09e445561d099fa7884 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 13:26:06 +0000 Subject: drm/i915/selftest: Make guc clients static Make the private array used for stashing test clients static, to silence sparse. References: 55bd6bd75717 ("drm/i915/selftests: Add a GuC doorbells selftest") Signed-off-by: Chris Wilson Cc: Michel Thierry Cc: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20171120132606.4254-1-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/selftests/intel_guc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c index f10029e18820..f1baeda8b4a8 100644 --- a/drivers/gpu/drm/i915/selftests/intel_guc.c +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c @@ -27,7 +27,7 @@ /* max doorbell number + negative test for each client type */ #define ATTEMPTS (GUC_NUM_DOORBELLS + GUC_CLIENT_PRIORITY_NUM) -struct intel_guc_client *clients[ATTEMPTS]; +static struct intel_guc_client *clients[ATTEMPTS]; static bool available_dbs(struct intel_guc *guc, u32 priority) { -- cgit From ba74cb10c775c839f6e1d0fabd1e772eabd9c43f Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 20 Nov 2017 12:34:58 +0000 Subject: drm/i915/execlists: Delay writing to ELSP until HW has processed the previous write The hardware needs some time to process the information received in the ExecList Submission Port, and expects us to not write anything more until it has 'acknowledged' this new submission by sending an IDLE_ACTIVE or PREEMPTED CSB event. If we do not follow this, the driver could write new data into the ELSP before HW had finishing fetching the previous one, putting us in 'undefined behaviour' space. This seems to be the problem causing the spurious PREEMPTED & COMPLETE events after a COMPLETE like the one below: [] vcs0: sw rd pointer = 2, hw wr pointer = 0, current 'head' = 3. [] vcs0: Execlist CSB[0]: 0x00000018 _ 0x00000007 [] vcs0: Execlist CSB[1]: 0x00000001 _ 0x00000000 [] vcs0: Execlist CSB[2]: 0x00000018 _ 0x00000007 <<< COMPLETE [] vcs0: Execlist CSB[3]: 0x00000012 _ 0x00000007 <<< PREEMPTED & COMPLETE [] vcs0: Execlist CSB[4]: 0x00008002 _ 0x00000006 [] vcs0: Execlist CSB[5]: 0x00000014 _ 0x00000006 The ELSP writes that lead to this CSB sequence show that the HW hadn't started executing the previous execlist (the one with only ctx 0x6) by the time the new one was submitted; this is a bit more clear in the data show in the EXECLIST_STATUS register at the time of the ELSP write. [] vcs0: ELSP[0] = 0x0_0 [execlist1] - status_reg = 0x0_302 [] vcs0: ELSP[1] = 0x6_fedb2119 [execlist0] - status_reg = 0x0_8302 [] vcs0: ELSP[2] = 0x7_fedaf119 [execlist1] - status_reg = 0x0_8308 [] vcs0: ELSP[3] = 0x6_fedb2119 [execlist0] - status_reg = 0x7_8308 Note that having to wait for this ack does not disable lite-restores, although it may reduce their numbers. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102035 Signed-off-by: Michel Thierry Link: https://patchwork.freedesktop.org/patch/msgid/<20171118003038.7935-1-michel.thierry@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171120123458.23242-4-chris@chris-wilson.co.uk Reviewed-by: Chris Wilson Tested-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_lrc.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 2 files changed, 23 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4aed00323780..8d0c49388863 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -477,6 +477,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) elsp_write(desc, elsp); } + execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK); } static bool ctx_single_port_submission(const struct i915_gem_context *ctx) @@ -529,6 +530,7 @@ static void inject_preempt_context(struct intel_engine_cs *engine) elsp_write(0, elsp); elsp_write(ce->lrc_desc, elsp); + execlists_clear_active(&engine->execlists, EXECLISTS_ACTIVE_HWACK); } static void execlists_dequeue(struct intel_engine_cs *engine) @@ -575,9 +577,20 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * know the next preemption status we see corresponds * to this ELSP update. */ + GEM_BUG_ON(!port_count(&port[0])); if (port_count(&port[0]) > 1) goto unlock; + /* + * If we write to ELSP a second time before the HW has had + * a chance to respond to the previous write, we can confuse + * the HW and hit "undefined behaviour". After writing to ELSP, + * we must then wait until we see a context-switch event from + * the HW to indicate that it has had a chance to respond. + */ + if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) + goto unlock; + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && rb_entry(rb, struct i915_priolist, node)->priority > max(last->priotree.priority, 0)) { @@ -871,6 +884,15 @@ static void execlists_submission_tasklet(unsigned long data) GEM_TRACE("%s csb[%dd]: status=0x%08x:0x%08x\n", engine->name, head, status, buf[2*head + 1]); + + if (status & (GEN8_CTX_STATUS_IDLE_ACTIVE | + GEN8_CTX_STATUS_PREEMPTED)) + execlists_set_active(execlists, + EXECLISTS_ACTIVE_HWACK); + if (status & GEN8_CTX_STATUS_ACTIVE_IDLE) + execlists_clear_active(execlists, + EXECLISTS_ACTIVE_HWACK); + if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) continue; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index c00804ed64c6..e437a9556c08 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -251,6 +251,7 @@ struct intel_engine_execlists { unsigned int active; #define EXECLISTS_ACTIVE_USER 0 #define EXECLISTS_ACTIVE_PREEMPT 1 +#define EXECLISTS_ACTIVE_HWACK 2 /** * @port_mask: number of execlist ports - 1 -- cgit From fb5c551ad510e4a408c105670f89c725ebbfe6c8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 20:55:00 +0000 Subject: drm/i915: Remove i915.enable_execlists module parameter Execlists and legacy ringbuffer submission are no longer feature comparable (execlists now offer greater functionality that should overcome their performance hit) and obsoletes the unsafe module parameter, i.e. comparing the two modes of execution is no longer useful, so remove the debug tool. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Reviewed-by: Lionel Landwerlin #i915_perf.c Link: https://patchwork.freedesktop.org/patch/msgid/20171120205504.21892-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/gvt/render.c | 3 +- drivers/gpu/drm/i915/i915_debugfs.c | 70 --------------------------------- drivers/gpu/drm/i915/i915_drv.c | 8 +--- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_gem.c | 10 ++--- drivers/gpu/drm/i915/i915_gem_context.c | 10 +---- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 +- drivers/gpu/drm/i915/i915_params.c | 4 -- drivers/gpu/drm/i915/i915_params.h | 1 - drivers/gpu/drm/i915/i915_perf.c | 8 ++-- drivers/gpu/drm/i915/intel_engine_cs.c | 8 ++-- drivers/gpu/drm/i915/intel_gvt.c | 5 --- drivers/gpu/drm/i915/intel_lrc.c | 31 --------------- drivers/gpu/drm/i915/intel_lrc.h | 4 -- 14 files changed, 20 insertions(+), 149 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index 0672178548ef..dac12c25f349 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -294,8 +294,7 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id) * write. */ if (mmio->in_context && - ((ctx_ctrl & inhibit_mask) != inhibit_mask) && - i915_modparams.enable_execlists) + (ctx_ctrl & inhibit_mask) != inhibit_mask) continue; if (mmio->mask) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index df3852c02a35..5e2a6e18771f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1989,75 +1989,6 @@ static int i915_context_status(struct seq_file *m, void *unused) return 0; } -static void i915_dump_lrc_obj(struct seq_file *m, - struct i915_gem_context *ctx, - struct intel_engine_cs *engine) -{ - struct i915_vma *vma = ctx->engine[engine->id].state; - struct page *page; - int j; - - seq_printf(m, "CONTEXT: %s %u\n", engine->name, ctx->hw_id); - - if (!vma) { - seq_puts(m, "\tFake context\n"); - return; - } - - if (vma->flags & I915_VMA_GLOBAL_BIND) - seq_printf(m, "\tBound in GGTT at 0x%08x\n", - i915_ggtt_offset(vma)); - - if (i915_gem_object_pin_pages(vma->obj)) { - seq_puts(m, "\tFailed to get pages for context object\n\n"); - return; - } - - page = i915_gem_object_get_page(vma->obj, LRC_STATE_PN); - if (page) { - u32 *reg_state = kmap_atomic(page); - - for (j = 0; j < 0x600 / sizeof(u32) / 4; j += 4) { - seq_printf(m, - "\t[0x%04x] 0x%08x 0x%08x 0x%08x 0x%08x\n", - j * 4, - reg_state[j], reg_state[j + 1], - reg_state[j + 2], reg_state[j + 3]); - } - kunmap_atomic(reg_state); - } - - i915_gem_object_unpin_pages(vma->obj); - seq_putc(m, '\n'); -} - -static int i915_dump_lrc(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_engine_cs *engine; - struct i915_gem_context *ctx; - enum intel_engine_id id; - int ret; - - if (!i915_modparams.enable_execlists) { - seq_printf(m, "Logical Ring Contexts are disabled\n"); - return 0; - } - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - list_for_each_entry(ctx, &dev_priv->contexts.list, link) - for_each_engine(engine, dev_priv, id) - i915_dump_lrc_obj(m, ctx, engine); - - mutex_unlock(&dev->struct_mutex); - - return 0; -} - static const char *swizzle_string(unsigned swizzle) { switch (swizzle) { @@ -4833,7 +4764,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_vbt", i915_vbt, 0}, {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, {"i915_context_status", i915_context_status, 0}, - {"i915_dump_lrc", i915_dump_lrc, 0}, {"i915_forcewake_domains", i915_forcewake_domains, 0}, {"i915_swizzle_info", i915_swizzle_info, 0}, {"i915_ppgtt_info", i915_ppgtt_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2b4ced93011b..c608fd96771c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -371,9 +371,7 @@ static int i915_getparam(struct drm_device *dev, void *data, if (dev_priv->engine[RCS] && dev_priv->engine[RCS]->schedule) { value |= I915_SCHEDULER_CAP_ENABLED; value |= I915_SCHEDULER_CAP_PRIORITY; - - if (HAS_LOGICAL_RING_PREEMPTION(dev_priv) && - i915_modparams.enable_execlists) + if (HAS_LOGICAL_RING_PREEMPTION(dev_priv)) value |= I915_SCHEDULER_CAP_PREEMPTION; } break; @@ -1054,10 +1052,6 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) static void intel_sanitize_options(struct drm_i915_private *dev_priv) { - i915_modparams.enable_execlists = - intel_sanitize_enable_execlists(dev_priv, - i915_modparams.enable_execlists); - /* * i915.enable_ppgtt is read-only, so do an early pass to validate the * user's requested state against the hardware/driver capabilities. We diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b766253f970..d2c6ba7f8acd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3153,6 +3153,9 @@ intel_info(const struct drm_i915_private *dev_priv) ((dev_priv)->info.has_logical_ring_contexts) #define HAS_LOGICAL_RING_PREEMPTION(dev_priv) \ ((dev_priv)->info.has_logical_ring_preemption) + +#define HAS_EXECLISTS(dev_priv) HAS_LOGICAL_RING_CONTEXTS(dev_priv) + #define USES_PPGTT(dev_priv) (i915_modparams.enable_ppgtt) #define USES_FULL_PPGTT(dev_priv) (i915_modparams.enable_ppgtt >= 2) #define USES_FULL_48BIT_PPGTT(dev_priv) (i915_modparams.enable_ppgtt == 3) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e07eb0beef13..494c6be035b2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5003,7 +5003,7 @@ bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) return false; /* TODO: make semaphores and Execlists play nicely together */ - if (i915_modparams.enable_execlists) + if (HAS_EXECLISTS(dev_priv)) return false; if (value >= 0) @@ -5147,12 +5147,12 @@ int i915_gem_init(struct drm_i915_private *dev_priv) dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1); - if (!i915_modparams.enable_execlists) { - dev_priv->gt.resume = intel_legacy_submission_resume; - dev_priv->gt.cleanup_engine = intel_engine_cleanup; - } else { + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { dev_priv->gt.resume = intel_lr_context_resume; dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup; + } else { + dev_priv->gt.resume = intel_legacy_submission_resume; + dev_priv->gt.cleanup_engine = intel_engine_cleanup; } /* This is just a security blanket to placate dragons. diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index c1efbaf02bf2..c75941d3d7e7 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -460,14 +460,6 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); init_llist_head(&dev_priv->contexts.free_list); - if (intel_vgpu_active(dev_priv) && - HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { - if (!i915_modparams.enable_execlists) { - DRM_INFO("Only EXECLIST mode is supported in vgpu.\n"); - return -EINVAL; - } - } - /* Using the simple ida interface, the max is limited by sizeof(int) */ BUILD_BUG_ON(MAX_CONTEXT_HW_ID > INT_MAX); ida_init(&dev_priv->contexts.hw_ida); @@ -842,7 +834,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) struct intel_engine_cs *engine = req->engine; lockdep_assert_held(&req->i915->drm.struct_mutex); - GEM_BUG_ON(i915_modparams.enable_execlists); + GEM_BUG_ON(HAS_EXECLISTS(req->i915)); if (!req->ctx->engine[engine->id].state) { struct i915_gem_context *to = req->ctx; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index f92a39fc511c..e101b9a98957 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -178,7 +178,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, return 0; } - if (INTEL_GEN(dev_priv) >= 8 && i915_modparams.enable_execlists) { + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { if (has_full_48bit_ppgtt) return 3; @@ -2162,7 +2162,7 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv) /* In the case of execlists, PPGTT is enabled by the context descriptor * and the PDPs are contained within the context itself. We don't * need to do anything here. */ - if (i915_modparams.enable_execlists) + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) return 0; if (!USES_PPGTT(dev_priv)) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index b4faeb6aa2bd..d61c1787c164 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -99,10 +99,6 @@ i915_param_named_unsafe(enable_ppgtt, int, 0400, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)"); -i915_param_named_unsafe(enable_execlists, int, 0400, - "Override execlists usage. " - "(-1=auto [default], 0=disabled, 1=enabled)"); - i915_param_named_unsafe(enable_psr, int, 0600, "Enable PSR " "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index c7292268ed43..0aef3d7178eb 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -39,7 +39,6 @@ param(int, enable_dc, -1) \ param(int, enable_fbc, -1) \ param(int, enable_ppgtt, -1) \ - param(int, enable_execlists, -1) \ param(int, enable_psr, -1) \ param(int, disable_power_well, -1) \ param(int, enable_ips, 1) \ diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index adbce839a918..f0cfdece14ae 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1216,9 +1216,9 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915_modparams.enable_execlists) + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { dev_priv->perf.oa.specific_ctx_id = stream->ctx->hw_id; - else { + } else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; struct intel_ring *ring; int ret; @@ -1262,7 +1262,7 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915_modparams.enable_execlists) { + if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; } else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; @@ -3439,7 +3439,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) gen7_oa_hw_tail_read; dev_priv->perf.oa.oa_formats = hsw_oa_formats; - } else if (i915_modparams.enable_execlists) { + } else if (HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { /* Note: that although we could theoretically also support the * legacy ringbuffer mode on BDW (and earlier iterations of * this driver, before upstreaming did this) it didn't seem diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 9897c7f78c51..cae76f47fec2 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -164,9 +164,7 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) case 9: return GEN9_LR_CONTEXT_RENDER_SIZE; case 8: - return i915_modparams.enable_execlists ? - GEN8_LR_CONTEXT_RENDER_SIZE : - GEN8_CXT_TOTAL_SIZE; + return GEN8_LR_CONTEXT_RENDER_SIZE; case 7: if (IS_HASWELL(dev_priv)) return HSW_CXT_TOTAL_SIZE; @@ -316,7 +314,7 @@ int intel_engines_init(struct drm_i915_private *dev_priv) &intel_engine_classes[engine->class]; int (*init)(struct intel_engine_cs *engine); - if (i915_modparams.enable_execlists) + if (HAS_EXECLISTS(dev_priv)) init = class_info->init_execlists; else init = class_info->init_legacy; @@ -1739,7 +1737,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) drm_printf(m, "\tBBADDR: 0x%08x_%08x\n", upper_32_bits(addr), lower_32_bits(addr)); - if (i915_modparams.enable_execlists) { + if (HAS_EXECLISTS(dev_priv)) { const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; u32 ptr, read, write; unsigned int idx; diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index b4a7f31f0214..126f7c769c69 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -95,11 +95,6 @@ int intel_gvt_init(struct drm_i915_private *dev_priv) return 0; } - if (!i915_modparams.enable_execlists) { - DRM_ERROR("i915 GVT-g loading failed due to disabled execlists mode\n"); - return -EIO; - } - if (i915_modparams.enable_guc_submission) { DRM_ERROR("i915 GVT-g loading failed due to Graphics virtualization is not yet supported with GuC submission\n"); return -EIO; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8d0c49388863..16d4936e2368 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -218,37 +218,6 @@ static void execlists_init_reg_state(u32 *reg_state, struct intel_engine_cs *engine, struct intel_ring *ring); -/** - * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists - * @dev_priv: i915 device private - * @enable_execlists: value of i915.enable_execlists module parameter. - * - * Only certain platforms support Execlists (the prerequisites being - * support for Logical Ring Contexts and Aliasing PPGTT or better). - * - * Return: 1 if Execlists is supported and has to be enabled. - */ -int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, int enable_execlists) -{ - /* On platforms with execlist available, vGPU will only - * support execlist mode, no ring buffer mode. - */ - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv) && intel_vgpu_active(dev_priv)) - return 1; - - if (INTEL_GEN(dev_priv) >= 9) - return 1; - - if (enable_execlists == 0) - return 0; - - if (HAS_LOGICAL_RING_CONTEXTS(dev_priv) && - USES_PPGTT(dev_priv)) - return 1; - - return 0; -} - /** * intel_lr_context_descriptor_update() - calculate & cache the descriptor * descriptor for a pinned context diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 17182ce29674..6d4f9b995a11 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -107,8 +107,4 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx, return ctx->engine[engine->id].lrc_desc; } -/* Execlists */ -int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, - int enable_execlists); - #endif /* _INTEL_LRC_H_ */ -- cgit From 79e6770cb1f5e32eb49590edbb794a97d0113aed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 20:55:01 +0000 Subject: drm/i915: Remove obsolete ringbuffer emission for gen8+ Since removing the module parameter to force selection of ringbuffer emission for gen8, the code is defunct. Remove it. To put the difference into perspective, a couple of microbenchmarks (bdw i7-5557u, 20170324): ring execlists exec continuous nops on all rings: 1.491us 2.223us exec sequential nops on each ring: 12.508us 53.682us single nop + sync: 9.272us 30.291us vblank_mode=0 glxgears: ~11000fps ~9000fps Since the earlier submission, gen8 ringbuffer submission has fallen further and further behind in features. So while ringbuffer may hold the throughput crown, in terms of interactive latency, execlists is much better. Alas, we have no convenient metrics for such, other than demonstrating things we can do with execlists but can not using legacy ringbuffer submission. We have made a few improvements to lowlevel execlists throughput, and ringbuffer currently panics on boot! (bdw i7-5557u, 20171026): ring execlists exec continuous nops on all rings: n/a 1.921us exec sequential nops on each ring: n/a 44.621us single nop + sync: n/a 21.953us vblank_mode=0 glxgears: n/a ~18500fps References: https://bugs.freedesktop.org/show_bug.cgi?id=87725 Signed-off-by: Chris Wilson Once-upon-a-time-Reviewed-by: Joonas Lahtinen Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171120205504.21892-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 44 +--- drivers/gpu/drm/i915/i915_drv.h | 2 - drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 47 +--- drivers/gpu/drm/i915/i915_gpu_error.c | 36 --- drivers/gpu/drm/i915/intel_engine_cs.c | 14 -- drivers/gpu/drm/i915/intel_hangcheck.c | 44 +--- drivers/gpu/drm/i915/intel_ringbuffer.c | 431 +++++--------------------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 25 +- 9 files changed, 94 insertions(+), 551 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5e2a6e18771f..9cef1463d411 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3254,44 +3254,12 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) return ret; intel_runtime_pm_get(dev_priv); - if (IS_BROADWELL(dev_priv)) { - struct page *page; - uint64_t *seqno; - - page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0); - - seqno = (uint64_t *)kmap_atomic(page); - for_each_engine(engine, dev_priv, id) { - uint64_t offset; - - seq_printf(m, "%s\n", engine->name); - - seq_puts(m, " Last signal:"); - for (j = 0; j < num_rings; j++) { - offset = id * I915_NUM_ENGINES + j; - seq_printf(m, "0x%08llx (0x%02llx) ", - seqno[offset], offset * 8); - } - seq_putc(m, '\n'); - - seq_puts(m, " Last wait: "); - for (j = 0; j < num_rings; j++) { - offset = id + (j * I915_NUM_ENGINES); - seq_printf(m, "0x%08llx (0x%02llx) ", - seqno[offset], offset * 8); - } - seq_putc(m, '\n'); - - } - kunmap_atomic(seqno); - } else { - seq_puts(m, " Last signal:"); - for_each_engine(engine, dev_priv, id) - for (j = 0; j < num_rings; j++) - seq_printf(m, "0x%08x\n", - I915_READ(engine->semaphore.mbox.signal[j])); - seq_putc(m, '\n'); - } + seq_puts(m, " Last signal:"); + for_each_engine(engine, dev_priv, id) + for (j = 0; j < num_rings; j++) + seq_printf(m, "0x%08x\n", + I915_READ(engine->semaphore.mbox.signal[j])); + seq_putc(m, '\n'); intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d2c6ba7f8acd..5ce778c26bb8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -942,7 +942,6 @@ struct i915_gpu_state { u64 fence[I915_MAX_NUM_FENCES]; struct intel_overlay_error_state *overlay; struct intel_display_error_state *display; - struct drm_i915_error_object *semaphore; struct drm_i915_error_engine { int engine_id; @@ -2291,7 +2290,6 @@ struct drm_i915_private { struct i915_gem_context *kernel_context; /* Context only to be used for injecting preemption commands */ struct i915_gem_context *preempt_context; - struct i915_vma *semaphore; struct drm_dma_handle *status_page_dmah; struct resource mch_res; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 494c6be035b2..d470e10b2edd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4999,7 +4999,7 @@ out: bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) { - if (INTEL_INFO(dev_priv)->gen < 6) + if (INTEL_GEN(dev_priv) < 6) return false; /* TODO: make semaphores and Execlists play nicely together */ diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index c75941d3d7e7..0704d9af261b 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -574,21 +574,21 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) enum intel_engine_id id; const int num_rings = /* Use an extended w/a on gen7 if signalling from other rings */ - (i915_modparams.semaphores && INTEL_GEN(dev_priv) == 7) ? + (i915_modparams.semaphores && IS_GEN7(dev_priv)) ? INTEL_INFO(dev_priv)->num_rings - 1 : 0; int len; u32 *cs; flags |= MI_MM_SPACE_GTT; - if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8) + if (IS_HASWELL(dev_priv)) /* These flags are for resource streamer on HSW+ */ flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN; else flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN; len = 4; - if (INTEL_GEN(dev_priv) >= 7) + if (IS_GEN7(dev_priv)) len += 2 + (num_rings ? 4*num_rings + 6 : 0); cs = intel_ring_begin(req, len); @@ -596,7 +596,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) return PTR_ERR(cs); /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ - if (INTEL_GEN(dev_priv) >= 7) { + if (IS_GEN7(dev_priv)) { *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; if (num_rings) { struct intel_engine_cs *signaller; @@ -623,7 +623,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) */ *cs++ = MI_NOOP; - if (INTEL_GEN(dev_priv) >= 7) { + if (IS_GEN7(dev_priv)) { if (num_rings) { struct intel_engine_cs *signaller; i915_reg_t last_reg = {}; /* keep gcc quiet */ @@ -714,27 +714,7 @@ needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt, struct intel_engine_cs *engine) if (engine->id != RCS) return true; - if (INTEL_GEN(engine->i915) < 8) - return true; - - return false; -} - -static bool -needs_pd_load_post(struct i915_hw_ppgtt *ppgtt, - struct i915_gem_context *to, - u32 hw_flags) -{ - if (!ppgtt) - return false; - - if (!IS_GEN8(to->i915)) - return false; - - if (hw_flags & MI_RESTORE_INHIBIT) - return true; - - return false; + return true; } static int do_rcs_switch(struct drm_i915_gem_request *req) @@ -784,21 +764,6 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) engine->legacy_active_context = to; } - /* GEN8 does *not* require an explicit reload if the PDPs have been - * setup, and we do not wish to move them. - */ - if (needs_pd_load_post(ppgtt, to, hw_flags)) { - trace_switch_mm(engine, to); - ret = ppgtt->switch_mm(ppgtt, req); - /* The hardware context switch is emitted, but we haven't - * actually changed the state - so it's probably safe to bail - * here. Still, let the user know something dangerous has - * happened. - */ - if (ret) - return ret; - } - if (ppgtt) ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7481c8e1b5a8..3d18d67d065f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -793,8 +793,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, "WA batchbuffer", ee->wa_batchbuffer); } - print_error_obj(m, NULL, "Semaphores", error->semaphore); - if (error->overlay) intel_overlay_print_error_state(m, error->overlay); @@ -903,8 +901,6 @@ void __i915_gpu_state_free(struct kref *error_ref) kfree(ee->waiters); } - i915_error_object_free(error->semaphore); - for (i = 0; i < ARRAY_SIZE(error->active_bo); i++) kfree(error->active_bo[i]); kfree(error->pinned_bo); @@ -1116,34 +1112,6 @@ gen8_engine_sync_index(struct intel_engine_cs *engine, return idx; } -static void gen8_record_semaphore_state(struct i915_gpu_state *error, - struct intel_engine_cs *engine, - struct drm_i915_error_engine *ee) -{ - struct drm_i915_private *dev_priv = engine->i915; - struct intel_engine_cs *to; - enum intel_engine_id id; - - if (!error->semaphore) - return; - - for_each_engine(to, dev_priv, id) { - int idx; - u16 signal_offset; - u32 *tmp; - - if (engine == to) - continue; - - signal_offset = - (GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1)) / 4; - tmp = error->semaphore->pages[0]; - idx = gen8_engine_sync_index(engine, to); - - ee->semaphore_mboxes[idx] = tmp[signal_offset]; - } -} - static void gen6_record_semaphore_state(struct intel_engine_cs *engine, struct drm_i915_error_engine *ee) { @@ -1218,7 +1186,6 @@ static void error_record_engine_registers(struct i915_gpu_state *error, if (INTEL_GEN(dev_priv) >= 6) { ee->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base)); if (INTEL_GEN(dev_priv) >= 8) { - gen8_record_semaphore_state(error, engine, ee); ee->fault_reg = I915_READ(GEN8_RING_FAULT_REG); } else { gen6_record_semaphore_state(engine, ee); @@ -1453,9 +1420,6 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, struct i915_ggtt *ggtt = &dev_priv->ggtt; int i; - error->semaphore = - i915_error_object_create(dev_priv, dev_priv->semaphore); - for (i = 0; i < I915_NUM_ENGINES; i++) { struct intel_engine_cs *engine = dev_priv->engine[i]; struct drm_i915_error_engine *ee = &error->engine[i]; diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index cae76f47fec2..1fca7ac3b059 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -37,8 +37,6 @@ * Resource Streamer, is 66944 bytes, which rounds to 17 pages. */ #define HSW_CXT_TOTAL_SIZE (17 * PAGE_SIZE) -/* Same as Haswell, but 72064 bytes now. */ -#define GEN8_CXT_TOTAL_SIZE (18 * PAGE_SIZE) #define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE) #define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE) @@ -364,18 +362,6 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) if (HAS_VEBOX(dev_priv)) I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); } - if (dev_priv->semaphore) { - struct page *page = i915_vma_first_page(dev_priv->semaphore); - void *semaphores; - - /* Semaphores are in noncoherent memory, flush to be safe */ - semaphores = kmap_atomic(page); - memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), - 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); - drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), - I915_NUM_ENGINES * gen8_semaphore_seqno_size); - kunmap_atomic(semaphores); - } intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted); diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index 12ac270a5f93..95bbb5a79c4f 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -27,13 +27,9 @@ static bool ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr) { - if (INTEL_GEN(engine->i915) >= 8) { - return (ipehr >> 23) == 0x1c; - } else { - ipehr &= ~MI_SEMAPHORE_SYNC_MASK; - return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | - MI_SEMAPHORE_REGISTER); - } + ipehr &= ~MI_SEMAPHORE_SYNC_MASK; + return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | + MI_SEMAPHORE_REGISTER); } static struct intel_engine_cs * @@ -41,31 +37,20 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, u64 offset) { struct drm_i915_private *dev_priv = engine->i915; + u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; struct intel_engine_cs *signaller; enum intel_engine_id id; - if (INTEL_GEN(dev_priv) >= 8) { - for_each_engine(signaller, dev_priv, id) { - if (engine == signaller) - continue; - - if (offset == signaller->semaphore.signal_ggtt[engine->hw_id]) - return signaller; - } - } else { - u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; - - for_each_engine(signaller, dev_priv, id) { - if(engine == signaller) - continue; + for_each_engine(signaller, dev_priv, id) { + if (engine == signaller) + continue; - if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) - return signaller; - } + if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) + return signaller; } - DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n", - engine->name, ipehr, offset); + DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x\n", + engine->name, ipehr); return ERR_PTR(-ENODEV); } @@ -135,11 +120,6 @@ semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno) return NULL; *seqno = ioread32(vaddr + head + 4) + 1; - if (INTEL_GEN(dev_priv) >= 8) { - offset = ioread32(vaddr + head + 12); - offset <<= 32; - offset |= ioread32(vaddr + head + 8); - } return semaphore_wait_to_signaller_ring(engine, ipehr, offset); } @@ -273,7 +253,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) return ENGINE_WAIT_KICK; } - if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) { + if (IS_GEN(dev_priv, 6, 7) && tmp & RING_WAIT_SEMAPHORE) { switch (semaphore_passed(engine)) { default: return ENGINE_DEAD; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index be98868115bf..5465e708545f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -340,50 +340,6 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) return 0; } -static int -gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) -{ - u32 flags; - u32 *cs; - - cs = intel_ring_begin(req, mode & EMIT_INVALIDATE ? 12 : 6); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - flags = PIPE_CONTROL_CS_STALL; - - if (mode & EMIT_FLUSH) { - flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; - flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; - flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; - flags |= PIPE_CONTROL_FLUSH_ENABLE; - } - if (mode & EMIT_INVALIDATE) { - flags |= PIPE_CONTROL_TLB_INVALIDATE; - flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; - flags |= PIPE_CONTROL_QW_WRITE; - flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; - - /* WaCsStallBeforeStateCacheInvalidate:bdw,chv */ - cs = gen8_emit_pipe_control(cs, - PIPE_CONTROL_CS_STALL | - PIPE_CONTROL_STALL_AT_SCOREBOARD, - 0); - } - - cs = gen8_emit_pipe_control(cs, flags, - i915_ggtt_offset(req->engine->scratch) + - 2 * CACHELINE_BYTES); - - intel_ring_advance(req, cs); - - return 0; -} - static void ring_setup_phys_status_page(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; @@ -427,7 +383,6 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) } else if (IS_GEN6(dev_priv)) { mmio = RING_HWS_PGA_GEN6(engine->mmio_base); } else { - /* XXX: gen8 returns to sanity */ mmio = RING_HWS_PGA(engine->mmio_base); } @@ -437,13 +392,7 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) I915_WRITE(mmio, engine->status_page.ggtt_offset); POSTING_READ(mmio); - /* - * Flush the TLB for this page - * - * FIXME: These two bits have disappeared on gen8, so a question - * arises: do we still need this and if so how should we go about - * invalidating the TLB? - */ + /* Flush the TLB for this page */ if (IS_GEN(dev_priv, 6, 7)) { i915_reg_t reg = RING_INSTPM(engine->mmio_base); @@ -611,8 +560,6 @@ static void reset_ring_common(struct intel_engine_cs *engine, struct intel_context *ce = &request->ctx->engine[engine->id]; struct i915_hw_ppgtt *ppgtt; - /* FIXME consider gen8 reset */ - if (ce->state) { I915_WRITE(CCID, i915_ggtt_offset(ce->state) | @@ -713,62 +660,6 @@ static int init_render_ring(struct intel_engine_cs *engine) return init_workarounds_ring(engine); } -static void render_ring_cleanup(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - i915_vma_unpin_and_release(&dev_priv->semaphore); -} - -static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *cs) -{ - struct drm_i915_private *dev_priv = req->i915; - struct intel_engine_cs *waiter; - enum intel_engine_id id; - - for_each_engine(waiter, dev_priv, id) { - u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; - if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) - continue; - - *cs++ = GFX_OP_PIPE_CONTROL(6); - *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_CS_STALL; - *cs++ = lower_32_bits(gtt_offset); - *cs++ = upper_32_bits(gtt_offset); - *cs++ = req->global_seqno; - *cs++ = 0; - *cs++ = MI_SEMAPHORE_SIGNAL | - MI_SEMAPHORE_TARGET(waiter->hw_id); - *cs++ = 0; - } - - return cs; -} - -static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *cs) -{ - struct drm_i915_private *dev_priv = req->i915; - struct intel_engine_cs *waiter; - enum intel_engine_id id; - - for_each_engine(waiter, dev_priv, id) { - u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; - if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) - continue; - - *cs++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW; - *cs++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT; - *cs++ = upper_32_bits(gtt_offset); - *cs++ = req->global_seqno; - *cs++ = MI_SEMAPHORE_SIGNAL | - MI_SEMAPHORE_TARGET(waiter->hw_id); - *cs++ = 0; - } - - return cs; -} - static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs) { struct drm_i915_private *dev_priv = req->i915; @@ -851,70 +742,6 @@ static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) req->engine->semaphore.signal(req, cs)); } -static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req, - u32 *cs) -{ - struct intel_engine_cs *engine = req->engine; - - if (engine->semaphore.signal) - cs = engine->semaphore.signal(req, cs); - - *cs++ = GFX_OP_PIPE_CONTROL(6); - *cs++ = PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | - PIPE_CONTROL_QW_WRITE; - *cs++ = intel_hws_seqno_address(engine); - *cs++ = 0; - *cs++ = req->global_seqno; - /* We're thrashing one dword of HWS. */ - *cs++ = 0; - *cs++ = MI_USER_INTERRUPT; - *cs++ = MI_NOOP; - - req->tail = intel_ring_offset(req, cs); - assert_ring_tail_valid(req->ring, req->tail); -} - -static const int gen8_render_emit_breadcrumb_sz = 8; - -/** - * intel_ring_sync - sync the waiter to the signaller on seqno - * - * @waiter - ring that is waiting - * @signaller - ring which has, or will signal - * @seqno - seqno which the waiter will block on - */ - -static int -gen8_ring_sync_to(struct drm_i915_gem_request *req, - struct drm_i915_gem_request *signal) -{ - struct drm_i915_private *dev_priv = req->i915; - u64 offset = GEN8_WAIT_OFFSET(req->engine, signal->engine->id); - struct i915_hw_ppgtt *ppgtt; - u32 *cs; - - cs = intel_ring_begin(req, 4); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - *cs++ = MI_SEMAPHORE_WAIT | MI_SEMAPHORE_GLOBAL_GTT | - MI_SEMAPHORE_SAD_GTE_SDD; - *cs++ = signal->global_seqno; - *cs++ = lower_32_bits(offset); - *cs++ = upper_32_bits(offset); - intel_ring_advance(req, cs); - - /* When the !RCS engines idle waiting upon a semaphore, they lose their - * pagetables and we must reload them before executing the batch. - * We do this on the i915_switch_context() following the wait and - * before the dispatch. - */ - ppgtt = req->ctx->ppgtt; - if (ppgtt && req->engine->id != RCS) - ppgtt->pd_dirty_rings |= intel_engine_flag(req->engine); - return 0; -} - static int gen6_ring_sync_to(struct drm_i915_gem_request *req, struct drm_i915_gem_request *signal) @@ -1090,25 +917,6 @@ hsw_vebox_irq_disable(struct intel_engine_cs *engine) gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask); } -static void -gen8_irq_enable(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - I915_WRITE_IMR(engine, - ~(engine->irq_enable_mask | - engine->irq_keep_mask)); - POSTING_READ_FW(RING_IMR(engine->mmio_base)); -} - -static void -gen8_irq_disable(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - I915_WRITE_IMR(engine, ~engine->irq_keep_mask); -} - static int i965_emit_bb_start(struct drm_i915_gem_request *req, u64 offset, u32 length, @@ -1796,8 +1604,6 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) return PTR_ERR(cs); cmd = MI_FLUSH_DW; - if (INTEL_GEN(req->i915) >= 8) - cmd += 1; /* We always require a command barrier so that subsequent * commands, such as breadcrumb interrupts, are strictly ordered @@ -1817,38 +1623,9 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 mode) *cs++ = cmd; *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; - if (INTEL_GEN(req->i915) >= 8) { - *cs++ = 0; /* upper addr */ - *cs++ = 0; /* value */ - } else { - *cs++ = 0; - *cs++ = MI_NOOP; - } - intel_ring_advance(req, cs); - return 0; -} - -static int -gen8_emit_bb_start(struct drm_i915_gem_request *req, - u64 offset, u32 len, - unsigned int dispatch_flags) -{ - bool ppgtt = USES_PPGTT(req->i915) && - !(dispatch_flags & I915_DISPATCH_SECURE); - u32 *cs; - - cs = intel_ring_begin(req, 4); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - /* FIXME(BDW): Address space and security selectors. */ - *cs++ = MI_BATCH_BUFFER_START_GEN8 | (ppgtt << 8) | (dispatch_flags & - I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0); - *cs++ = lower_32_bits(offset); - *cs++ = upper_32_bits(offset); + *cs++ = 0; *cs++ = MI_NOOP; intel_ring_advance(req, cs); - return 0; } @@ -1905,8 +1682,6 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) return PTR_ERR(cs); cmd = MI_FLUSH_DW; - if (INTEL_GEN(req->i915) >= 8) - cmd += 1; /* We always require a command barrier so that subsequent * commands, such as breadcrumb interrupts, are strictly ordered @@ -1925,13 +1700,8 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) cmd |= MI_INVALIDATE_TLB; *cs++ = cmd; *cs++ = I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT; - if (INTEL_GEN(req->i915) >= 8) { - *cs++ = 0; /* upper addr */ - *cs++ = 0; /* value */ - } else { - *cs++ = 0; - *cs++ = MI_NOOP; - } + *cs++ = 0; + *cs++ = MI_NOOP; intel_ring_advance(req, cs); return 0; @@ -1940,110 +1710,61 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 mode) static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, struct intel_engine_cs *engine) { - struct drm_i915_gem_object *obj; - int ret, i; + int i; if (!i915_modparams.semaphores) return; - if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { - struct i915_vma *vma; - - obj = i915_gem_object_create(dev_priv, PAGE_SIZE); - if (IS_ERR(obj)) - goto err; - - vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL); - if (IS_ERR(vma)) - goto err_obj; - - ret = i915_gem_object_set_to_gtt_domain(obj, false); - if (ret) - goto err_obj; - - ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); - if (ret) - goto err_obj; + GEM_BUG_ON(INTEL_GEN(dev_priv) < 6); + engine->semaphore.sync_to = gen6_ring_sync_to; + engine->semaphore.signal = gen6_signal; - dev_priv->semaphore = vma; - } - - if (INTEL_GEN(dev_priv) >= 8) { - u32 offset = i915_ggtt_offset(dev_priv->semaphore); - - engine->semaphore.sync_to = gen8_ring_sync_to; - engine->semaphore.signal = gen8_xcs_signal; - - for (i = 0; i < I915_NUM_ENGINES; i++) { - u32 ring_offset; - - if (i != engine->id) - ring_offset = offset + GEN8_SEMAPHORE_OFFSET(engine->id, i); - else - ring_offset = MI_SEMAPHORE_SYNC_INVALID; - - engine->semaphore.signal_ggtt[i] = ring_offset; - } - } else if (INTEL_GEN(dev_priv) >= 6) { - engine->semaphore.sync_to = gen6_ring_sync_to; - engine->semaphore.signal = gen6_signal; - - /* - * The current semaphore is only applied on pre-gen8 - * platform. And there is no VCS2 ring on the pre-gen8 - * platform. So the semaphore between RCS and VCS2 is - * initialized as INVALID. Gen8 will initialize the - * sema between VCS2 and RCS later. - */ - for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) { - static const struct { - u32 wait_mbox; - i915_reg_t mbox_reg; - } sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = { - [RCS_HW] = { - [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, - [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, - [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, - }, - [VCS_HW] = { - [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, - [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, - [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, - }, - [BCS_HW] = { - [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, - [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, - [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, - }, - [VECS_HW] = { - [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, - [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, - [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, - }, - }; + /* + * The current semaphore is only applied on pre-gen8 + * platform. And there is no VCS2 ring on the pre-gen8 + * platform. So the semaphore between RCS and VCS2 is + * initialized as INVALID. + */ + for (i = 0; i < GEN6_NUM_SEMAPHORES; i++) { + static const struct { u32 wait_mbox; i915_reg_t mbox_reg; + } sem_data[GEN6_NUM_SEMAPHORES][GEN6_NUM_SEMAPHORES] = { + [RCS_HW] = { + [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RV, .mbox_reg = GEN6_VRSYNC }, + [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RB, .mbox_reg = GEN6_BRSYNC }, + [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_RVE, .mbox_reg = GEN6_VERSYNC }, + }, + [VCS_HW] = { + [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VR, .mbox_reg = GEN6_RVSYNC }, + [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VB, .mbox_reg = GEN6_BVSYNC }, + [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VVE, .mbox_reg = GEN6_VEVSYNC }, + }, + [BCS_HW] = { + [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BR, .mbox_reg = GEN6_RBSYNC }, + [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BV, .mbox_reg = GEN6_VBSYNC }, + [VECS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_BVE, .mbox_reg = GEN6_VEBSYNC }, + }, + [VECS_HW] = { + [RCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VER, .mbox_reg = GEN6_RVESYNC }, + [VCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEV, .mbox_reg = GEN6_VVESYNC }, + [BCS_HW] = { .wait_mbox = MI_SEMAPHORE_SYNC_VEB, .mbox_reg = GEN6_BVESYNC }, + }, + }; + u32 wait_mbox; + i915_reg_t mbox_reg; - if (i == engine->hw_id) { - wait_mbox = MI_SEMAPHORE_SYNC_INVALID; - mbox_reg = GEN6_NOSYNC; - } else { - wait_mbox = sem_data[engine->hw_id][i].wait_mbox; - mbox_reg = sem_data[engine->hw_id][i].mbox_reg; - } - - engine->semaphore.mbox.wait[i] = wait_mbox; - engine->semaphore.mbox.signal[i] = mbox_reg; + if (i == engine->hw_id) { + wait_mbox = MI_SEMAPHORE_SYNC_INVALID; + mbox_reg = GEN6_NOSYNC; + } else { + wait_mbox = sem_data[engine->hw_id][i].wait_mbox; + mbox_reg = sem_data[engine->hw_id][i].mbox_reg; } - } - - return; -err_obj: - i915_gem_object_put(obj); -err: - DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); - i915_modparams.semaphores = 0; + engine->semaphore.mbox.wait[i] = wait_mbox; + engine->semaphore.mbox.signal[i] = mbox_reg; + } } static void intel_ring_init_irq(struct drm_i915_private *dev_priv, @@ -2051,11 +1772,7 @@ static void intel_ring_init_irq(struct drm_i915_private *dev_priv, { engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << engine->irq_shift; - if (INTEL_GEN(dev_priv) >= 8) { - engine->irq_enable = gen8_irq_enable; - engine->irq_disable = gen8_irq_disable; - engine->irq_seqno_barrier = gen6_seqno_barrier; - } else if (INTEL_GEN(dev_priv) >= 6) { + if (INTEL_GEN(dev_priv) >= 6) { engine->irq_enable = gen6_irq_enable; engine->irq_disable = gen6_irq_disable; engine->irq_seqno_barrier = gen6_seqno_barrier; @@ -2090,6 +1807,9 @@ static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, struct intel_engine_cs *engine) { + /* gen8+ are only supported with execlists */ + GEM_BUG_ON(INTEL_GEN(dev_priv) >= 8); + intel_ring_init_irq(dev_priv, engine); intel_ring_init_semaphores(dev_priv, engine); @@ -2109,20 +1829,14 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; num_rings = INTEL_INFO(dev_priv)->num_rings - 1; - if (INTEL_GEN(dev_priv) >= 8) { - engine->emit_breadcrumb_sz += num_rings * 6; - } else { - engine->emit_breadcrumb_sz += num_rings * 3; - if (num_rings & 1) - engine->emit_breadcrumb_sz++; - } + engine->emit_breadcrumb_sz += num_rings * 3; + if (num_rings & 1) + engine->emit_breadcrumb_sz++; } engine->set_default_submission = i9xx_set_default_submission; - if (INTEL_GEN(dev_priv) >= 8) - engine->emit_bb_start = gen8_emit_bb_start; - else if (INTEL_GEN(dev_priv) >= 6) + if (INTEL_GEN(dev_priv) >= 6) engine->emit_bb_start = gen6_emit_bb_start; else if (INTEL_GEN(dev_priv) >= 4) engine->emit_bb_start = i965_emit_bb_start; @@ -2142,20 +1856,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) if (HAS_L3_DPF(dev_priv)) engine->irq_keep_mask = GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - if (INTEL_GEN(dev_priv) >= 8) { - engine->init_context = intel_rcs_ctx_init; - engine->emit_breadcrumb = gen8_render_emit_breadcrumb; - engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; - engine->emit_flush = gen8_render_ring_flush; - if (i915_modparams.semaphores) { - int num_rings; - - engine->semaphore.signal = gen8_rcs_signal; - - num_rings = INTEL_INFO(dev_priv)->num_rings - 1; - engine->emit_breadcrumb_sz += num_rings * 8; - } - } else if (INTEL_GEN(dev_priv) >= 6) { + if (INTEL_GEN(dev_priv) >= 6) { engine->init_context = intel_rcs_ctx_init; engine->emit_flush = gen7_render_ring_flush; if (IS_GEN6(dev_priv)) @@ -2174,7 +1875,6 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) engine->emit_bb_start = hsw_emit_bb_start; engine->init_hw = init_render_ring; - engine->cleanup = render_ring_cleanup; ret = intel_init_ring_buffer(engine); if (ret) @@ -2204,8 +1904,7 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine) if (IS_GEN6(dev_priv)) engine->set_default_submission = gen6_bsd_set_default_submission; engine->emit_flush = gen6_bsd_ring_flush; - if (INTEL_GEN(dev_priv) < 8) - engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; + engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; } else { engine->mmio_base = BSD_RING_BASE; engine->emit_flush = bsd_ring_flush; @@ -2225,8 +1924,7 @@ int intel_init_blt_ring_buffer(struct intel_engine_cs *engine) intel_ring_default_vfuncs(dev_priv, engine); engine->emit_flush = gen6_ring_flush; - if (INTEL_GEN(dev_priv) < 8) - engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; + engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; return intel_init_ring_buffer(engine); } @@ -2238,12 +1936,9 @@ int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine) intel_ring_default_vfuncs(dev_priv, engine); engine->emit_flush = gen6_ring_flush; - - if (INTEL_GEN(dev_priv) < 8) { - engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; - engine->irq_enable = hsw_vebox_irq_enable; - engine->irq_disable = hsw_vebox_irq_disable; - } + engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; + engine->irq_enable = hsw_vebox_irq_enable; + engine->irq_disable = hsw_vebox_irq_disable; return intel_init_ring_buffer(engine); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index e437a9556c08..80cd7812ce02 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -46,16 +46,6 @@ struct intel_hw_status_page { /* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to * do the writes, and that must have qw aligned offsets, simply pretend it's 8b. */ -#define gen8_semaphore_seqno_size sizeof(uint64_t) -#define GEN8_SEMAPHORE_OFFSET(__from, __to) \ - (((__from) * I915_NUM_ENGINES + (__to)) * gen8_semaphore_seqno_size) -#define GEN8_SIGNAL_OFFSET(__ring, to) \ - (dev_priv->semaphore->node.start + \ - GEN8_SEMAPHORE_OFFSET((__ring)->id, (to))) -#define GEN8_WAIT_OFFSET(__ring, from) \ - (dev_priv->semaphore->node.start + \ - GEN8_SEMAPHORE_OFFSET(from, (__ring)->id)) - enum intel_engine_hangcheck_action { ENGINE_IDLE = 0, ENGINE_WAIT, @@ -467,18 +457,15 @@ struct intel_engine_cs { * ie. transpose of f(x, y) */ struct { - union { #define GEN6_SEMAPHORE_LAST VECS_HW #define GEN6_NUM_SEMAPHORES (GEN6_SEMAPHORE_LAST + 1) #define GEN6_SEMAPHORES_MASK GENMASK(GEN6_SEMAPHORE_LAST, 0) - struct { - /* our mbox written by others */ - u32 wait[GEN6_NUM_SEMAPHORES]; - /* mboxes this ring signals to */ - i915_reg_t signal[GEN6_NUM_SEMAPHORES]; - } mbox; - u64 signal_ggtt[I915_NUM_ENGINES]; - }; + struct { + /* our mbox written by others */ + u32 wait[GEN6_NUM_SEMAPHORES]; + /* mboxes this ring signals to */ + i915_reg_t signal[GEN6_NUM_SEMAPHORES]; + } mbox; /* AKA wait() */ int (*sync_to)(struct drm_i915_gem_request *req, -- cgit From 0da715ee60774401bea00dc71fca6fd1096c734a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 20:55:02 +0000 Subject: drm/i915: Disable semaphores on Sandybridge I should have admitted defeat long ago as there has been a rare but persistent error on Sandybridge where semaphore signaling did not propagate to the waiter, leading to a GPU hang. With the work on fence signaling for v4.9, the impact of using CPU driven signaling was greatly reduced wrt to the latency of GPU semaphores, though without logical rings support, the benefit of reordering work to avoid bubbles is not realised (i.e. as it stands fence signaling is just a slower, more costly version of HW semaphores; but works more consistently). As a rough indicator of the difference, with semaphores: Sequential (3 engines, 1 processes): average 5.470us per cycle [expected 4.988us] w/o semaphores: Sequential (3 engines, 1 processes): average 15.771us per cycle [expected 4.923us] In comparison, v3.4: with semaphores: Sequential (3 engines, 1 processes): average 16.066us per cycle [expected 11.842us] w/o semaphores: Sequential (3 engines, 1 processes): average 23.460us per cycle [expected 11.839us] Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54226 #and 100+ dupes Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Acked-by: Mika Kuoppala Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171120205504.21892-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d470e10b2edd..d53bb8e872ba 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4999,20 +4999,12 @@ out: bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) { - if (INTEL_GEN(dev_priv) < 6) - return false; - - /* TODO: make semaphores and Execlists play nicely together */ - if (HAS_EXECLISTS(dev_priv)) + if (!IS_GEN7(dev_priv)) return false; if (value >= 0) return value; - /* Enable semaphores on SNB when IO remapping is off */ - if (IS_GEN6(dev_priv) && intel_vtd_active()) - return false; - return true; } -- cgit From af9ff6c70df452b42779aac1bb787ec72d5f257b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 20:55:03 +0000 Subject: drm/i915: Move debugfs/i915_semaphore_status to i915_engine_info As the semaphores is just part of the engine, include it with the general pretty printer universally used for debugging. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171120205504.21892-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 32 -------------------------------- drivers/gpu/drm/i915/intel_engine_cs.c | 9 +++++++++ 2 files changed, 9 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9cef1463d411..41d49a4d25d3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3235,37 +3235,6 @@ static int i915_shrinker_info(struct seq_file *m, void *unused) return 0; } -static int i915_semaphore_status(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_engine_cs *engine; - int num_rings = INTEL_INFO(dev_priv)->num_rings; - enum intel_engine_id id; - int j, ret; - - if (!i915_modparams.semaphores) { - seq_puts(m, "Semaphores are disabled\n"); - return 0; - } - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - intel_runtime_pm_get(dev_priv); - - seq_puts(m, " Last signal:"); - for_each_engine(engine, dev_priv, id) - for (j = 0; j < num_rings; j++) - seq_printf(m, "0x%08x\n", - I915_READ(engine->semaphore.mbox.signal[j])); - seq_putc(m, '\n'); - - intel_runtime_pm_put(dev_priv); - mutex_unlock(&dev->struct_mutex); - return 0; -} - static int i915_shared_dplls_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -4745,7 +4714,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_display_info", i915_display_info, 0}, {"i915_engine_info", i915_engine_info, 0}, {"i915_shrinker_info", i915_shrinker_info, 0}, - {"i915_semaphore_status", i915_semaphore_status, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, {"i915_dp_mst_info", i915_dp_mst_info, 0}, {"i915_wa_registers", i915_wa_registers, 0}, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 1fca7ac3b059..ef8e101ebd98 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1713,6 +1713,15 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) I915_READ(RING_MI_MODE(engine->mmio_base)), I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); } + if (i915_modparams.semaphores) { + drm_printf(m, "\tSYNC_0: 0x%08x\n", + I915_READ(RING_SYNC_0(engine->mmio_base))); + drm_printf(m, "\tSYNC_1: 0x%08x\n", + I915_READ(RING_SYNC_1(engine->mmio_base))); + if (HAS_VEBOX(dev_priv)) + drm_printf(m, "\tSYNC_2: 0x%08x\n", + I915_READ(RING_SYNC_2(engine->mmio_base))); + } rcu_read_unlock(); -- cgit From 93c6e966b4cd1c99d02b488e149df606f811587b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 20:55:04 +0000 Subject: drm/i915: Remove i915.semaphores modparam Having disabled the broken semaphores on Sandybridge, there is no need for a modparam any more, so remove it in favour of a simple HAS_LEGACY_SEMAPHORES() guard. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Maarten Lankhorst Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171120205504.21892-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 7 +------ drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 11 ----------- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_params.c | 4 ---- drivers/gpu/drm/i915/i915_params.h | 1 - drivers/gpu/drm/i915/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 ++-- 8 files changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c608fd96771c..8dbcb03b5f54 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -321,7 +321,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = USES_PPGTT(dev_priv); break; case I915_PARAM_HAS_SEMAPHORES: - value = i915_modparams.semaphores; + value = HAS_LEGACY_SEMAPHORES(dev_priv); break; case I915_PARAM_HAS_SECURE_BATCHES: value = capable(CAP_SYS_ADMIN); @@ -1063,11 +1063,6 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) i915_modparams.enable_ppgtt); DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); - i915_modparams.semaphores = - intel_sanitize_semaphores(dev_priv, i915_modparams.semaphores); - DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", - yesno(i915_modparams.semaphores)); - intel_uc_sanitize_options(dev_priv); intel_gvt_sanitize_options(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5ce778c26bb8..9a0654e10a55 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3139,6 +3139,8 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_BLT(dev_priv) HAS_ENGINE(dev_priv, BCS) #define HAS_VEBOX(dev_priv) HAS_ENGINE(dev_priv, VECS) +#define HAS_LEGACY_SEMAPHORES(dev_priv) IS_GEN7(dev_priv) + #define HAS_LLC(dev_priv) ((dev_priv)->info.has_llc) #define HAS_SNOOP(dev_priv) ((dev_priv)->info.has_snoop) #define HAS_EDRAM(dev_priv) (!!((dev_priv)->edram_cap & EDRAM_ENABLED)) @@ -3302,8 +3304,6 @@ intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv) int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, int enable_ppgtt); -bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value); - /* i915_drv.c */ void __printf(3, 4) __i915_printk(struct drm_i915_private *dev_priv, const char *level, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d53bb8e872ba..792e6dc7e19b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4997,17 +4997,6 @@ out: return ret; } -bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) -{ - if (!IS_GEN7(dev_priv)) - return false; - - if (value >= 0) - return value; - - return true; -} - static int __intel_engines_record_defaults(struct drm_i915_private *i915) { struct i915_gem_context *ctx; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 0704d9af261b..6ca56e482d79 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -574,7 +574,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) enum intel_engine_id id; const int num_rings = /* Use an extended w/a on gen7 if signalling from other rings */ - (i915_modparams.semaphores && IS_GEN7(dev_priv)) ? + (HAS_LEGACY_SEMAPHORES(dev_priv) && IS_GEN7(dev_priv)) ? INTEL_INFO(dev_priv)->num_rings - 1 : 0; int len; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index d61c1787c164..3328147b4863 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,10 +46,6 @@ i915_param_named_unsafe(panel_ignore_lid, int, 0600, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); -i915_param_named_unsafe(semaphores, int, 0400, - "Use semaphores for inter-ring sync " - "(default: -1 (use per-chip defaults))"); - i915_param_named_unsafe(enable_rc6, int, 0400, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 0aef3d7178eb..8321bd86cba5 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -31,7 +31,6 @@ param(char *, vbt_firmware, NULL) \ param(int, modeset, -1) \ param(int, panel_ignore_lid, 1) \ - param(int, semaphores, -1) \ param(int, lvds_channel_mode, 0) \ param(int, panel_use_ssc, -1) \ param(int, vbt_sdvo_panel_type, -1) \ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index ef8e101ebd98..22c095035539 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1713,7 +1713,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) I915_READ(RING_MI_MODE(engine->mmio_base)), I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); } - if (i915_modparams.semaphores) { + if (HAS_LEGACY_SEMAPHORES(dev_priv)) { drm_printf(m, "\tSYNC_0: 0x%08x\n", I915_READ(RING_SYNC_0(engine->mmio_base))); drm_printf(m, "\tSYNC_1: 0x%08x\n", diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5465e708545f..bfa11a84e476 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1712,7 +1712,7 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, { int i; - if (!i915_modparams.semaphores) + if (!HAS_LEGACY_SEMAPHORES(dev_priv)) return; GEM_BUG_ON(INTEL_GEN(dev_priv) < 6); @@ -1823,7 +1823,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->emit_breadcrumb = i9xx_emit_breadcrumb; engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; - if (i915_modparams.semaphores) { + if (HAS_LEGACY_SEMAPHORES(dev_priv)) { int num_rings; engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; -- cgit From 0ab42a78712acbdcfefe5aa3205a15393ebbc6d7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 20 Nov 2017 21:19:07 +0000 Subject: drm/i915/selftests: Declare we allocated the guc clients Silence smatch over drivers/gpu/drm/i915/selftests/intel_guc.c:135 igt_guc_init_doorbell_hw() error: we previously assumed 'guc->execbuf_client' could be null (see line 123) drivers/gpu/drm/i915/selftests/intel_guc.c:142 igt_guc_init_doorbell_hw() error: we previously assumed 'guc->preempt_client' could be null (see line 123) by asserting that we did succeed in creating the pair of clients for testing. References: 55bd6bd75717 ("drm/i915/selftests: Add a GuC doorbells selftest") Signed-off-by: Chris Wilson Cc: Michel Thierry Cc: Michal Wajdeczko Cc: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20171120211907.1649-1-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/selftests/intel_guc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c index f1baeda8b4a8..7b23597858bb 100644 --- a/drivers/gpu/drm/i915/selftests/intel_guc.c +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c @@ -131,6 +131,8 @@ static int igt_guc_init_doorbell_hw(void *args) pr_err("Failed to create clients\n"); goto unlock; } + GEM_BUG_ON(!guc->execbuf_client); + GEM_BUG_ON(!guc->preempt_client); err = validate_client(guc->execbuf_client, GUC_CLIENT_PRIORITY_KMD_NORMAL, false); -- cgit From 36fe778a489e0461126fc657ff333522c24d5391 Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Fri, 17 Nov 2017 10:01:46 +0200 Subject: drm/i915: Don't use GEN6_RC_VIDEO_FREQ on gen10+ GEN6_RC_VIDEO_FREQ is deprecated for >= gen10; don't try to program it. v2: Use IS_GEN9() instead of INTEL_GEN() and remove comment (Rodrigo) Signed-off-by: David Weinehall Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20171117080146.20150-1-david.weinehall@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4d2cd432f739..ce5cd75b8130 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6602,9 +6602,10 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv) { intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - /* Program defaults and thresholds for RPS*/ - I915_WRITE(GEN6_RC_VIDEO_FREQ, - GEN9_FREQUENCY(dev_priv->gt_pm.rps.rp1_freq)); + /* Program defaults and thresholds for RPS */ + if (IS_GEN9(dev_priv)) + I915_WRITE(GEN6_RC_VIDEO_FREQ, + GEN9_FREQUENCY(dev_priv->gt_pm.rps.rp1_freq)); /* 1 second timeout*/ I915_WRITE(GEN6_RP_DOWN_TIMEOUT, -- cgit From 51f5a096398433a881e845d3685a2c1dac756019 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:08 +0200 Subject: drm/i915: Add .get_hw_state() method for planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a .get_hw_state() method for planes, returning true or false depending on whether the plane is enabled. Use it to rewrite the plane enabled/disabled asserts in platform agnostic fashion. We do lose the pre-gen4 plane<->pipe mapping checks, but since we're supposed sanitize that anyway it doesn't really matter. v2: Reoder patches to not depend on enum old_plane_id Just call assert_plane_disabled() from assert_planes_disabled() v3: Deal with disabled power wells in .get_hw_state() v4: Rebase due skl primary plane code removal Cc: Thierry Reding Cc: Alex Villacís Lasso Reviewed-by: Daniel Vetter #v2 Tested-by: Thierry Reding #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-2-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 188 +++++++++++++++++------------------ drivers/gpu/drm/i915/intel_drv.h | 2 + drivers/gpu/drm/i915/intel_sprite.c | 83 ++++++++++++++++ 3 files changed, 175 insertions(+), 98 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3b3dec1e6640..7bf8290f0343 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1190,23 +1190,6 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) pipe_name(pipe)); } -static void assert_cursor(struct drm_i915_private *dev_priv, - enum pipe pipe, bool state) -{ - bool cur_state; - - if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) - cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; - else - cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; - - I915_STATE_WARN(cur_state != state, - "cursor on pipe %c assertion failure (expected %s, current %s)\n", - pipe_name(pipe), onoff(state), onoff(cur_state)); -} -#define assert_cursor_enabled(d, p) assert_cursor(d, p, true) -#define assert_cursor_disabled(d, p) assert_cursor(d, p, false) - void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { @@ -1234,77 +1217,25 @@ void assert_pipe(struct drm_i915_private *dev_priv, pipe_name(pipe), onoff(state), onoff(cur_state)); } -static void assert_plane(struct drm_i915_private *dev_priv, - enum plane plane, bool state) +static void assert_plane(struct intel_plane *plane, bool state) { - u32 val; - bool cur_state; + bool cur_state = plane->get_hw_state(plane); - val = I915_READ(DSPCNTR(plane)); - cur_state = !!(val & DISPLAY_PLANE_ENABLE); I915_STATE_WARN(cur_state != state, - "plane %c assertion failure (expected %s, current %s)\n", - plane_name(plane), onoff(state), onoff(cur_state)); + "%s assertion failure (expected %s, current %s)\n", + plane->base.name, onoff(state), onoff(cur_state)); } -#define assert_plane_enabled(d, p) assert_plane(d, p, true) -#define assert_plane_disabled(d, p) assert_plane(d, p, false) +#define assert_plane_enabled(p) assert_plane(p, true) +#define assert_plane_disabled(p) assert_plane(p, false) -static void assert_planes_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe) +static void assert_planes_disabled(struct intel_crtc *crtc) { - int i; - - /* Primary planes are fixed to pipes on gen4+ */ - if (INTEL_GEN(dev_priv) >= 4) { - u32 val = I915_READ(DSPCNTR(pipe)); - I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE, - "plane %c assertion failure, should be disabled but not\n", - plane_name(pipe)); - return; - } - - /* Need to check both planes against the pipe */ - for_each_pipe(dev_priv, i) { - u32 val = I915_READ(DSPCNTR(i)); - enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >> - DISPPLANE_SEL_PIPE_SHIFT; - I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, - "plane %c assertion failure, should be off on pipe %c but is still active\n", - plane_name(i), pipe_name(pipe)); - } -} - -static void assert_sprites_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - int sprite; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_plane *plane; - if (INTEL_GEN(dev_priv) >= 9) { - for_each_sprite(dev_priv, pipe, sprite) { - u32 val = I915_READ(PLANE_CTL(pipe, sprite)); - I915_STATE_WARN(val & PLANE_CTL_ENABLE, - "plane %d assertion failure, should be off on pipe %c but is still active\n", - sprite, pipe_name(pipe)); - } - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - for_each_sprite(dev_priv, pipe, sprite) { - u32 val = I915_READ(SPCNTR(pipe, PLANE_SPRITE0 + sprite)); - I915_STATE_WARN(val & SP_ENABLE, - "sprite %c assertion failure, should be off on pipe %c but is still active\n", - sprite_name(pipe, sprite), pipe_name(pipe)); - } - } else if (INTEL_GEN(dev_priv) >= 7) { - u32 val = I915_READ(SPRCTL(pipe)); - I915_STATE_WARN(val & SPRITE_ENABLE, - "sprite %c assertion failure, should be off on pipe %c but is still active\n", - plane_name(pipe), pipe_name(pipe)); - } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) { - u32 val = I915_READ(DVSCNTR(pipe)); - I915_STATE_WARN(val & DVS_ENABLE, - "sprite %c assertion failure, should be off on pipe %c but is still active\n", - plane_name(pipe), pipe_name(pipe)); - } + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) + assert_plane_disabled(plane); } static void assert_vblank_disabled(struct drm_crtc *crtc) @@ -1896,9 +1827,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc) DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe)); - assert_planes_disabled(dev_priv, pipe); - assert_cursor_disabled(dev_priv, pipe); - assert_sprites_disabled(dev_priv, pipe); + assert_planes_disabled(crtc); /* * A pipe without a PLL won't actually be able to drive bits from @@ -1968,9 +1897,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc) * Make sure planes won't keep trying to pump pixels to us, * or we might hang the display. */ - assert_planes_disabled(dev_priv, pipe); - assert_cursor_disabled(dev_priv, pipe); - assert_sprites_disabled(dev_priv, pipe); + assert_planes_disabled(crtc); reg = PIPECONF(cpu_transcoder); val = I915_READ(reg); @@ -3364,6 +3291,31 @@ static void i9xx_disable_primary_plane(struct intel_plane *primary, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static bool i9xx_plane_get_hw_state(struct intel_plane *primary) +{ + + struct drm_i915_private *dev_priv = to_i915(primary->base.dev); + enum intel_display_power_domain power_domain; + enum plane plane = primary->plane; + enum pipe pipe = primary->pipe; + bool ret; + + /* + * Not 100% correct for planes that can move between pipes, + * but that's only the case for gen2-4 which don't have any + * display power wells. + */ + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static u32 intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane) { @@ -4879,7 +4831,8 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state) * a vblank wait. */ - assert_plane_enabled(dev_priv, crtc->plane); + assert_plane_enabled(to_intel_plane(crtc->base.primary)); + if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->pcu_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, @@ -4913,7 +4866,8 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state) if (!crtc_state->ips_enabled) return; - assert_plane_enabled(dev_priv, crtc->plane); + assert_plane_enabled(to_intel_plane(crtc->base.primary)); + if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->pcu_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); @@ -9499,6 +9453,23 @@ static void i845_disable_cursor(struct intel_plane *plane, i845_update_cursor(plane, NULL, NULL); } +static bool i845_cursor_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + bool ret; + + power_domain = POWER_DOMAIN_PIPE(PIPE_A); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -9692,6 +9663,28 @@ static void i9xx_disable_cursor(struct intel_plane *plane, i9xx_update_cursor(plane, NULL, NULL); } +static bool i9xx_cursor_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + enum pipe pipe = plane->pipe; + bool ret; + + /* + * Not 100% correct for planes that can move between pipes, + * but that's only the case for gen2-3 which don't have any + * display power wells. + */ + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} /* VESA 640x480x72Hz mode to set on the pipe */ static const struct drm_display_mode load_detect_mode = { @@ -13279,6 +13272,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = skl_update_plane; primary->disable_plane = skl_disable_plane; + primary->get_hw_state = skl_plane_get_hw_state; } else if (INTEL_GEN(dev_priv) >= 9) { intel_primary_formats = skl_primary_formats; num_formats = ARRAY_SIZE(skl_primary_formats); @@ -13289,6 +13283,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = skl_update_plane; primary->disable_plane = skl_disable_plane; + primary->get_hw_state = skl_plane_get_hw_state; } else if (INTEL_GEN(dev_priv) >= 4) { intel_primary_formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); @@ -13296,6 +13291,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_primary_plane; primary->disable_plane = i9xx_disable_primary_plane; + primary->get_hw_state = i9xx_plane_get_hw_state; } else { intel_primary_formats = i8xx_primary_formats; num_formats = ARRAY_SIZE(i8xx_primary_formats); @@ -13303,6 +13299,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_primary_plane; primary->disable_plane = i9xx_disable_primary_plane; + primary->get_hw_state = i9xx_plane_get_hw_state; } if (INTEL_GEN(dev_priv) >= 9) @@ -13392,10 +13389,12 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) { cursor->update_plane = i845_update_cursor; cursor->disable_plane = i845_disable_cursor; + cursor->get_hw_state = i845_cursor_get_hw_state; cursor->check_plane = i845_check_cursor; } else { cursor->update_plane = i9xx_update_cursor; cursor->disable_plane = i9xx_disable_cursor; + cursor->get_hw_state = i9xx_cursor_get_hw_state; cursor->check_plane = i9xx_check_cursor; } @@ -14761,8 +14760,8 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n", pipe_name(pipe)); - assert_plane_disabled(dev_priv, PLANE_A); - assert_plane_disabled(dev_priv, PLANE_B); + assert_planes_disabled(intel_get_crtc_for_pipe(dev_priv, PIPE_A)); + assert_planes_disabled(intel_get_crtc_for_pipe(dev_priv, PIPE_B)); I915_WRITE(PIPECONF(pipe), 0); POSTING_READ(PIPECONF(pipe)); @@ -14976,20 +14975,13 @@ void i915_redisable_vga(struct drm_i915_private *dev_priv) intel_display_power_put(dev_priv, POWER_DOMAIN_VGA); } -static bool primary_get_hw_state(struct intel_plane *plane) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - - return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE; -} - /* FIXME read out full plane state for all planes */ static void readout_plane_state(struct intel_crtc *crtc) { struct intel_plane *primary = to_intel_plane(crtc->base.primary); bool visible; - visible = crtc->active && primary_get_hw_state(primary); + visible = crtc->active && primary->get_hw_state(primary); intel_set_plane_visible(to_intel_crtc_state(crtc->base.state), to_intel_plane_state(primary->base.state), diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 69aab324aaa1..99840f3940c7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -866,6 +866,7 @@ struct intel_plane { const struct intel_plane_state *plane_state); void (*disable_plane)(struct intel_plane *plane, struct intel_crtc *crtc); + bool (*get_hw_state)(struct intel_plane *plane); int (*check_plane)(struct intel_plane *plane, struct intel_crtc_state *crtc_state, struct intel_plane_state *state); @@ -1934,6 +1935,7 @@ void skl_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc); +bool skl_plane_get_hw_state(struct intel_plane *plane); /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ce615704982a..5baa0023964e 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -325,6 +325,26 @@ skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +bool +skl_plane_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + bool ret; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(PLANE_CTL(pipe, plane_id)) & PLANE_CTL_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static void chv_update_csc(struct intel_plane *plane, uint32_t format) { @@ -502,6 +522,26 @@ vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static bool +vlv_plane_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + bool ret; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(SPCNTR(pipe, plane_id)) & SP_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -642,6 +682,25 @@ ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static bool +ivb_plane_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + enum pipe pipe = plane->pipe; + bool ret; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(SPRCTL(pipe)) & SPRITE_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -773,6 +832,25 @@ g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static bool +g4x_plane_get_hw_state(struct intel_plane *plane) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum intel_display_power_domain power_domain; + enum pipe pipe = plane->pipe; + bool ret; + + power_domain = POWER_DOMAIN_PIPE(pipe); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + + ret = I915_READ(DVSCNTR(pipe)) & DVS_ENABLE; + + intel_display_power_put(dev_priv, power_domain); + + return ret; +} + static int intel_check_sprite_plane(struct intel_plane *plane, struct intel_crtc_state *crtc_state, @@ -1231,6 +1309,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; + intel_plane->get_hw_state = skl_plane_get_hw_state; plane_formats = skl_plane_formats; num_plane_formats = ARRAY_SIZE(skl_plane_formats); @@ -1241,6 +1320,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; + intel_plane->get_hw_state = skl_plane_get_hw_state; plane_formats = skl_plane_formats; num_plane_formats = ARRAY_SIZE(skl_plane_formats); @@ -1251,6 +1331,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; + intel_plane->get_hw_state = vlv_plane_get_hw_state; plane_formats = vlv_plane_formats; num_plane_formats = ARRAY_SIZE(vlv_plane_formats); @@ -1266,6 +1347,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; + intel_plane->get_hw_state = ivb_plane_get_hw_state; plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); @@ -1276,6 +1358,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = g4x_update_plane; intel_plane->disable_plane = g4x_disable_plane; + intel_plane->get_hw_state = g4x_plane_get_hw_state; modifiers = i9xx_plane_format_modifiers; if (IS_GEN6(dev_priv)) { -- cgit From b1e01595a66dc206a2c75401ec4c285740537f3f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:09 +0200 Subject: drm/i915: Redo plane sanitation during readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the plane disabling during state readout by pulling the code into a new helper intel_plane_disable_noatomic(). We'll also read out the state of all planes, so that we know which planes really need to be diabled. Additonally we change the plane<->pipe mapping sanitation to work by simply disabling the offending planes instead of entire pipes. And we do it before we otherwise sanitize the crtcs, which means we don't have to worry about misassigned planes during crtc sanitation anymore. v2: Reoder patches to not depend on enum old_plane_id v3: s/for_each_pipe/for_each_intel_crtc/ Cc: Thierry Reding Cc: Alex Villacís Lasso Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103223 Reviewed-by: Daniel Vetter Tested-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-3-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 114 ++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7bf8290f0343..91f74c5373b3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2726,6 +2726,23 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state, crtc_state->active_planes); } +static void intel_plane_disable_noatomic(struct intel_crtc *crtc, + struct intel_plane *plane) +{ + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + + intel_set_plane_visible(crtc_state, plane_state, false); + + if (plane->id == PLANE_PRIMARY) + intel_pre_disable_primary_noatomic(&crtc->base); + + trace_intel_disable_plane(&plane->base, crtc); + plane->disable_plane(plane, crtc); +} + static void intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, struct intel_initial_plane_config *plane_config) @@ -2783,12 +2800,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, * simplest solution is to just disable the primary plane now and * pretend the BIOS never had it enabled. */ - intel_set_plane_visible(to_intel_crtc_state(crtc_state), - to_intel_plane_state(plane_state), - false); - intel_pre_disable_primary_noatomic(&intel_crtc->base); - trace_intel_disable_plane(primary, intel_crtc); - intel_plane->disable_plane(intel_plane, intel_crtc); + intel_plane_disable_noatomic(intel_crtc, intel_plane); return; @@ -5869,6 +5881,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_private *dev_priv = to_i915(crtc->dev); enum intel_display_power_domain domain; + struct intel_plane *plane; u64 domains; struct drm_atomic_state *state; struct intel_crtc_state *crtc_state; @@ -5877,11 +5890,12 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, if (!intel_crtc->active) return; - if (crtc->primary->state->visible) { - intel_pre_disable_primary_noatomic(crtc); + for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) { + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); - intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary)); - crtc->primary->state->visible = false; + if (plane_state->base.visible) + intel_plane_disable_noatomic(intel_crtc, plane); } state = drm_atomic_state_alloc(crtc->dev); @@ -14773,22 +14787,36 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) POSTING_READ(DPLL(pipe)); } -static bool -intel_check_plane_mapping(struct intel_crtc *crtc) +static bool intel_plane_mapping_ok(struct intel_crtc *crtc, + struct intel_plane *primary) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 val; + enum plane plane = primary->plane; + u32 val = I915_READ(DSPCNTR(plane)); - if (INTEL_INFO(dev_priv)->num_pipes == 1) - return true; + return (val & DISPLAY_PLANE_ENABLE) == 0 || + (val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe); +} - val = I915_READ(DSPCNTR(!crtc->plane)); +static void +intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv) +{ + struct intel_crtc *crtc; - if ((val & DISPLAY_PLANE_ENABLE) && - (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) - return false; + if (INTEL_GEN(dev_priv) >= 4) + return; - return true; + for_each_intel_crtc(&dev_priv->drm, crtc) { + struct intel_plane *plane = + to_intel_plane(crtc->base.primary); + + if (intel_plane_mapping_ok(crtc, plane)) + continue; + + DRM_DEBUG_KMS("%s attached to the wrong pipe, disabling plane\n", + plane->base.name); + intel_plane_disable_noatomic(crtc, plane); + } } static bool intel_crtc_has_encoders(struct intel_crtc *crtc) @@ -14844,33 +14872,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, /* Disable everything but the primary plane */ for_each_intel_plane_on_crtc(dev, crtc, plane) { - if (plane->base.type == DRM_PLANE_TYPE_PRIMARY) - continue; + const struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); - trace_intel_disable_plane(&plane->base, crtc); - plane->disable_plane(plane, crtc); + if (plane_state->base.visible && + plane->base.type != DRM_PLANE_TYPE_PRIMARY) + intel_plane_disable_noatomic(crtc, plane); } } - /* We need to sanitize the plane -> pipe mapping first because this will - * disable the crtc (and hence change the state) if it is wrong. Note - * that gen4+ has a fixed plane -> pipe mapping. */ - if (INTEL_GEN(dev_priv) < 4 && !intel_check_plane_mapping(crtc)) { - bool plane; - - DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n", - crtc->base.base.id, crtc->base.name); - - /* Pipe has the wrong plane attached and the plane is active. - * Temporarily change the plane mapping and disable everything - * ... */ - plane = crtc->plane; - crtc->base.primary->state->visible = true; - crtc->plane = !plane; - intel_crtc_disable_noatomic(&crtc->base, ctx); - crtc->plane = plane; - } - /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ if (crtc->active && !intel_crtc_has_encoders(crtc)) @@ -14978,14 +14988,18 @@ void i915_redisable_vga(struct drm_i915_private *dev_priv) /* FIXME read out full plane state for all planes */ static void readout_plane_state(struct intel_crtc *crtc) { - struct intel_plane *primary = to_intel_plane(crtc->base.primary); - bool visible; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + struct intel_plane *plane; - visible = crtc->active && primary->get_hw_state(primary); + for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) { + struct intel_plane_state *plane_state = + to_intel_plane_state(plane->base.state); + bool visible = plane->get_hw_state(plane); - intel_set_plane_visible(to_intel_crtc_state(crtc->base.state), - to_intel_plane_state(primary->base.state), - visible); + intel_set_plane_visible(crtc_state, plane_state, visible); + } } static void intel_modeset_readout_hw_state(struct drm_device *dev) @@ -15193,6 +15207,8 @@ intel_modeset_setup_hw_state(struct drm_device *dev, /* HW state is read out, now we need to sanitize this mess. */ get_encoder_power_domains(dev_priv); + intel_sanitize_plane_mapping(dev_priv); + for_each_intel_encoder(dev, encoder) { intel_sanitize_encoder(encoder); } -- cgit From ed15030d7ab0cfe395a494f03e5ee2e66ccb8be9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:10 +0200 Subject: drm/i915: s/enum plane/enum i9xx_plane_id/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename enum plane to enum i9xx_plane_id to make it clear that it only applies to pre-SKL platforms. enum i9xx_plane_id is a global identifier, whereas enum plane_id is per-pipe. We need the old global identifier to index the primary plane (and the pre-g4x sprite C if we ever expose it) registers on pre-SKL platforms. v2: Reorder patches v3: s/old_plane_id/i9xx_plane_id/ (Daniel) Pimp the commit message a bit Note that i9xx_plane_id doesn't apply to SKL+ v4: Rebase due to power domain handling in plane readout v5: Rebase due to crtc->dspaddr_offset removal v6: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-4-ville.syrjala@linux.intel.com Reviewed-by: James Ausmus Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 6 +-- drivers/gpu/drm/i915/intel_display.c | 98 ++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_drv.h | 6 +-- drivers/gpu/drm/i915/intel_fbc.c | 12 ++--- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 5 files changed, 62 insertions(+), 62 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a0654e10a55..d63a731ef60b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -304,9 +304,9 @@ static inline bool transcoder_is_dsi(enum transcoder transcoder) /* * Global legacy plane identifier. Valid only for primary/sprite - * planes on pre-g4x, and only for primary planes on g4x+. + * planes on pre-g4x, and only for primary planes on g4x-bdw. */ -enum plane { +enum i9xx_plane_id { PLANE_A, PLANE_B, PLANE_C, @@ -1144,7 +1144,7 @@ struct intel_fbc { struct { enum pipe pipe; - enum plane plane; + enum i9xx_plane_id i9xx_plane; unsigned int fence_y_offset; } crtc; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91f74c5373b3..16ac86816f28 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3220,16 +3220,16 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) return 0; } -static void i9xx_update_primary_plane(struct intel_plane *primary, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) +static void i9xx_update_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(primary->base.dev); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->base.fb; - enum plane plane = primary->plane; + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; u32 linear_offset; u32 dspcntr = plane_state->ctl; - i915_reg_t reg = DSPCNTR(plane); + i915_reg_t reg = DSPCNTR(i9xx_plane); int x = plane_state->main.x; int y = plane_state->main.y; unsigned long irqflags; @@ -3248,34 +3248,34 @@ static void i9xx_update_primary_plane(struct intel_plane *primary, /* pipesrc and dspsize control the size that is scaled from, * which should always be the user's requested size. */ - I915_WRITE_FW(DSPSIZE(plane), + I915_WRITE_FW(DSPSIZE(i9xx_plane), ((crtc_state->pipe_src_h - 1) << 16) | (crtc_state->pipe_src_w - 1)); - I915_WRITE_FW(DSPPOS(plane), 0); - } else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) { - I915_WRITE_FW(PRIMSIZE(plane), + I915_WRITE_FW(DSPPOS(i9xx_plane), 0); + } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { + I915_WRITE_FW(PRIMSIZE(i9xx_plane), ((crtc_state->pipe_src_h - 1) << 16) | (crtc_state->pipe_src_w - 1)); - I915_WRITE_FW(PRIMPOS(plane), 0); - I915_WRITE_FW(PRIMCNSTALPHA(plane), 0); + I915_WRITE_FW(PRIMPOS(i9xx_plane), 0); + I915_WRITE_FW(PRIMCNSTALPHA(i9xx_plane), 0); } I915_WRITE_FW(reg, dspcntr); - I915_WRITE_FW(DSPSTRIDE(plane), fb->pitches[0]); + I915_WRITE_FW(DSPSTRIDE(i9xx_plane), fb->pitches[0]); if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - I915_WRITE_FW(DSPSURF(plane), + I915_WRITE_FW(DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x); + I915_WRITE_FW(DSPOFFSET(i9xx_plane), (y << 16) | x); } else if (INTEL_GEN(dev_priv) >= 4) { - I915_WRITE_FW(DSPSURF(plane), + I915_WRITE_FW(DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - I915_WRITE_FW(DSPTILEOFF(plane), (y << 16) | x); - I915_WRITE_FW(DSPLINOFF(plane), linear_offset); + I915_WRITE_FW(DSPTILEOFF(i9xx_plane), (y << 16) | x); + I915_WRITE_FW(DSPLINOFF(i9xx_plane), linear_offset); } else { - I915_WRITE_FW(DSPADDR(plane), + I915_WRITE_FW(DSPADDR(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); } @@ -3284,32 +3284,31 @@ static void i9xx_update_primary_plane(struct intel_plane *primary, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void i9xx_disable_primary_plane(struct intel_plane *primary, - struct intel_crtc *crtc) +static void i9xx_disable_plane(struct intel_plane *plane, + struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(primary->base.dev); - enum plane plane = primary->plane; + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; unsigned long irqflags; spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - I915_WRITE_FW(DSPCNTR(plane), 0); - if (INTEL_INFO(dev_priv)->gen >= 4) - I915_WRITE_FW(DSPSURF(plane), 0); + I915_WRITE_FW(DSPCNTR(i9xx_plane), 0); + if (INTEL_GEN(dev_priv) >= 4) + I915_WRITE_FW(DSPSURF(i9xx_plane), 0); else - I915_WRITE_FW(DSPADDR(plane), 0); - POSTING_READ_FW(DSPCNTR(plane)); + I915_WRITE_FW(DSPADDR(i9xx_plane), 0); + POSTING_READ_FW(DSPCNTR(i9xx_plane)); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static bool i9xx_plane_get_hw_state(struct intel_plane *primary) +static bool i9xx_plane_get_hw_state(struct intel_plane *plane) { - - struct drm_i915_private *dev_priv = to_i915(primary->base.dev); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum intel_display_power_domain power_domain; - enum plane plane = primary->plane; - enum pipe pipe = primary->pipe; + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + enum pipe pipe = plane->pipe; bool ret; /* @@ -3321,7 +3320,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *primary) if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - ret = I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE; + ret = I915_READ(DSPCNTR(i9xx_plane)) & DISPLAY_PLANE_ENABLE; intel_display_power_put(dev_priv, power_domain); @@ -7406,7 +7405,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); u32 val, base, offset; - int pipe = crtc->pipe, plane = crtc->plane; + int pipe = crtc->pipe, plane = crtc->i9xx_plane; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; @@ -13272,9 +13271,9 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) * port is hooked to pipe B. Hence we want plane A feeding pipe B. */ if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4) - primary->plane = (enum plane) !pipe; + primary->i9xx_plane = (enum i9xx_plane_id) !pipe; else - primary->plane = (enum plane) pipe; + primary->i9xx_plane = (enum i9xx_plane_id) pipe; primary->id = PLANE_PRIMARY; primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe); primary->check_plane = intel_check_primary_plane; @@ -13303,16 +13302,16 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(i965_primary_formats); modifiers = i9xx_format_modifiers; - primary->update_plane = i9xx_update_primary_plane; - primary->disable_plane = i9xx_disable_primary_plane; + primary->update_plane = i9xx_update_plane; + primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; } else { intel_primary_formats = i8xx_primary_formats; num_formats = ARRAY_SIZE(i8xx_primary_formats); modifiers = i9xx_format_modifiers; - primary->update_plane = i9xx_update_primary_plane; - primary->disable_plane = i9xx_disable_primary_plane; + primary->update_plane = i9xx_update_plane; + primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; } @@ -13336,7 +13335,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) intel_primary_formats, num_formats, modifiers, DRM_PLANE_TYPE_PRIMARY, - "plane %c", plane_name(primary->plane)); + "plane %c", + plane_name(primary->i9xx_plane)); if (ret) goto fail; @@ -13396,7 +13396,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, cursor->can_scale = false; cursor->max_downscale = 1; cursor->pipe = pipe; - cursor->plane = pipe; + cursor->i9xx_plane = (enum i9xx_plane_id) pipe; cursor->id = PLANE_CURSOR; cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe); @@ -13524,14 +13524,14 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) goto fail; intel_crtc->pipe = pipe; - intel_crtc->plane = primary->plane; + intel_crtc->i9xx_plane = primary->i9xx_plane; /* initialize shared scalers */ intel_crtc_init_scalers(intel_crtc, crtc_state); BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || - dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL); - dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc; + dev_priv->plane_to_crtc_mapping[intel_crtc->i9xx_plane] != NULL); + dev_priv->plane_to_crtc_mapping[intel_crtc->i9xx_plane] = intel_crtc; dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); @@ -14788,11 +14788,11 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) } static bool intel_plane_mapping_ok(struct intel_crtc *crtc, - struct intel_plane *primary) + struct intel_plane *plane) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum plane plane = primary->plane; - u32 val = I915_READ(DSPCNTR(plane)); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + u32 val = I915_READ(DSPCNTR(i9xx_plane)); return (val & DISPLAY_PLANE_ENABLE) == 0 || (val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 99840f3940c7..d1fe7be94b62 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -799,7 +799,7 @@ struct intel_crtc_state { struct intel_crtc { struct drm_crtc base; enum pipe pipe; - enum plane plane; + enum i9xx_plane_id i9xx_plane; /* * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has @@ -844,7 +844,7 @@ struct intel_crtc { struct intel_plane { struct drm_plane base; - u8 plane; + enum i9xx_plane_id i9xx_plane; enum plane_id id; enum pipe pipe; bool can_scale; @@ -1130,7 +1130,7 @@ intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) } static inline struct intel_crtc * -intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum plane plane) +intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum i9xx_plane_id plane) { return dev_priv->plane_to_crtc_mapping[plane]; } diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1a0f5e0c8d10..3133131306a9 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -151,7 +151,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv) /* Set it up... */ fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; - fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.plane); + fbc_ctl2 |= FBC_CTL_PLANE(params->crtc.i9xx_plane); I915_WRITE(FBC_CONTROL2, fbc_ctl2); I915_WRITE(FBC_FENCE_OFF, params->crtc.fence_y_offset); } @@ -177,7 +177,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) struct intel_fbc_reg_params *params = &dev_priv->fbc.params; u32 dpfc_ctl; - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane) | DPFC_SR_EN; + dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane) | DPFC_SR_EN; if (params->fb.format->cpp[0] == 2) dpfc_ctl |= DPFC_CTL_LIMIT_2X; else @@ -224,7 +224,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; - dpfc_ctl = DPFC_CTL_PLANE(params->crtc.plane); + dpfc_ctl = DPFC_CTL_PLANE(params->crtc.i9xx_plane); if (params->fb.format->cpp[0] == 2) threshold++; @@ -306,7 +306,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) dpfc_ctl = 0; if (IS_IVYBRIDGE(dev_priv)) - dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.plane); + dpfc_ctl |= IVB_DPFC_CTL_PLANE(params->crtc.i9xx_plane); if (params->fb.format->cpp[0] == 2) threshold++; @@ -890,7 +890,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->vma = cache->vma; params->crtc.pipe = crtc->pipe; - params->crtc.plane = crtc->plane; + params->crtc.i9xx_plane = crtc->i9xx_plane; params->crtc.fence_y_offset = get_crtc_fence_y_offset(fbc); params->fb.format = cache->fb.format; @@ -1088,7 +1088,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) continue; - if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) + if (fbc_on_plane_a_only(dev_priv) && crtc->i9xx_plane != PLANE_A) continue; intel_crtc_state = to_intel_crtc_state( diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5baa0023964e..dd485f59eb1d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1384,7 +1384,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, } intel_plane->pipe = pipe; - intel_plane->plane = plane; + intel_plane->i9xx_plane = plane; intel_plane->id = PLANE_SPRITE0 + plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); intel_plane->check_plane = intel_check_sprite_plane; -- cgit From bdaf8439ba8176908b1b33e7db724f3de35ee0f3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:11 +0200 Subject: drm/i915: Use enum i9xx_plane_id for the .get_fifo_size() hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the 0 and 1 with PLANE_A and PLANE_B in the pre-g4x wm code. v2: s/old_plane_id/i9xx_plane_id/ (Daniel) v3: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Daniel Vetter Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-5-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_pm.c | 36 +++++++++++++++++++----------------- 2 files changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d63a731ef60b..a1268d706c5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -698,7 +698,8 @@ struct drm_i915_display_funcs { struct intel_cdclk_state *cdclk_state); void (*set_cdclk)(struct drm_i915_private *dev_priv, const struct intel_cdclk_state *cdclk_state); - int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane); + int (*get_fifo_size)(struct drm_i915_private *dev_priv, + enum i9xx_plane_id i9xx_plane); int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ce5cd75b8130..e445ec174831 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -512,38 +512,41 @@ static void vlv_get_fifo_size(struct intel_crtc_state *crtc_state) fifo_state->plane[PLANE_CURSOR] = 63; } -static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane) +static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, + enum i9xx_plane_id i9xx_plane) { uint32_t dsparb = I915_READ(DSPARB); int size; size = dsparb & 0x7f; - if (plane) + if (i9xx_plane == PLANE_B) size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, - plane ? "B" : "A", size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %c: %d\n", + dsparb, plane_name(i9xx_plane), size); return size; } -static int i830_get_fifo_size(struct drm_i915_private *dev_priv, int plane) +static int i830_get_fifo_size(struct drm_i915_private *dev_priv, + enum i9xx_plane_id i9xx_plane) { uint32_t dsparb = I915_READ(DSPARB); int size; size = dsparb & 0x1ff; - if (plane) + if (i9xx_plane == PLANE_B) size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size; size >>= 1; /* Convert to cachelines */ - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, - plane ? "B" : "A", size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %c: %d\n", + dsparb, plane_name(i9xx_plane), size); return size; } -static int i845_get_fifo_size(struct drm_i915_private *dev_priv, int plane) +static int i845_get_fifo_size(struct drm_i915_private *dev_priv, + enum i9xx_plane_id i9xx_plane) { uint32_t dsparb = I915_READ(DSPARB); int size; @@ -551,9 +554,8 @@ static int i845_get_fifo_size(struct drm_i915_private *dev_priv, int plane) size = dsparb & 0x7f; size >>= 2; /* Convert to cachelines */ - DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, - plane ? "B" : "A", - size); + DRM_DEBUG_KMS("FIFO size - (0x%08x) %c: %d\n", + dsparb, plane_name(i9xx_plane), size); return size; } @@ -2277,8 +2279,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) else wm_info = &i830_a_wm_info; - fifo_size = dev_priv->display.get_fifo_size(dev_priv, 0); - crtc = intel_get_crtc_for_plane(dev_priv, 0); + fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_A); + crtc = intel_get_crtc_for_plane(dev_priv, PLANE_A); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -2304,8 +2306,8 @@ static void i9xx_update_wm(struct intel_crtc *unused_crtc) if (IS_GEN2(dev_priv)) wm_info = &i830_bc_wm_info; - fifo_size = dev_priv->display.get_fifo_size(dev_priv, 1); - crtc = intel_get_crtc_for_plane(dev_priv, 1); + fifo_size = dev_priv->display.get_fifo_size(dev_priv, PLANE_B); + crtc = intel_get_crtc_for_plane(dev_priv, PLANE_B); if (intel_crtc_active(crtc)) { const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -2417,7 +2419,7 @@ static void i845_update_wm(struct intel_crtc *unused_crtc) adjusted_mode = &crtc->config->base.adjusted_mode; planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i845_wm_info, - dev_priv->display.get_fifo_size(dev_priv, 0), + dev_priv->display.get_fifo_size(dev_priv, PLANE_A), 4, pessimal_latency_ns); fwater_lo = I915_READ(FW_BLC) & ~0xfff; fwater_lo |= (3<<8) | planea_wm; -- cgit From 282e83ef6289542914697eae633444c7089d4479 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:12 +0200 Subject: drm/i915: Cleanup enum pipe/enum plane_id/enum i9xx_plane_id in initial fb readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use enum pipe, enum plane_id, and enum i9xx_plane_id consistently in the initial framebuffe readout. v2: Use old_plane_id in the ilk code v3: s/old_plane_id/i9xx_plane_id/ (Daniel) v4: Rebase due to GLK/CNL PLANE_COLOR_CTL alpha stuff v5: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Daniel Vetter Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-6-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 60 ++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 16ac86816f28..0c407cb0e6aa 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7404,14 +7404,16 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_plane *plane = to_intel_plane(crtc->base.primary); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + enum pipe pipe = crtc->pipe; u32 val, base, offset; - int pipe = crtc->pipe, plane = crtc->i9xx_plane; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - val = I915_READ(DSPCNTR(plane)); + val = I915_READ(DSPCNTR(i9xx_plane)); if (!(val & DISPLAY_PLANE_ENABLE)) return; @@ -7438,12 +7440,12 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, if (INTEL_GEN(dev_priv) >= 4) { if (plane_config->tiling) - offset = I915_READ(DSPTILEOFF(plane)); + offset = I915_READ(DSPTILEOFF(i9xx_plane)); else - offset = I915_READ(DSPLINOFF(plane)); - base = I915_READ(DSPSURF(plane)) & 0xfffff000; + offset = I915_READ(DSPLINOFF(i9xx_plane)); + base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000; } else { - base = I915_READ(DSPADDR(plane)); + base = I915_READ(DSPADDR(i9xx_plane)); } plane_config->base = base; @@ -7451,15 +7453,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->width = ((val >> 16) & 0xfff) + 1; fb->height = ((val >> 0) & 0xfff) + 1; - val = I915_READ(DSPSTRIDE(pipe)); + val = I915_READ(DSPSTRIDE(i9xx_plane)); fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(fb, 0, fb->height); plane_config->size = fb->pitches[0] * aligned_height; - DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe_name(pipe), plane, fb->width, fb->height, + DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + crtc->base.name, plane->base.name, fb->width, fb->height, fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); @@ -8428,8 +8430,10 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_plane *plane = to_intel_plane(crtc->base.primary); + enum plane_id plane_id = plane->id; + enum pipe pipe = crtc->pipe; u32 val, base, offset, stride_mult, tiling, alpha; - int pipe = crtc->pipe; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; @@ -8445,14 +8449,14 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, fb->dev = dev; - val = I915_READ(PLANE_CTL(pipe, 0)); + val = I915_READ(PLANE_CTL(pipe, plane_id)); if (!(val & PLANE_CTL_ENABLE)) goto error; pixel_format = val & PLANE_CTL_FORMAT_MASK; if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { - alpha = I915_READ(PLANE_COLOR_CTL(pipe, 0)); + alpha = I915_READ(PLANE_COLOR_CTL(pipe, plane_id)); alpha &= PLANE_COLOR_ALPHA_MASK; } else { alpha = val & PLANE_CTL_ALPHA_MASK; @@ -8488,16 +8492,16 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, goto error; } - base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000; + base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000; plane_config->base = base; - offset = I915_READ(PLANE_OFFSET(pipe, 0)); + offset = I915_READ(PLANE_OFFSET(pipe, plane_id)); - val = I915_READ(PLANE_SIZE(pipe, 0)); + val = I915_READ(PLANE_SIZE(pipe, plane_id)); fb->height = ((val >> 16) & 0xfff) + 1; fb->width = ((val >> 0) & 0x1fff) + 1; - val = I915_READ(PLANE_STRIDE(pipe, 0)); + val = I915_READ(PLANE_STRIDE(pipe, plane_id)); stride_mult = intel_fb_stride_alignment(fb, 0); fb->pitches[0] = (val & 0x3ff) * stride_mult; @@ -8505,8 +8509,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, plane_config->size = fb->pitches[0] * aligned_height; - DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe_name(pipe), fb->width, fb->height, + DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + crtc->base.name, plane->base.name, fb->width, fb->height, fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); @@ -8547,14 +8551,16 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_plane *plane = to_intel_plane(crtc->base.primary); + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + enum pipe pipe = crtc->pipe; u32 val, base, offset; - int pipe = crtc->pipe; int fourcc, pixel_format; unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - val = I915_READ(DSPCNTR(pipe)); + val = I915_READ(DSPCNTR(i9xx_plane)); if (!(val & DISPLAY_PLANE_ENABLE)) return; @@ -8579,14 +8585,14 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, fourcc = i9xx_format_to_fourcc(pixel_format); fb->format = drm_format_info(fourcc); - base = I915_READ(DSPSURF(pipe)) & 0xfffff000; + base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - offset = I915_READ(DSPOFFSET(pipe)); + offset = I915_READ(DSPOFFSET(i9xx_plane)); } else { if (plane_config->tiling) - offset = I915_READ(DSPTILEOFF(pipe)); + offset = I915_READ(DSPTILEOFF(i9xx_plane)); else - offset = I915_READ(DSPLINOFF(pipe)); + offset = I915_READ(DSPLINOFF(i9xx_plane)); } plane_config->base = base; @@ -8594,15 +8600,15 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, fb->width = ((val >> 16) & 0xfff) + 1; fb->height = ((val >> 0) & 0xfff) + 1; - val = I915_READ(DSPSTRIDE(pipe)); + val = I915_READ(DSPSTRIDE(i9xx_plane)); fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(fb, 0, fb->height); plane_config->size = fb->pitches[0] * aligned_height; - DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - pipe_name(pipe), fb->width, fb->height, + DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", + crtc->base.name, plane->base.name, fb->width, fb->height, fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); -- cgit From 81894b2fb9285f21dc2ca5f4c1ab0c9197d48607 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:13 +0200 Subject: drm/i915: Nuke ironlake_get_initial_plane_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only relevant difference between i9xx_get_initial_plane_config() and ironlake_get_initial_plane_config() is the HSW/BDW TILEOFF handling. Add that to i9xx_get_initial_plane_config() and nuke ironlake_get_initial_plane_config(). v2: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-7-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 79 +++--------------------------------- 1 file changed, 6 insertions(+), 73 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c407cb0e6aa..c1d7547c1457 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7438,7 +7438,10 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fourcc = i9xx_format_to_fourcc(pixel_format); fb->format = drm_format_info(fourcc); - if (INTEL_GEN(dev_priv) >= 4) { + if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { + offset = I915_READ(DSPOFFSET(i9xx_plane)); + base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000; + } else if (INTEL_GEN(dev_priv) >= 4) { if (plane_config->tiling) offset = I915_READ(DSPTILEOFF(i9xx_plane)); else @@ -8545,76 +8548,6 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc, } } -static void -ironlake_get_initial_plane_config(struct intel_crtc *crtc, - struct intel_initial_plane_config *plane_config) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_plane *plane = to_intel_plane(crtc->base.primary); - enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - enum pipe pipe = crtc->pipe; - u32 val, base, offset; - int fourcc, pixel_format; - unsigned int aligned_height; - struct drm_framebuffer *fb; - struct intel_framebuffer *intel_fb; - - val = I915_READ(DSPCNTR(i9xx_plane)); - if (!(val & DISPLAY_PLANE_ENABLE)) - return; - - intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); - if (!intel_fb) { - DRM_DEBUG_KMS("failed to alloc fb\n"); - return; - } - - fb = &intel_fb->base; - - fb->dev = dev; - - if (INTEL_GEN(dev_priv) >= 4) { - if (val & DISPPLANE_TILED) { - plane_config->tiling = I915_TILING_X; - fb->modifier = I915_FORMAT_MOD_X_TILED; - } - } - - pixel_format = val & DISPPLANE_PIXFORMAT_MASK; - fourcc = i9xx_format_to_fourcc(pixel_format); - fb->format = drm_format_info(fourcc); - - base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000; - if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - offset = I915_READ(DSPOFFSET(i9xx_plane)); - } else { - if (plane_config->tiling) - offset = I915_READ(DSPTILEOFF(i9xx_plane)); - else - offset = I915_READ(DSPLINOFF(i9xx_plane)); - } - plane_config->base = base; - - val = I915_READ(PIPESRC(pipe)); - fb->width = ((val >> 16) & 0xfff) + 1; - fb->height = ((val >> 0) & 0xfff) + 1; - - val = I915_READ(DSPSTRIDE(i9xx_plane)); - fb->pitches[0] = val & 0xffffffc0; - - aligned_height = intel_fb_align_height(fb, 0, fb->height); - - plane_config->size = fb->pitches[0] * aligned_height; - - DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", - crtc->base.name, plane->base.name, fb->width, fb->height, - fb->format->cpp[0] * 8, base, fb->pitches[0], - plane_config->size); - - plane_config->fb = intel_fb; -} - static bool ironlake_get_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -14217,7 +14150,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) } else if (HAS_DDI(dev_priv)) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = - ironlake_get_initial_plane_config; + i9xx_get_initial_plane_config; dev_priv->display.crtc_compute_clock = haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; @@ -14225,7 +14158,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) } else if (HAS_PCH_SPLIT(dev_priv)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; dev_priv->display.get_initial_plane_config = - ironlake_get_initial_plane_config; + i9xx_get_initial_plane_config; dev_priv->display.crtc_compute_clock = ironlake_crtc_compute_clock; dev_priv->display.crtc_enable = ironlake_crtc_enable; -- cgit From dd57602efbce0d4f39770ec253fe6f95a6f0791f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:14 +0200 Subject: drm/i915: Switch fbc over to for_each_new_intel_plane_in_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop using the old for_each_intel_plane_in_state() type iteration macro and replace it with for_each_new_intel_plane_in_state(). And similarly replace drm_atomic_get_existing_crtc_state() with intel_atomic_get_new_crtc_state(). Switch over to intel_ types as well to make the code less cluttered. v2: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Maarten Lankhorst Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-8-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 7 +++---- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_fbc.c | 23 ++++++++++------------- 4 files changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a1268d706c5e..9a890f6ad2df 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -560,13 +560,13 @@ struct i915_hotplug { for_each_power_well_rev(__dev_priv, __power_well) \ for_each_if ((__power_well)->domains & (__domain_mask)) -#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \ +#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ ((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \ - (plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \ + (new_plane_state) = to_intel_plane_state((__state)->base.planes[__i].new_state), 1); \ (__i)++) \ - for_each_if (plane_state) + for_each_if (plane) #define for_each_new_intel_crtc_in_state(__state, crtc, new_crtc_state, __i) \ for ((__i) = 0; \ @@ -576,7 +576,6 @@ struct i915_hotplug { (__i)++) \ for_each_if (crtc) - #define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c1d7547c1457..b1ead3f95cde 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12080,7 +12080,7 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; - intel_fbc_choose_crtc(dev_priv, state); + intel_fbc_choose_crtc(dev_priv, intel_state); return calc_watermark_data(state); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d1fe7be94b62..3ebe62666108 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1652,7 +1652,7 @@ static inline void intel_fbdev_restore_mode(struct drm_device *dev) /* intel_fbc.c */ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, - struct drm_atomic_state *state); + struct intel_atomic_state *state); bool intel_fbc_is_active(struct drm_i915_private *dev_priv); void intel_fbc_pre_update(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 3133131306a9..474234322b8b 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -1054,11 +1054,11 @@ out: * enable FBC for the chosen CRTC. If it does, it will set dev_priv->fbc.crtc. */ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, - struct drm_atomic_state *state) + struct intel_atomic_state *state) { struct intel_fbc *fbc = &dev_priv->fbc; - struct drm_plane *plane; - struct drm_plane_state *plane_state; + struct intel_plane *plane; + struct intel_plane_state *plane_state; bool crtc_chosen = false; int i; @@ -1066,7 +1066,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, /* Does this atomic commit involve the CRTC currently tied to FBC? */ if (fbc->crtc && - !drm_atomic_get_existing_crtc_state(state, &fbc->crtc->base)) + !intel_atomic_get_new_crtc_state(state, fbc->crtc)) goto out; if (!intel_fbc_can_enable(dev_priv)) @@ -1076,13 +1076,11 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, * plane. We could go for fancier schemes such as checking the plane * size, but this would just affect the few platforms that don't tie FBC * to pipe or plane A. */ - for_each_new_plane_in_state(state, plane, plane_state, i) { - struct intel_plane_state *intel_plane_state = - to_intel_plane_state(plane_state); - struct intel_crtc_state *intel_crtc_state; - struct intel_crtc *crtc = to_intel_crtc(plane_state->crtc); + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + struct intel_crtc_state *crtc_state; + struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc); - if (!intel_plane_state->base.visible) + if (!plane_state->base.visible) continue; if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) @@ -1091,10 +1089,9 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, if (fbc_on_plane_a_only(dev_priv) && crtc->i9xx_plane != PLANE_A) continue; - intel_crtc_state = to_intel_crtc_state( - drm_atomic_get_existing_crtc_state(state, &crtc->base)); + crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - intel_crtc_state->enable_fbc = true; + crtc_state->enable_fbc = true; crtc_chosen = true; break; } -- cgit From b1558c7ea16038f3c3dcc40dd5c1cf7ad6004ada Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:15 +0200 Subject: drm/i915: Nuke crtc->plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eliminate crtc->plane since it's pretty much a layering violation. We can always get the plane via crtc->primary if we actually need it. The only ugly thing left is plane_to_crtc_mapping[], but that's still needed by the pre-g4x watermark code. v2: Removed a misplaced comment change (Daniel) v3: Rebase due to fbc crtc->y usage removal v4: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Daniel Vetter Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-9-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 5 ++--- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_fbc.c | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b1ead3f95cde..62cc2a600205 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13463,14 +13463,13 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) goto fail; intel_crtc->pipe = pipe; - intel_crtc->i9xx_plane = primary->i9xx_plane; /* initialize shared scalers */ intel_crtc_init_scalers(intel_crtc, crtc_state); BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || - dev_priv->plane_to_crtc_mapping[intel_crtc->i9xx_plane] != NULL); - dev_priv->plane_to_crtc_mapping[intel_crtc->i9xx_plane] = intel_crtc; + dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] != NULL); + dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] = intel_crtc; dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3ebe62666108..635a96fcd788 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -799,7 +799,6 @@ struct intel_crtc_state { struct intel_crtc { struct drm_crtc base; enum pipe pipe; - enum i9xx_plane_id i9xx_plane; /* * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 474234322b8b..4aefc658a5cf 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -890,7 +890,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->vma = cache->vma; params->crtc.pipe = crtc->pipe; - params->crtc.i9xx_plane = crtc->i9xx_plane; + params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; params->crtc.fence_y_offset = get_crtc_fence_y_offset(fbc); params->fb.format = cache->fb.format; @@ -1086,7 +1086,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv, if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) continue; - if (fbc_on_plane_a_only(dev_priv) && crtc->i9xx_plane != PLANE_A) + if (fbc_on_plane_a_only(dev_priv) && plane->i9xx_plane != PLANE_A) continue; crtc_state = intel_atomic_get_new_crtc_state(state, crtc); -- cgit From 2924b8cc415a950687a890cb6dea8dbc0e930447 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:16 +0200 Subject: drm/i915: Use plane->get_hw_state() for initial plane fb readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we now have a ->get_hw_state() method for planes, let's use that during the initial plane fb readout. v2: s/plane/i9xx_plane/ etc. (James) Cc: James Ausmus Cc: Daniel Vetter Suggested-by: Daniel Vetter Reviewed-by: James Ausmus Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-10-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62cc2a600205..ed58311e8da0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7413,8 +7413,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - val = I915_READ(DSPCNTR(i9xx_plane)); - if (!(val & DISPLAY_PLANE_ENABLE)) + if (!plane->get_hw_state(plane)) return; intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); @@ -7427,6 +7426,8 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->dev = dev; + val = I915_READ(DSPCNTR(i9xx_plane)); + if (INTEL_GEN(dev_priv) >= 4) { if (val & DISPPLANE_TILED) { plane_config->tiling = I915_TILING_X; @@ -8442,6 +8443,9 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; + if (!plane->get_hw_state(plane)) + return; + intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); if (!intel_fb) { DRM_DEBUG_KMS("failed to alloc fb\n"); @@ -8453,8 +8457,6 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, fb->dev = dev; val = I915_READ(PLANE_CTL(pipe, plane_id)); - if (!(val & PLANE_CTL_ENABLE)) - goto error; pixel_format = val & PLANE_CTL_FORMAT_MASK; -- cgit From cff109f06dfebc379a5a36d49b541212caaec607 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 17 Nov 2017 21:19:17 +0200 Subject: drm/i915: Add rudimentary plane state verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check that the planes are in the state we expect them to be. For now we can only check whether each plane is correctly enabled or disabled. In the future we may want to expand the plane state readout to support a more thorough verification. v2: Verify all planes part of the state as long as at least one crtc is doing a modeset (Daniel) v3: Fix typoes (James) Cc: James Ausmus Cc: Daniel Vetter Suggested-by: Daniel Vetter Reviewed-by: James Ausmus Link: https://patchwork.freedesktop.org/patch/msgid/20171117191917.11506-11-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ed58311e8da0..5ca7b33554ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11600,6 +11600,18 @@ verify_crtc_state(struct drm_crtc *crtc, } } +static void +intel_verify_planes(struct intel_atomic_state *state) +{ + struct intel_plane *plane; + const struct intel_plane_state *plane_state; + int i; + + for_each_new_intel_plane_in_state(state, plane, + plane_state, i) + assert_plane(plane, plane_state->base.visible); +} + static void verify_single_dpll_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, @@ -12393,6 +12405,9 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); } + if (intel_state->modeset) + intel_verify_planes(intel_state); + if (intel_state->modeset && intel_can_enable_sagv(state)) intel_enable_sagv(dev_priv); -- cgit From f9eb63b98c91f4cfaddf54b769f971c77da10917 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 21 Nov 2017 11:06:52 +0000 Subject: drm/i915/selftests: Avoid drm_gem_handle_create under struct_mutex Despite us reloading the module around every selftest, the lockclasses persist and the chains used in selftesting may then dictate how we are allowed to nest locks during runtime testing. As such we have to be just as careful, and in particular it turns out we are not allowed to nest dev->object_name_lock (drm_gem_handle_create) inside dev->struct_mutex. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103830 Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20171121110652.1107-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 09340b3c1156..ec1eff739e01 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -264,6 +264,23 @@ out_unmap: return err; } +static int file_add_object(struct drm_file *file, + struct drm_i915_gem_object *obj) +{ + int err; + + GEM_BUG_ON(obj->base.handle_count); + + /* tie the object to the drm_file for easy reaping */ + err = idr_alloc(&file->object_idr, &obj->base, 1, 0, GFP_KERNEL); + if (err < 0) + return err; + + i915_gem_object_get(obj); + obj->base.handle_count++; + return 0; +} + static struct drm_i915_gem_object * create_test_object(struct i915_gem_context *ctx, struct drm_file *file, @@ -273,7 +290,6 @@ create_test_object(struct i915_gem_context *ctx, struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base; u64 size; - u32 handle; int err; size = min(vm->total / 2, 1024ull * DW_PER_PAGE * PAGE_SIZE); @@ -283,8 +299,7 @@ create_test_object(struct i915_gem_context *ctx, if (IS_ERR(obj)) return obj; - /* tie the handle to the drm_file for easy reaping */ - err = drm_gem_handle_create(file, &obj->base, &handle); + err = file_add_object(file, obj); i915_gem_object_put(obj); if (err) return ERR_PTR(err); -- cgit From c84b27054643db73e56a5e933191bda435b6c46e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:44 +0000 Subject: drm/i915: Extract intel_get_cagf Code to be shared between debugfs and the PMU implementation. v2: Checkpatch cleanup. v3: Also consolidate i915_sysfs.c/gt_act_freq_mhz_show. v4: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 9 ++------- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_sysfs.c | 11 +++-------- drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 41d49a4d25d3..28294470ae31 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1151,13 +1151,8 @@ static int i915_frequency_info(struct seq_file *m, void *unused) rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK; rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK; rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK; - if (INTEL_GEN(dev_priv) >= 9) - cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; - else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) - cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; - else - cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; - cagf = intel_gpu_freq(dev_priv, cagf); + cagf = intel_gpu_freq(dev_priv, + intel_get_cagf(dev_priv, rpstat)); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a890f6ad2df..019117144b3b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -4226,6 +4226,8 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, const i915_reg_t reg); +u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat1); + #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 791759f632e1..450ac7d343ad 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -252,14 +252,9 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); ret = intel_gpu_freq(dev_priv, (freq >> 8) & 0xff); } else { - u32 rpstat = I915_READ(GEN6_RPSTAT1); - if (INTEL_GEN(dev_priv) >= 9) - ret = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; - else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) - ret = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; - else - ret = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; - ret = intel_gpu_freq(dev_priv, ret); + ret = intel_gpu_freq(dev_priv, + intel_get_cagf(dev_priv, + I915_READ(GEN6_RPSTAT1))); } mutex_unlock(&dev_priv->pcu_lock); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e445ec174831..f1dc36c1fd69 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9468,3 +9468,17 @@ u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, intel_runtime_pm_put(dev_priv); return DIV_ROUND_UP_ULL(time_hw * units, div); } + +u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat) +{ + u32 cagf; + + if (INTEL_GEN(dev_priv) >= 9) + cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; + else + cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; + + return cagf; +} -- cgit From b46a33e271ed81bd765c632b972c49d5b44729c7 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:45 +0000 Subject: drm/i915/pmu: Expose a PMU interface for perf queries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Chris Wilson From: Tvrtko Ursulin From: Dmitry Rogozhkin The first goal is to be able to measure GPU (and invidual ring) busyness without having to poll registers from userspace. (Which not only incurs holding the forcewake lock indefinitely, perturbing the system, but also runs the risk of hanging the machine.) As an alternative we can use the perf event counter interface to sample the ring registers periodically and send those results to userspace. Functionality we are exporting to userspace is via the existing perf PMU API and can be exercised via the existing tools. For example: perf stat -a -e i915/rcs0-busy/ -I 1000 Will print the render engine busynnes once per second. All the performance counters can be enumerated (perf list) and have their unit of measure correctly reported in sysfs. v1-v2 (Chris Wilson): v2: Use a common timer for the ring sampling. v3: (Tvrtko Ursulin) * Decouple uAPI from i915 engine ids. * Complete uAPI defines. * Refactor some code to helpers for clarity. * Skip sampling disabled engines. * Expose counters in sysfs. * Pass in fake regs to avoid null ptr deref in perf core. * Convert to class/instance uAPI. * Use shared driver code for rc6 residency, power and frequency. v4: (Dmitry Rogozhkin) * Register PMU with .task_ctx_nr=perf_invalid_context * Expose cpumask for the PMU with the single CPU in the mask * Properly support pmu->stop(): it should call pmu->read() * Properly support pmu->del(): it should call stop(event, PERF_EF_UPDATE) * Introduce refcounting of event subscriptions. * Make pmu.busy_stats a refcounter to avoid busy stats going away with some deleted event. * Expose cpumask for i915 PMU to avoid multiple events creation of the same type followed by counter aggregation by perf-stat. * Track CPUs getting online/offline to migrate perf context. If (likely) cpumask will initially set CPU0, CONFIG_BOOTPARAM_HOTPLUG_CPU0 will be needed to see effect of CPU status tracking. * End result is that only global events are supported and perf stat works correctly. * Deny perf driver level sampling - it is prohibited for uncore PMU. v5: (Tvrtko Ursulin) * Don't hardcode number of engine samplers. * Rewrite event ref-counting for correctness and simplicity. * Store initial counter value when starting already enabled events to correctly report values to all listeners. * Fix RC6 residency readout. * Comments, GPL header. v6: * Add missing entry to v4 changelog. * Fix accounting in CPU hotplug case by copying the approach from arch/x86/events/intel/cstate.c. (Dmitry Rogozhkin) v7: * Log failure message only on failure. * Remove CPU hotplug notification state on unregister. v8: * Fix error unwind on failed registration. * Checkpatch cleanup. v9: * Drop the energy metric, it is available via intel_rapl_perf. (Ville Syrjälä) * Use HAS_RC6(p). (Chris Wilson) * Handle unsupported non-engine events. (Dmitry Rogozhkin) * Rebase for intel_rc6_residency_ns needing caller managed runtime pm. * Drop HAS_RC6 checks from the read callback since creating those events will be rejected at init time already. * Add counter units to sysfs so perf stat output is nicer. * Cleanup the attribute tables for brevity and readability. v10: * Fixed queued accounting. v11: * Move intel_engine_lookup_user to intel_engine_cs.c * Commit update. (Joonas Lahtinen) v12: * More accurate sampling. (Chris Wilson) * Store and report frequency in MHz for better usability from perf stat. * Removed metrics: queued, interrupts, rc6 counters. * Sample engine busyness based on seqno difference only for less MMIO (and forcewake) on all platforms. (Chris Wilson) v13: * Comment spelling, use mul_u32_u32 to work around potential GCC issue and somne code alignment changes. (Chris Wilson) v14: * Rebase. v15: * Rebase for RPS refactoring. v16: * Use the dynamic slot in the CPU hotplug state machine so that we are free to setup our state as multi-instance. Previously we were re-using the CPUHP_AP_PERF_X86_UNCORE_ONLINE slot which is neither used as multi-instance, nor owned by our driver to start with. * Register the CPU hotplug handlers after the PMU, otherwise the callback will get called before the PMU is initialized which can end up in perf_pmu_migrate_context with an un-initialized base. * Added workaround for a probable bug in cpuhp core. v17: * Remove workaround for the cpuhp bug. v18: * Rebase for drm_i915_gem_engine_class getting upstream before us. v19: * Rebase. (trivial) Signed-off-by: Chris Wilson Signed-off-by: Tvrtko Ursulin Signed-off-by: Dmitry Rogozhkin Cc: Tvrtko Ursulin Cc: Chris Wilson Cc: Dmitry Rogozhkin Cc: Peter Zijlstra Reviewed-by: Chris Wilson Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-2-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.c | 3 + drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_pmu.c | 688 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_pmu.h | 104 +++++ drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_engine_cs.c | 33 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 26 ++ 8 files changed, 863 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_pmu.c create mode 100644 drivers/gpu/drm/i915/i915_pmu.h (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index c3649ec5b041..42bc8bd4ff06 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -45,6 +45,7 @@ i915-y := i915_drv.o \ i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o +i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o # GEM code i915-y += i915_cmd_parser.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8dbcb03b5f54..0793a27e2b95 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -48,6 +48,7 @@ #include "i915_drv.h" #include "i915_trace.h" +#include "i915_pmu.h" #include "i915_vgpu.h" #include "intel_drv.h" #include "intel_uc.h" @@ -1215,6 +1216,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) struct drm_device *dev = &dev_priv->drm; i915_gem_shrinker_init(dev_priv); + i915_pmu_register(dev_priv); /* * Notify a valid surface after modesetting, @@ -1269,6 +1271,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) intel_opregion_unregister(dev_priv); i915_perf_unregister(dev_priv); + i915_pmu_unregister(dev_priv); i915_teardown_sysfs(dev_priv); i915_guc_log_unregister(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 019117144b3b..5bd5ac4cd03e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -2290,6 +2291,8 @@ struct drm_i915_private { struct i915_gem_context *kernel_context; /* Context only to be used for injecting preemption commands */ struct i915_gem_context *preempt_context; + struct intel_engine_cs *engine_class[MAX_ENGINE_CLASS + 1] + [MAX_ENGINE_INSTANCE + 1]; struct drm_dma_handle *status_page_dmah; struct resource mch_res; @@ -2761,6 +2764,8 @@ struct drm_i915_private { int irq; } lpe_audio; + struct i915_pmu pmu; + /* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c new file mode 100644 index 000000000000..01b5ee67c1bf --- /dev/null +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -0,0 +1,688 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include +#include + +#include "i915_drv.h" +#include "i915_pmu.h" +#include "intel_ringbuffer.h" + +/* Frequency for the sampling timer for events which need it. */ +#define FREQUENCY 200 +#define PERIOD max_t(u64, 10000, NSEC_PER_SEC / FREQUENCY) + +#define ENGINE_SAMPLE_MASK \ + (BIT(I915_SAMPLE_BUSY) | \ + BIT(I915_SAMPLE_WAIT) | \ + BIT(I915_SAMPLE_SEMA)) + +#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS) + +static cpumask_t i915_pmu_cpumask = CPU_MASK_NONE; + +static u8 engine_config_sample(u64 config) +{ + return config & I915_PMU_SAMPLE_MASK; +} + +static u8 engine_event_sample(struct perf_event *event) +{ + return engine_config_sample(event->attr.config); +} + +static u8 engine_event_class(struct perf_event *event) +{ + return (event->attr.config >> I915_PMU_CLASS_SHIFT) & 0xff; +} + +static u8 engine_event_instance(struct perf_event *event) +{ + return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff; +} + +static bool is_engine_config(u64 config) +{ + return config < __I915_PMU_OTHER(0); +} + +static unsigned int config_enabled_bit(u64 config) +{ + if (is_engine_config(config)) + return engine_config_sample(config); + else + return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0)); +} + +static u64 config_enabled_mask(u64 config) +{ + return BIT_ULL(config_enabled_bit(config)); +} + +static bool is_engine_event(struct perf_event *event) +{ + return is_engine_config(event->attr.config); +} + +static unsigned int event_enabled_bit(struct perf_event *event) +{ + return config_enabled_bit(event->attr.config); +} + +static bool grab_forcewake(struct drm_i915_private *i915, bool fw) +{ + if (!fw) + intel_uncore_forcewake_get(i915, FORCEWAKE_ALL); + + return true; +} + +static void +update_sample(struct i915_pmu_sample *sample, u32 unit, u32 val) +{ + /* + * Since we are doing stochastic sampling for these counters, + * average the delta with the previous value for better accuracy. + */ + sample->cur += div_u64(mul_u32_u32(sample->prev + val, unit), 2); + sample->prev = val; +} + +static void engines_sample(struct drm_i915_private *dev_priv) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + bool fw = false; + + if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0) + return; + + if (!dev_priv->gt.awake) + return; + + if (!intel_runtime_pm_get_if_in_use(dev_priv)) + return; + + for_each_engine(engine, dev_priv, id) { + u32 current_seqno = intel_engine_get_seqno(engine); + u32 last_seqno = intel_engine_last_submit(engine); + u32 val; + + val = !i915_seqno_passed(current_seqno, last_seqno); + + update_sample(&engine->pmu.sample[I915_SAMPLE_BUSY], + PERIOD, val); + + if (val && (engine->pmu.enable & + (BIT(I915_SAMPLE_WAIT) | BIT(I915_SAMPLE_SEMA)))) { + fw = grab_forcewake(dev_priv, fw); + + val = I915_READ_FW(RING_CTL(engine->mmio_base)); + } else { + val = 0; + } + + update_sample(&engine->pmu.sample[I915_SAMPLE_WAIT], + PERIOD, !!(val & RING_WAIT)); + + update_sample(&engine->pmu.sample[I915_SAMPLE_SEMA], + PERIOD, !!(val & RING_WAIT_SEMAPHORE)); + } + + if (fw) + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + + intel_runtime_pm_put(dev_priv); +} + +static void frequency_sample(struct drm_i915_private *dev_priv) +{ + if (dev_priv->pmu.enable & + config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) { + u32 val; + + val = dev_priv->gt_pm.rps.cur_freq; + if (dev_priv->gt.awake && + intel_runtime_pm_get_if_in_use(dev_priv)) { + val = intel_get_cagf(dev_priv, + I915_READ_NOTRACE(GEN6_RPSTAT1)); + intel_runtime_pm_put(dev_priv); + } + + update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT], + 1, intel_gpu_freq(dev_priv, val)); + } + + if (dev_priv->pmu.enable & + config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) { + update_sample(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_REQ], 1, + intel_gpu_freq(dev_priv, + dev_priv->gt_pm.rps.cur_freq)); + } +} + +static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) +{ + struct drm_i915_private *i915 = + container_of(hrtimer, struct drm_i915_private, pmu.timer); + + if (i915->pmu.enable == 0) + return HRTIMER_NORESTART; + + engines_sample(i915); + frequency_sample(i915); + + hrtimer_forward_now(hrtimer, ns_to_ktime(PERIOD)); + return HRTIMER_RESTART; +} + +static void i915_pmu_event_destroy(struct perf_event *event) +{ + WARN_ON(event->parent); +} + +static int engine_event_init(struct perf_event *event) +{ + struct drm_i915_private *i915 = + container_of(event->pmu, typeof(*i915), pmu.base); + + if (!intel_engine_lookup_user(i915, engine_event_class(event), + engine_event_instance(event))) + return -ENODEV; + + switch (engine_event_sample(event)) { + case I915_SAMPLE_BUSY: + case I915_SAMPLE_WAIT: + break; + case I915_SAMPLE_SEMA: + if (INTEL_GEN(i915) < 6) + return -ENODEV; + break; + default: + return -ENOENT; + } + + return 0; +} + +static int i915_pmu_event_init(struct perf_event *event) +{ + struct drm_i915_private *i915 = + container_of(event->pmu, typeof(*i915), pmu.base); + int cpu, ret; + + if (event->attr.type != event->pmu->type) + return -ENOENT; + + /* unsupported modes and filters */ + if (event->attr.sample_period) /* no sampling */ + return -EINVAL; + + if (has_branch_stack(event)) + return -EOPNOTSUPP; + + if (event->cpu < 0) + return -EINVAL; + + cpu = cpumask_any_and(&i915_pmu_cpumask, + topology_sibling_cpumask(event->cpu)); + if (cpu >= nr_cpu_ids) + return -ENODEV; + + if (is_engine_event(event)) { + ret = engine_event_init(event); + } else { + ret = 0; + switch (event->attr.config) { + case I915_PMU_ACTUAL_FREQUENCY: + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + /* Requires a mutex for sampling! */ + ret = -ENODEV; + case I915_PMU_REQUESTED_FREQUENCY: + if (INTEL_GEN(i915) < 6) + ret = -ENODEV; + break; + default: + ret = -ENOENT; + break; + } + } + if (ret) + return ret; + + event->cpu = cpu; + if (!event->parent) + event->destroy = i915_pmu_event_destroy; + + return 0; +} + +static u64 __i915_pmu_event_read(struct perf_event *event) +{ + struct drm_i915_private *i915 = + container_of(event->pmu, typeof(*i915), pmu.base); + u64 val = 0; + + if (is_engine_event(event)) { + u8 sample = engine_event_sample(event); + struct intel_engine_cs *engine; + + engine = intel_engine_lookup_user(i915, + engine_event_class(event), + engine_event_instance(event)); + + if (WARN_ON_ONCE(!engine)) { + /* Do nothing */ + } else { + val = engine->pmu.sample[sample].cur; + } + } else { + switch (event->attr.config) { + case I915_PMU_ACTUAL_FREQUENCY: + val = + div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_ACT].cur, + FREQUENCY); + break; + case I915_PMU_REQUESTED_FREQUENCY: + val = + div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur, + FREQUENCY); + break; + } + } + + return val; +} + +static void i915_pmu_event_read(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + u64 prev, new; + +again: + prev = local64_read(&hwc->prev_count); + new = __i915_pmu_event_read(event); + + if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) + goto again; + + local64_add(new - prev, &event->count); +} + +static void i915_pmu_enable(struct perf_event *event) +{ + struct drm_i915_private *i915 = + container_of(event->pmu, typeof(*i915), pmu.base); + unsigned int bit = event_enabled_bit(event); + unsigned long flags; + + spin_lock_irqsave(&i915->pmu.lock, flags); + + /* + * Start the sampling timer when enabling the first event. + */ + if (i915->pmu.enable == 0) + hrtimer_start_range_ns(&i915->pmu.timer, + ns_to_ktime(PERIOD), 0, + HRTIMER_MODE_REL_PINNED); + + /* + * Update the bitmask of enabled events and increment + * the event reference counter. + */ + GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); + GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0); + i915->pmu.enable |= BIT_ULL(bit); + i915->pmu.enable_count[bit]++; + + /* + * For per-engine events the bitmask and reference counting + * is stored per engine. + */ + if (is_engine_event(event)) { + u8 sample = engine_event_sample(event); + struct intel_engine_cs *engine; + + engine = intel_engine_lookup_user(i915, + engine_event_class(event), + engine_event_instance(event)); + GEM_BUG_ON(!engine); + engine->pmu.enable |= BIT(sample); + + GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); + GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); + engine->pmu.enable_count[sample]++; + } + + /* + * Store the current counter value so we can report the correct delta + * for all listeners. Even when the event was already enabled and has + * an existing non-zero value. + */ + local64_set(&event->hw.prev_count, __i915_pmu_event_read(event)); + + spin_unlock_irqrestore(&i915->pmu.lock, flags); +} + +static void i915_pmu_disable(struct perf_event *event) +{ + struct drm_i915_private *i915 = + container_of(event->pmu, typeof(*i915), pmu.base); + unsigned int bit = event_enabled_bit(event); + unsigned long flags; + + spin_lock_irqsave(&i915->pmu.lock, flags); + + if (is_engine_event(event)) { + u8 sample = engine_event_sample(event); + struct intel_engine_cs *engine; + + engine = intel_engine_lookup_user(i915, + engine_event_class(event), + engine_event_instance(event)); + GEM_BUG_ON(!engine); + GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); + GEM_BUG_ON(engine->pmu.enable_count[sample] == 0); + /* + * Decrement the reference count and clear the enabled + * bitmask when the last listener on an event goes away. + */ + if (--engine->pmu.enable_count[sample] == 0) + engine->pmu.enable &= ~BIT(sample); + } + + GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); + GEM_BUG_ON(i915->pmu.enable_count[bit] == 0); + /* + * Decrement the reference count and clear the enabled + * bitmask when the last listener on an event goes away. + */ + if (--i915->pmu.enable_count[bit] == 0) + i915->pmu.enable &= ~BIT_ULL(bit); + + spin_unlock_irqrestore(&i915->pmu.lock, flags); +} + +static void i915_pmu_event_start(struct perf_event *event, int flags) +{ + i915_pmu_enable(event); + event->hw.state = 0; +} + +static void i915_pmu_event_stop(struct perf_event *event, int flags) +{ + if (flags & PERF_EF_UPDATE) + i915_pmu_event_read(event); + i915_pmu_disable(event); + event->hw.state = PERF_HES_STOPPED; +} + +static int i915_pmu_event_add(struct perf_event *event, int flags) +{ + if (flags & PERF_EF_START) + i915_pmu_event_start(event, flags); + + return 0; +} + +static void i915_pmu_event_del(struct perf_event *event, int flags) +{ + i915_pmu_event_stop(event, PERF_EF_UPDATE); +} + +static int i915_pmu_event_event_idx(struct perf_event *event) +{ + return 0; +} + +static ssize_t i915_pmu_format_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + return sprintf(buf, "%s\n", (char *)eattr->var); +} + +#define I915_PMU_FORMAT_ATTR(_name, _config) \ + (&((struct dev_ext_attribute[]) { \ + { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \ + .var = (void *)_config, } \ + })[0].attr.attr) + +static struct attribute *i915_pmu_format_attrs[] = { + I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"), + NULL, +}; + +static const struct attribute_group i915_pmu_format_attr_group = { + .name = "format", + .attrs = i915_pmu_format_attrs, +}; + +static ssize_t i915_pmu_event_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var); +} + +#define I915_EVENT_ATTR(_name, _config) \ + (&((struct dev_ext_attribute[]) { \ + { .attr = __ATTR(_name, 0444, i915_pmu_event_show, NULL), \ + .var = (void *)_config, } \ + })[0].attr.attr) + +#define I915_EVENT_STR(_name, _str) \ + (&((struct perf_pmu_events_attr[]) { \ + { .attr = __ATTR(_name, 0444, perf_event_sysfs_show, NULL), \ + .id = 0, \ + .event_str = _str, } \ + })[0].attr.attr) + +#define I915_EVENT(_name, _config, _unit) \ + I915_EVENT_ATTR(_name, _config), \ + I915_EVENT_STR(_name.unit, _unit) + +#define I915_ENGINE_EVENT(_name, _class, _instance, _sample) \ + I915_EVENT_ATTR(_name, __I915_PMU_ENGINE(_class, _instance, _sample)), \ + I915_EVENT_STR(_name.unit, "ns") + +#define I915_ENGINE_EVENTS(_name, _class, _instance) \ + I915_ENGINE_EVENT(_name##_instance-busy, _class, _instance, I915_SAMPLE_BUSY), \ + I915_ENGINE_EVENT(_name##_instance-sema, _class, _instance, I915_SAMPLE_SEMA), \ + I915_ENGINE_EVENT(_name##_instance-wait, _class, _instance, I915_SAMPLE_WAIT) + +static struct attribute *i915_pmu_events_attrs[] = { + I915_ENGINE_EVENTS(rcs, I915_ENGINE_CLASS_RENDER, 0), + I915_ENGINE_EVENTS(bcs, I915_ENGINE_CLASS_COPY, 0), + I915_ENGINE_EVENTS(vcs, I915_ENGINE_CLASS_VIDEO, 0), + I915_ENGINE_EVENTS(vcs, I915_ENGINE_CLASS_VIDEO, 1), + I915_ENGINE_EVENTS(vecs, I915_ENGINE_CLASS_VIDEO_ENHANCE, 0), + + I915_EVENT(actual-frequency, I915_PMU_ACTUAL_FREQUENCY, "MHz"), + I915_EVENT(requested-frequency, I915_PMU_REQUESTED_FREQUENCY, "MHz"), + + NULL, +}; + +static const struct attribute_group i915_pmu_events_attr_group = { + .name = "events", + .attrs = i915_pmu_events_attrs, +}; + +static ssize_t +i915_pmu_get_attr_cpumask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask); +} + +static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL); + +static struct attribute *i915_cpumask_attrs[] = { + &dev_attr_cpumask.attr, + NULL, +}; + +static struct attribute_group i915_pmu_cpumask_attr_group = { + .attrs = i915_cpumask_attrs, +}; + +static const struct attribute_group *i915_pmu_attr_groups[] = { + &i915_pmu_format_attr_group, + &i915_pmu_events_attr_group, + &i915_pmu_cpumask_attr_group, + NULL +}; + +#ifdef CONFIG_HOTPLUG_CPU +static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) +{ + struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); + unsigned int target; + + GEM_BUG_ON(!pmu->base.event_init); + + target = cpumask_any_and(&i915_pmu_cpumask, &i915_pmu_cpumask); + /* Select the first online CPU as a designated reader. */ + if (target >= nr_cpu_ids) + cpumask_set_cpu(cpu, &i915_pmu_cpumask); + + return 0; +} + +static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) +{ + struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); + unsigned int target; + + GEM_BUG_ON(!pmu->base.event_init); + + if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) { + target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); + /* Migrate events if there is a valid target */ + if (target < nr_cpu_ids) { + cpumask_set_cpu(target, &i915_pmu_cpumask); + perf_pmu_migrate_context(&pmu->base, cpu, target); + } + } + + return 0; +} + +static enum cpuhp_state cpuhp_slot = CPUHP_INVALID; +#endif + +static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915) +{ +#ifdef CONFIG_HOTPLUG_CPU + enum cpuhp_state slot; + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "perf/x86/intel/i915:online", + i915_pmu_cpu_online, + i915_pmu_cpu_offline); + if (ret < 0) + return ret; + + slot = ret; + ret = cpuhp_state_add_instance(slot, &i915->pmu.node); + if (ret) { + cpuhp_remove_multi_state(slot); + return ret; + } + + cpuhp_slot = slot; +#endif + return 0; +} + +static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915) +{ +#ifdef CONFIG_HOTPLUG_CPU + WARN_ON(cpuhp_slot == CPUHP_INVALID); + WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &i915->pmu.node)); + cpuhp_remove_multi_state(cpuhp_slot); +#endif +} + +void i915_pmu_register(struct drm_i915_private *i915) +{ + int ret; + + if (INTEL_GEN(i915) <= 2) { + DRM_INFO("PMU not supported for this GPU."); + return; + } + + i915->pmu.base.attr_groups = i915_pmu_attr_groups; + i915->pmu.base.task_ctx_nr = perf_invalid_context; + i915->pmu.base.event_init = i915_pmu_event_init; + i915->pmu.base.add = i915_pmu_event_add; + i915->pmu.base.del = i915_pmu_event_del; + i915->pmu.base.start = i915_pmu_event_start; + i915->pmu.base.stop = i915_pmu_event_stop; + i915->pmu.base.read = i915_pmu_event_read; + i915->pmu.base.event_idx = i915_pmu_event_event_idx; + + spin_lock_init(&i915->pmu.lock); + hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + i915->pmu.timer.function = i915_sample; + + ret = perf_pmu_register(&i915->pmu.base, "i915", -1); + if (ret) + goto err; + + ret = i915_pmu_register_cpuhp_state(i915); + if (ret) + goto err_unreg; + + return; + +err_unreg: + perf_pmu_unregister(&i915->pmu.base); +err: + i915->pmu.base.event_init = NULL; + DRM_NOTE("Failed to register PMU! (err=%d)\n", ret); +} + +void i915_pmu_unregister(struct drm_i915_private *i915) +{ + if (!i915->pmu.base.event_init) + return; + + WARN_ON(i915->pmu.enable); + + hrtimer_cancel(&i915->pmu.timer); + + i915_pmu_unregister_cpuhp_state(i915); + + perf_pmu_unregister(&i915->pmu.base); + i915->pmu.base.event_init = NULL; +} diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h new file mode 100644 index 000000000000..1ac8b2e34607 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -0,0 +1,104 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ +#ifndef __I915_PMU_H__ +#define __I915_PMU_H__ + +enum { + __I915_SAMPLE_FREQ_ACT = 0, + __I915_SAMPLE_FREQ_REQ, + __I915_NUM_PMU_SAMPLERS +}; + +/** + * How many different events we track in the global PMU mask. + * + * It is also used to know to needed number of event reference counters. + */ +#define I915_PMU_MASK_BITS \ + ((1 << I915_PMU_SAMPLE_BITS) + \ + (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0))) + +struct i915_pmu_sample { + u64 cur; + u32 prev; +}; + +struct i915_pmu { + /** + * @node: List node for CPU hotplug handling. + */ + struct hlist_node node; + /** + * @base: PMU base. + */ + struct pmu base; + /** + * @lock: Lock protecting enable mask and ref count handling. + */ + spinlock_t lock; + /** + * @timer: Timer for internal i915 PMU sampling. + */ + struct hrtimer timer; + /** + * @enable: Bitmask of all currently enabled events. + * + * Bits are derived from uAPI event numbers in a way that low 16 bits + * correspond to engine event _sample_ _type_ (I915_SAMPLE_QUEUED is + * bit 0), and higher bits correspond to other events (for instance + * I915_PMU_ACTUAL_FREQUENCY is bit 16 etc). + * + * In other words, low 16 bits are not per engine but per engine + * sampler type, while the upper bits are directly mapped to other + * event types. + */ + u64 enable; + /** + * @enable_count: Reference counts for the enabled events. + * + * Array indices are mapped in the same way as bits in the @enable field + * and they are used to control sampling on/off when multiple clients + * are using the PMU API. + */ + unsigned int enable_count[I915_PMU_MASK_BITS]; + /** + * @sample: Current and previous (raw) counters for sampling events. + * + * These counters are updated from the i915 PMU sampling timer. + * + * Only global counters are held here, while the per-engine ones are in + * struct intel_engine_cs. + */ + struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; +}; + +#ifdef CONFIG_PERF_EVENTS +void i915_pmu_register(struct drm_i915_private *i915); +void i915_pmu_unregister(struct drm_i915_private *i915); +#else +static inline void i915_pmu_register(struct drm_i915_private *i915) {} +static inline void i915_pmu_unregister(struct drm_i915_private *i915) {} +#endif + +#endif diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 96c80fa0fcac..09bf043c1c2e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -186,6 +186,9 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VIDEO_ENHANCEMENT_CLASS 2 #define COPY_ENGINE_CLASS 3 #define OTHER_CLASS 4 +#define MAX_ENGINE_CLASS 4 + +#define MAX_ENGINE_INSTANCE 1 /* PCI config space */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 22c095035539..a5a494210b9e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -205,6 +205,15 @@ intel_engine_setup(struct drm_i915_private *dev_priv, GEM_BUG_ON(info->class >= ARRAY_SIZE(intel_engine_classes)); class_info = &intel_engine_classes[info->class]; + if (GEM_WARN_ON(info->class > MAX_ENGINE_CLASS)) + return -EINVAL; + + if (GEM_WARN_ON(info->instance > MAX_ENGINE_INSTANCE)) + return -EINVAL; + + if (GEM_WARN_ON(dev_priv->engine_class[info->class][info->instance])) + return -EINVAL; + GEM_BUG_ON(dev_priv->engine[id]); engine = kzalloc(sizeof(*engine), GFP_KERNEL); if (!engine) @@ -234,6 +243,7 @@ intel_engine_setup(struct drm_i915_private *dev_priv, ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); + dev_priv->engine_class[info->class][info->instance] = engine; dev_priv->engine[id] = engine; return 0; } @@ -1816,6 +1826,29 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) drm_printf(m, "\n"); } +static u8 user_class_map[] = { + [I915_ENGINE_CLASS_RENDER] = RENDER_CLASS, + [I915_ENGINE_CLASS_COPY] = COPY_ENGINE_CLASS, + [I915_ENGINE_CLASS_VIDEO] = VIDEO_DECODE_CLASS, + [I915_ENGINE_CLASS_VIDEO_ENHANCE] = VIDEO_ENHANCEMENT_CLASS, +}; + +struct intel_engine_cs * +intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance) +{ + if (class >= ARRAY_SIZE(user_class_map)) + return NULL; + + class = user_class_map[class]; + + GEM_BUG_ON(class > MAX_ENGINE_CLASS); + + if (instance > MAX_ENGINE_INSTANCE) + return NULL; + + return i915->engine_class[class][instance]; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #endif diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 80cd7812ce02..7ee0f18d4179 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -5,6 +5,7 @@ #include "i915_gem_batch_pool.h" #include "i915_gem_request.h" #include "i915_gem_timeline.h" +#include "i915_pmu.h" #include "i915_selftest.h" struct drm_printer; @@ -338,6 +339,28 @@ struct intel_engine_cs { I915_SELFTEST_DECLARE(bool mock : 1); } breadcrumbs; + struct { + /** + * @enable: Bitmask of enable sample events on this engine. + * + * Bits correspond to sample event types, for instance + * I915_SAMPLE_QUEUED is bit 0 etc. + */ + u32 enable; + /** + * @enable_count: Reference count for the enabled samplers. + * + * Index number corresponds to the bit number from @enable. + */ + unsigned int enable_count[I915_PMU_SAMPLE_BITS]; + /** + * @sample: Counter values for sampling events. + * + * Our internal timer stores the current counters in this field. + */ + struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; + } pmu; + /* * A pool of objects to use as shadow copies of client batch buffers * when the command parser is enabled. Prevents the client from @@ -926,4 +949,7 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine); void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p); +struct intel_engine_cs * +intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance); + #endif /* _INTEL_RINGBUFFER_H_ */ -- cgit From feff0dc6cdc527f8a6fd170d8de7966f56890fc0 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:46 +0000 Subject: drm/i915/pmu: Suspend sampling when GPU is idle If only a subset of events is enabled we can afford to suspend the sampling timer when the GPU is idle and so save some cycles and power. v2: Rebase and limit timer even more. v3: Rebase. v4: Rebase. v5: Skip action if perf PMU failed to register. v6: Checkpatch cleanup. v7: * Add a common helper to start the timer if needed. (Chris Wilson) * Add comment explaining bitwise logic in pmu_needs_timer. v8: Fix some comments styles. (Chris Wilson) v9: Rebase. v10: Move function declarations to i915_pmu.h. v11: Rename functions to i915_pmu_gt_(un)parked. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-3-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 1 + drivers/gpu/drm/i915/i915_gem_request.c | 1 + drivers/gpu/drm/i915/i915_pmu.c | 88 +++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_pmu.h | 8 +++ 4 files changed, 88 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 792e6dc7e19b..21ca680e9e63 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3372,6 +3372,7 @@ i915_gem_idle_work_handler(struct work_struct *work) intel_engines_park(dev_priv); i915_gem_timelines_mark_idle(dev_priv); + i915_pmu_gt_parked(dev_priv); GEM_BUG_ON(!dev_priv->gt.awake); dev_priv->gt.awake = false; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 86e2346357cf..7325469ce754 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -258,6 +258,7 @@ static void mark_busy(struct drm_i915_private *i915) i915_update_gfx_val(i915); if (INTEL_GEN(i915) >= 6) gen6_rps_busy(i915); + i915_pmu_gt_unparked(i915); intel_engines_unpark(i915); diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 01b5ee67c1bf..fb95f0ac30ea 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -90,6 +90,75 @@ static unsigned int event_enabled_bit(struct perf_event *event) return config_enabled_bit(event->attr.config); } +static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active) +{ + u64 enable; + + /* + * Only some counters need the sampling timer. + * + * We start with a bitmask of all currently enabled events. + */ + enable = i915->pmu.enable; + + /* + * Mask out all the ones which do not need the timer, or in + * other words keep all the ones that could need the timer. + */ + enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) | + config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) | + ENGINE_SAMPLE_MASK; + + /* + * When the GPU is idle per-engine counters do not need to be + * running so clear those bits out. + */ + if (!gpu_active) + enable &= ~ENGINE_SAMPLE_MASK; + + /* + * If some bits remain it means we need the sampling timer running. + */ + return enable; +} + +void i915_pmu_gt_parked(struct drm_i915_private *i915) +{ + if (!i915->pmu.base.event_init) + return; + + spin_lock_irq(&i915->pmu.lock); + /* + * Signal sampling timer to stop if only engine events are enabled and + * GPU went idle. + */ + i915->pmu.timer_enabled = pmu_needs_timer(i915, false); + spin_unlock_irq(&i915->pmu.lock); +} + +static void __i915_pmu_maybe_start_timer(struct drm_i915_private *i915) +{ + if (!i915->pmu.timer_enabled && pmu_needs_timer(i915, true)) { + i915->pmu.timer_enabled = true; + hrtimer_start_range_ns(&i915->pmu.timer, + ns_to_ktime(PERIOD), 0, + HRTIMER_MODE_REL_PINNED); + } +} + +void i915_pmu_gt_unparked(struct drm_i915_private *i915) +{ + if (!i915->pmu.base.event_init) + return; + + spin_lock_irq(&i915->pmu.lock); + /* + * Re-enable sampling timer when GPU goes active. + */ + __i915_pmu_maybe_start_timer(i915); + spin_unlock_irq(&i915->pmu.lock); +} + static bool grab_forcewake(struct drm_i915_private *i915, bool fw) { if (!fw) @@ -187,7 +256,7 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) struct drm_i915_private *i915 = container_of(hrtimer, struct drm_i915_private, pmu.timer); - if (i915->pmu.enable == 0) + if (!READ_ONCE(i915->pmu.timer_enabled)) return HRTIMER_NORESTART; engines_sample(i915); @@ -339,14 +408,6 @@ static void i915_pmu_enable(struct perf_event *event) spin_lock_irqsave(&i915->pmu.lock, flags); - /* - * Start the sampling timer when enabling the first event. - */ - if (i915->pmu.enable == 0) - hrtimer_start_range_ns(&i915->pmu.timer, - ns_to_ktime(PERIOD), 0, - HRTIMER_MODE_REL_PINNED); - /* * Update the bitmask of enabled events and increment * the event reference counter. @@ -356,6 +417,11 @@ static void i915_pmu_enable(struct perf_event *event) i915->pmu.enable |= BIT_ULL(bit); i915->pmu.enable_count[bit]++; + /* + * Start the sampling timer if needed and not already enabled. + */ + __i915_pmu_maybe_start_timer(i915); + /* * For per-engine events the bitmask and reference counting * is stored per engine. @@ -418,8 +484,10 @@ static void i915_pmu_disable(struct perf_event *event) * Decrement the reference count and clear the enabled * bitmask when the last listener on an event goes away. */ - if (--i915->pmu.enable_count[bit] == 0) + if (--i915->pmu.enable_count[bit] == 0) { i915->pmu.enable &= ~BIT_ULL(bit); + i915->pmu.timer_enabled &= pmu_needs_timer(i915, true); + } spin_unlock_irqrestore(&i915->pmu.lock, flags); } diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 1ac8b2e34607..e209783a4c5f 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -82,6 +82,10 @@ struct i915_pmu { * are using the PMU API. */ unsigned int enable_count[I915_PMU_MASK_BITS]; + /** + * @timer_enabled: Should the internal sampling timer be running. + */ + bool timer_enabled; /** * @sample: Current and previous (raw) counters for sampling events. * @@ -96,9 +100,13 @@ struct i915_pmu { #ifdef CONFIG_PERF_EVENTS void i915_pmu_register(struct drm_i915_private *i915); void i915_pmu_unregister(struct drm_i915_private *i915); +void i915_pmu_gt_parked(struct drm_i915_private *i915); +void i915_pmu_gt_unparked(struct drm_i915_private *i915); #else static inline void i915_pmu_register(struct drm_i915_private *i915) {} static inline void i915_pmu_unregister(struct drm_i915_private *i915) {} +static inline void i915_pmu_gt_parked(struct drm_i915_private *i915) {} +static inline void i915_pmu_gt_unparked(struct drm_i915_private *i915) {} #endif #endif -- cgit From 73fd9d381693dee6f28bb24de4b81b643d4d6d63 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:47 +0000 Subject: drm/i915: Wrap context schedule notification No functional change just something which will be handy in the following patch. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-4-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_lrc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 16d4936e2368..8e3990d5191c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -379,6 +379,18 @@ execlists_context_status_change(struct drm_i915_gem_request *rq, status, rq); } +static inline void +execlists_context_schedule_in(struct drm_i915_gem_request *rq) +{ + execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); +} + +static inline void +execlists_context_schedule_out(struct drm_i915_gem_request *rq) +{ + execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); +} + static void execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) { @@ -430,7 +442,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) if (rq) { GEM_BUG_ON(count > !n); if (!count++) - execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); + execlists_context_schedule_in(rq); port_set(&port[n], port_pack(rq, count)); desc = execlists_update_context(rq); GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); @@ -902,8 +914,7 @@ static void execlists_submission_tasklet(unsigned long data) GEM_BUG_ON(port_isset(&port[1]) && !(status & GEN8_CTX_STATUS_ELEMENT_SWITCH)); GEM_BUG_ON(!i915_gem_request_completed(rq)); - execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); - + execlists_context_schedule_out(rq); trace_i915_gem_request_out(rq); i915_gem_request_put(rq); -- cgit From 30e17b7847f54732a91e5804144d445e9f29493b Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:48 +0000 Subject: drm/i915: Engine busy time tracking Track total time requests have been executing on the hardware. We add new kernel API to allow software tracking of time GPU engines are spending executing requests. Both per-engine and global API is added with the latter also being exported for use by external users. v2: * Squashed with the internal API. * Dropped static key. * Made per-engine. * Store time in monotonic ktime. v3: Moved stats clearing to disable. v4: * Comments. * Don't export the API just yet. v5: Whitespace cleanup. v6: * Rename ref to active. * Drop engine aggregate stats for now. * Account initial busy period after enabling stats. v7: * Rebase. v8: * Move context in notification after the notifier. (Chris Wilson) v9: In cases where stats tracking is getting disabled while there is an active context on an engine, add up the current value to the total. This also implies we don't clear the total when tracking is disabled any longer. There is no real need to do so because we define the stats as relative while enabled, meaning comparison between two samples while tracking is enabled is the valid usage. However, when busy stats will later be plugged into the perf PMU API, it is beneficial to not reset the total, since the PMU core likes to do some counter disable/enable cycles on startup, and while doing so during a single long context executing on an engine we would lose some accuracy and so make unit testing more difficult than needs to be. v10: * Fix accounting for preemption. v11: * Rebase for i915_modparams.enable_execlists removal. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-5-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_engine_cs.c | 87 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 3 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 92 +++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index a5a494210b9e..fede62daf3e1 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -241,6 +241,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv, /* Nothing to do here, execute in order of dependencies */ engine->schedule = NULL; + spin_lock_init(&engine->stats.lock); + ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); dev_priv->engine_class[info->class][info->instance] = engine; @@ -1849,6 +1851,91 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance) return i915->engine_class[class][instance]; } +/** + * intel_enable_engine_stats() - Enable engine busy tracking on engine + * @engine: engine to enable stats collection + * + * Start collecting the engine busyness data for @engine. + * + * Returns 0 on success or a negative error code. + */ +int intel_enable_engine_stats(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (INTEL_GEN(engine->i915) < 8) + return -ENODEV; + + spin_lock_irqsave(&engine->stats.lock, flags); + if (engine->stats.enabled == ~0) + goto busy; + if (engine->stats.enabled++ == 0) + engine->stats.enabled_at = ktime_get(); + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return 0; + +busy: + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return -EBUSY; +} + +static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine) +{ + ktime_t total = engine->stats.total; + + /* + * If the engine is executing something at the moment + * add it to the total. + */ + if (engine->stats.active) + total = ktime_add(total, + ktime_sub(ktime_get(), engine->stats.start)); + + return total; +} + +/** + * intel_engine_get_busy_time() - Return current accumulated engine busyness + * @engine: engine to report on + * + * Returns accumulated time @engine was busy since engine stats were enabled. + */ +ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine) +{ + ktime_t total; + unsigned long flags; + + spin_lock_irqsave(&engine->stats.lock, flags); + total = __intel_engine_get_busy_time(engine); + spin_unlock_irqrestore(&engine->stats.lock, flags); + + return total; +} + +/** + * intel_disable_engine_stats() - Disable engine busy tracking on engine + * @engine: engine to disable stats collection + * + * Stops collecting the engine busyness data for @engine. + */ +void intel_disable_engine_stats(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (INTEL_GEN(engine->i915) < 8) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + WARN_ON_ONCE(engine->stats.enabled == 0); + if (--engine->stats.enabled == 0) { + engine->stats.total = __intel_engine_get_busy_time(engine); + engine->stats.active = 0; + } + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 8e3990d5191c..570864583e28 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -383,11 +383,13 @@ static inline void execlists_context_schedule_in(struct drm_i915_gem_request *rq) { execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_IN); + intel_engine_context_in(rq->engine); } static inline void execlists_context_schedule_out(struct drm_i915_gem_request *rq) { + intel_engine_context_out(rq->engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); } @@ -705,6 +707,7 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) struct drm_i915_gem_request *rq = port_request(port); GEM_BUG_ON(!execlists->active); + intel_engine_context_out(rq->engine); execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_PREEMPTED); i915_gem_request_put(rq); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7ee0f18d4179..215edfa424d5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -547,6 +547,38 @@ struct intel_engine_cs { * certain bits to encode the command length in the header). */ u32 (*get_cmd_length_mask)(u32 cmd_header); + + struct { + /** + * @lock: Lock protecting the below fields. + */ + spinlock_t lock; + /** + * @enabled: Reference count indicating number of listeners. + */ + unsigned int enabled; + /** + * @active: Number of contexts currently scheduled in. + */ + unsigned int active; + /** + * @enabled_at: Timestamp when busy stats were enabled. + */ + ktime_t enabled_at; + /** + * @start: Timestamp of the last idle to active transition. + * + * Idle is defined as active == 0, active is active > 0. + */ + ktime_t start; + /** + * @total: Total time this engine was busy. + * + * Accumulated time not counting the most recent block in cases + * where engine is currently busy (active > 0). + */ + ktime_t total; + } stats; }; static inline void @@ -952,4 +984,64 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p); struct intel_engine_cs * intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance); +static inline void intel_engine_context_in(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (READ_ONCE(engine->stats.enabled) == 0) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + + if (engine->stats.enabled > 0) { + if (engine->stats.active++ == 0) + engine->stats.start = ktime_get(); + GEM_BUG_ON(engine->stats.active == 0); + } + + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + +static inline void intel_engine_context_out(struct intel_engine_cs *engine) +{ + unsigned long flags; + + if (READ_ONCE(engine->stats.enabled) == 0) + return; + + spin_lock_irqsave(&engine->stats.lock, flags); + + if (engine->stats.enabled > 0) { + ktime_t last; + + if (engine->stats.active && --engine->stats.active == 0) { + /* + * Decrement the active context count and in case GPU + * is now idle add up to the running total. + */ + last = ktime_sub(ktime_get(), engine->stats.start); + + engine->stats.total = ktime_add(engine->stats.total, + last); + } else if (engine->stats.active == 0) { + /* + * After turning on engine stats, context out might be + * the first event in which case we account from the + * time stats gathering was turned on. + */ + last = ktime_sub(ktime_get(), engine->stats.enabled_at); + + engine->stats.total = ktime_add(engine->stats.total, + last); + } + } + + spin_unlock_irqrestore(&engine->stats.lock, flags); +} + +int intel_enable_engine_stats(struct intel_engine_cs *engine); +void intel_disable_engine_stats(struct intel_engine_cs *engine); + +ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine); + #endif /* _INTEL_RINGBUFFER_H_ */ -- cgit From b3add01ee217db8e0da8a6596f03c487ed33b06e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:49 +0000 Subject: drm/i915/pmu: Wire up engine busy stats to PMU We can use engine busy stats instead of the sampling timer for better accuracy. By doing this we replace the stohastic sampling with busyness metric derived directly from engine activity. This is context switch interrupt driven, so as accurate as we can get from software tracking. As a secondary benefit, we can also not run the sampling timer in cases only busyness metric is enabled. v2: Rebase. v3: * Rebase, comments. * Leave engine busyness controls out of workers. v4: Checkpatch cleanup. v5: Added comment to pmu_needs_timer change. v6: * Rebase. * Fix style of some comments. (Chris Wilson) v7: Rebase and commit message update. (Chris Wilson) v8: Add delayed stats disabling to improve accuracy in face of CPU hotplug events. v9: Rebase. v10: Rebase - i915_modparams.enable_execlists removal. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-6-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 78 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_ringbuffer.h | 14 ++++++ 2 files changed, 90 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index fb95f0ac30ea..6a428e7218d2 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -90,6 +90,11 @@ static unsigned int event_enabled_bit(struct perf_event *event) return config_enabled_bit(event->attr.config); } +static bool supports_busy_stats(struct drm_i915_private *i915) +{ + return INTEL_GEN(i915) >= 8; +} + static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active) { u64 enable; @@ -115,6 +120,12 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active) */ if (!gpu_active) enable &= ~ENGINE_SAMPLE_MASK; + /* + * Also there is software busyness tracking available we do not + * need the timer for I915_SAMPLE_BUSY counter. + */ + else if (supports_busy_stats(i915)) + enable &= ~BIT(I915_SAMPLE_BUSY); /* * If some bits remain it means we need the sampling timer running. @@ -363,6 +374,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event) if (WARN_ON_ONCE(!engine)) { /* Do nothing */ + } else if (sample == I915_SAMPLE_BUSY && + engine->pmu.busy_stats) { + val = ktime_to_ns(intel_engine_get_busy_time(engine)); } else { val = engine->pmu.sample[sample].cur; } @@ -399,6 +413,12 @@ again: local64_add(new - prev, &event->count); } +static bool engine_needs_busy_stats(struct intel_engine_cs *engine) +{ + return supports_busy_stats(engine->i915) && + (engine->pmu.enable & BIT(I915_SAMPLE_BUSY)); +} + static void i915_pmu_enable(struct perf_event *event) { struct drm_i915_private *i915 = @@ -438,7 +458,21 @@ static void i915_pmu_enable(struct perf_event *event) GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); - engine->pmu.enable_count[sample]++; + if (engine->pmu.enable_count[sample]++ == 0) { + /* + * Enable engine busy stats tracking if needed or + * alternatively cancel the scheduled disable. + * + * If the delayed disable was pending, cancel it and + * in this case do not enable since it already is. + */ + if (engine_needs_busy_stats(engine) && + !engine->pmu.busy_stats) { + engine->pmu.busy_stats = true; + if (!cancel_delayed_work(&engine->pmu.disable_busy_stats)) + intel_enable_engine_stats(engine); + } + } } /* @@ -451,6 +485,14 @@ static void i915_pmu_enable(struct perf_event *event) spin_unlock_irqrestore(&i915->pmu.lock, flags); } +static void __disable_busy_stats(struct work_struct *work) +{ + struct intel_engine_cs *engine = + container_of(work, typeof(*engine), pmu.disable_busy_stats.work); + + intel_disable_engine_stats(engine); +} + static void i915_pmu_disable(struct perf_event *event) { struct drm_i915_private *i915 = @@ -474,8 +516,26 @@ static void i915_pmu_disable(struct perf_event *event) * Decrement the reference count and clear the enabled * bitmask when the last listener on an event goes away. */ - if (--engine->pmu.enable_count[sample] == 0) + if (--engine->pmu.enable_count[sample] == 0) { engine->pmu.enable &= ~BIT(sample); + if (!engine_needs_busy_stats(engine) && + engine->pmu.busy_stats) { + engine->pmu.busy_stats = false; + /* + * We request a delayed disable to handle the + * rapid on/off cycles on events, which can + * happen when tools like perf stat start, in a + * nicer way. + * + * In addition, this also helps with busy stats + * accuracy with background CPU offline/online + * migration events. + */ + queue_delayed_work(system_wq, + &engine->pmu.disable_busy_stats, + round_jiffies_up_relative(HZ)); + } + } } GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); @@ -702,6 +762,8 @@ static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915) void i915_pmu_register(struct drm_i915_private *i915) { + struct intel_engine_cs *engine; + enum intel_engine_id id; int ret; if (INTEL_GEN(i915) <= 2) { @@ -723,6 +785,10 @@ void i915_pmu_register(struct drm_i915_private *i915) hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); i915->pmu.timer.function = i915_sample; + for_each_engine(engine, i915, id) + INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats, + __disable_busy_stats); + ret = perf_pmu_register(&i915->pmu.base, "i915", -1); if (ret) goto err; @@ -742,6 +808,9 @@ err: void i915_pmu_unregister(struct drm_i915_private *i915) { + struct intel_engine_cs *engine; + enum intel_engine_id id; + if (!i915->pmu.base.event_init) return; @@ -749,6 +818,11 @@ void i915_pmu_unregister(struct drm_i915_private *i915) hrtimer_cancel(&i915->pmu.timer); + for_each_engine(engine, i915, id) { + GEM_BUG_ON(engine->pmu.busy_stats); + flush_delayed_work(&engine->pmu.disable_busy_stats); + } + i915_pmu_unregister_cpuhp_state(i915); perf_pmu_unregister(&i915->pmu.base); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 215edfa424d5..43473e6d1a4f 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -359,6 +359,20 @@ struct intel_engine_cs { * Our internal timer stores the current counters in this field. */ struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; + /** + * @busy_stats: Has enablement of engine stats tracking been + * requested. + */ + bool busy_stats; + /** + * @disable_busy_stats: Work item for busy stats disabling. + * + * Same as with @enable_busy_stats action, with the difference + * that we delay it in case there are rapid enable-disable + * actions, which can happen during tool startup (like perf + * stat). + */ + struct delayed_work disable_busy_stats; } pmu; /* -- cgit From 0cd4684d6ea9a4ffec33fc19de4dd667bb90d0a5 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:50 +0000 Subject: drm/i915/pmu: Add interrupt count metric For clients like intel-gpu-overlay it is easier to read the count via the perf API than having to parse /proc. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-7-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 6a428e7218d2..fef389ebf92c 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -277,6 +277,22 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) return HRTIMER_RESTART; } +static u64 count_interrupts(struct drm_i915_private *i915) +{ + /* open-coded kstat_irqs() */ + struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq); + u64 sum = 0; + int cpu; + + if (!desc || !desc->kstat_irqs) + return 0; + + for_each_possible_cpu(cpu) + sum += *per_cpu_ptr(desc->kstat_irqs, cpu); + + return sum; +} + static void i915_pmu_event_destroy(struct perf_event *event) { WARN_ON(event->parent); @@ -343,6 +359,8 @@ static int i915_pmu_event_init(struct perf_event *event) if (INTEL_GEN(i915) < 6) ret = -ENODEV; break; + case I915_PMU_INTERRUPTS: + break; default: ret = -ENOENT; break; @@ -392,6 +410,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event) div_u64(i915->pmu.sample[__I915_SAMPLE_FREQ_REQ].cur, FREQUENCY); break; + case I915_PMU_INTERRUPTS: + val = count_interrupts(i915); + break; } } @@ -654,6 +675,8 @@ static struct attribute *i915_pmu_events_attrs[] = { I915_EVENT(actual-frequency, I915_PMU_ACTUAL_FREQUENCY, "MHz"), I915_EVENT(requested-frequency, I915_PMU_REQUESTED_FREQUENCY, "MHz"), + I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS), + NULL, }; -- cgit From 36cc8b963f5eb46352dc79d79e4bd5e8dd2ac2d6 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:51 +0000 Subject: drm/i915: Convert intel_rc6_residency_us to ns Will be used for exposing the PMU counters. v2: * Move intel_runtime_pm_get/put to the callers. (Chris Wilson) * Restore full unit conversion precision. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-8-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_drv.h | 8 +++++++- drivers/gpu/drm/i915/i915_sysfs.c | 9 +++++++-- drivers/gpu/drm/i915/intel_pm.c | 27 +++++++++++++-------------- 3 files changed, 27 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5bd5ac4cd03e..d575a56fc100 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -4228,11 +4228,17 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder, int intel_gpu_freq(struct drm_i915_private *dev_priv, int val); int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); -u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, +u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, const i915_reg_t reg); u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat1); +static inline u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, + const i915_reg_t reg) +{ + return DIV_ROUND_UP_ULL(intel_rc6_residency_ns(dev_priv, reg), 1000); +} + #define I915_READ8(reg) dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) #define I915_WRITE8(reg, val) dev_priv->uncore.funcs.mmio_writeb(dev_priv, (reg), (val), true) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 450ac7d343ad..c290cb600eea 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -42,8 +42,13 @@ static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) static u32 calc_residency(struct drm_i915_private *dev_priv, i915_reg_t reg) { - return DIV_ROUND_CLOSEST_ULL(intel_rc6_residency_us(dev_priv, reg), - 1000); + u64 res; + + intel_runtime_pm_get(dev_priv); + res = intel_rc6_residency_us(dev_priv, reg); + intel_runtime_pm_put(dev_priv); + + return DIV_ROUND_CLOSEST_ULL(res, 1000); } static ssize_t diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f1dc36c1fd69..7d41aad79166 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9437,36 +9437,35 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, return lower | (u64)upper << 8; } -u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, +u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, const i915_reg_t reg) { - u64 time_hw, units, div; + u64 time_hw; + u32 mul, div; if (!intel_rc6_enabled()) return 0; - intel_runtime_pm_get(dev_priv); - /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - units = 1000; + mul = 1000000; div = dev_priv->czclk_freq; - time_hw = vlv_residency_raw(dev_priv, reg); - } else if (IS_GEN9_LP(dev_priv)) { - units = 1000; - div = 1200; /* 833.33ns */ - time_hw = I915_READ(reg); } else { - units = 128000; /* 1.28us */ - div = 100000; + /* 833.33ns units on Gen9LP, 1.28us elsewhere. */ + if (IS_GEN9_LP(dev_priv)) { + mul = 10000; + div = 12; + } else { + mul = 1280; + div = 1; + } time_hw = I915_READ(reg); } - intel_runtime_pm_put(dev_priv); - return DIV_ROUND_UP_ULL(time_hw * units, div); + return DIV_ROUND_UP_ULL(time_hw * mul, div); } u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat) -- cgit From 6060b6aec03c76f9ce0977b70c27429d39d2956e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 21 Nov 2017 18:18:52 +0000 Subject: drm/i915/pmu: Add RC6 residency metrics For clients like intel-gpu-overlay it is easier to read the counters via the perf API than having to parse sysfs. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171121181852.16128-9-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index fef389ebf92c..1071935bfa67 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -361,6 +361,15 @@ static int i915_pmu_event_init(struct perf_event *event) break; case I915_PMU_INTERRUPTS: break; + case I915_PMU_RC6_RESIDENCY: + if (!HAS_RC6(i915)) + ret = -ENODEV; + break; + case I915_PMU_RC6p_RESIDENCY: + case I915_PMU_RC6pp_RESIDENCY: + if (!HAS_RC6p(i915)) + ret = -ENODEV; + break; default: ret = -ENOENT; break; @@ -413,6 +422,24 @@ static u64 __i915_pmu_event_read(struct perf_event *event) case I915_PMU_INTERRUPTS: val = count_interrupts(i915); break; + case I915_PMU_RC6_RESIDENCY: + intel_runtime_pm_get(i915); + val = intel_rc6_residency_ns(i915, + IS_VALLEYVIEW(i915) ? + VLV_GT_RENDER_RC6 : + GEN6_GT_GFX_RC6); + intel_runtime_pm_put(i915); + break; + case I915_PMU_RC6p_RESIDENCY: + intel_runtime_pm_get(i915); + val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); + intel_runtime_pm_put(i915); + break; + case I915_PMU_RC6pp_RESIDENCY: + intel_runtime_pm_get(i915); + val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); + intel_runtime_pm_put(i915); + break; } } @@ -677,6 +704,10 @@ static struct attribute *i915_pmu_events_attrs[] = { I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS), + I915_EVENT(rc6-residency, I915_PMU_RC6_RESIDENCY, "ns"), + I915_EVENT(rc6p-residency, I915_PMU_RC6p_RESIDENCY, "ns"), + I915_EVENT(rc6pp-residency, I915_PMU_RC6pp_RESIDENCY, "ns"), + NULL, }; -- cgit From c65c8b0f7a1f90e84c273e111fc9391c50c3c482 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 22 Nov 2017 12:06:00 +0000 Subject: drm/i915/selftests: Use NOWARN for large allocations We may try to do a large kmalloc for the permutation array, falling back to a smaller array/test if the first allocation fails. Since we are intentionally trying a large allocation which may fail, pass __GFP_NOWARN. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103842 Signed-off-by: Chris Wilson Cc: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20171122120600.27025-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/i915_random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/i915_random.c b/drivers/gpu/drm/i915/selftests/i915_random.c index b85872cc7fbe..2088ae57aa89 100644 --- a/drivers/gpu/drm/i915/selftests/i915_random.c +++ b/drivers/gpu/drm/i915/selftests/i915_random.c @@ -57,7 +57,7 @@ unsigned int *i915_random_order(unsigned int count, struct rnd_state *state) { unsigned int *order, i; - order = kmalloc_array(count, sizeof(*order), GFP_KERNEL); + order = kmalloc_array(count, sizeof(*order), GFP_KERNEL | __GFP_NOWARN); if (!order) return order; -- cgit From 62d0fe45297d213ba923e252dcdbcee6f41a3bc6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 22 Nov 2017 14:56:46 +0000 Subject: drm/i915: Remove success dmesg noise for intel_rotate_pages() During selftesting intel_rotate_pages() is very, very verbose without giving us any information. Suppress the noise. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20171122145646.1859-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem_gtt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e101b9a98957..41a203e0c160 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3737,9 +3737,6 @@ intel_rotate_pages(struct intel_rotation_info *rot_info, rot_info->plane[i].stride, st, sg); } - DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages)\n", - obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size); - kvfree(page_addr_list); return st; @@ -3749,8 +3746,8 @@ err_sg_alloc: err_st_alloc: kvfree(page_addr_list); - DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n", - obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size); + DRM_DEBUG_DRIVER("Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n", + obj->base.size, rot_info->plane[0].width, rot_info->plane[0].height, size); return ERR_PTR(ret); } -- cgit From ee48700dd57d9ce783ec40f035b324d0b75632e4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 22 Nov 2017 17:26:21 +0000 Subject: drm/i915: Call i915_gem_init_userptr() before taking struct_mutex We don't need struct_mutex to initialise userptr (it just allocates a workqueue for itself etc), but we do need struct_mutex later on in i915_gem_init() in order to feed requests onto the HW. This should break the chain [ 385.697902] ====================================================== [ 385.697907] WARNING: possible circular locking dependency detected [ 385.697913] 4.14.0-CI-Patchwork_7234+ #1 Tainted: G U [ 385.697917] ------------------------------------------------------ [ 385.697922] perf_pmu/2631 is trying to acquire lock: [ 385.697927] (&mm->mmap_sem){++++}, at: [] __might_fault+0x3e/0x90 [ 385.697941] but task is already holding lock: [ 385.697946] (&cpuctx_mutex){+.+.}, at: [] perf_event_ctx_lock_nested+0xbc/0x1d0 [ 385.697957] which lock already depends on the new lock. [ 385.697963] the existing dependency chain (in reverse order) is: [ 385.697970] -> #4 (&cpuctx_mutex){+.+.}: [ 385.697980] __mutex_lock+0x86/0x9b0 [ 385.697985] perf_event_init_cpu+0x5a/0x90 [ 385.697991] perf_event_init+0x178/0x1a4 [ 385.697997] start_kernel+0x27f/0x3f1 [ 385.698003] verify_cpu+0x0/0xfb [ 385.698006] -> #3 (pmus_lock){+.+.}: [ 385.698015] __mutex_lock+0x86/0x9b0 [ 385.698020] perf_event_init_cpu+0x21/0x90 [ 385.698025] cpuhp_invoke_callback+0xca/0xc00 [ 385.698030] _cpu_up+0xa7/0x170 [ 385.698035] do_cpu_up+0x57/0x70 [ 385.698039] smp_init+0x62/0xa6 [ 385.698044] kernel_init_freeable+0x97/0x193 [ 385.698050] kernel_init+0xa/0x100 [ 385.698055] ret_from_fork+0x27/0x40 [ 385.698058] -> #2 (cpu_hotplug_lock.rw_sem){++++}: [ 385.698068] cpus_read_lock+0x39/0xa0 [ 385.698073] apply_workqueue_attrs+0x12/0x50 [ 385.698078] __alloc_workqueue_key+0x1d8/0x4d8 [ 385.698134] i915_gem_init_userptr+0x5f/0x80 [i915] [ 385.698176] i915_gem_init+0x7c/0x390 [i915] [ 385.698213] i915_driver_load+0x99e/0x15c0 [i915] [ 385.698250] i915_pci_probe+0x33/0x90 [i915] [ 385.698256] pci_device_probe+0xa1/0x130 [ 385.698262] driver_probe_device+0x293/0x440 [ 385.698267] __driver_attach+0xde/0xe0 [ 385.698272] bus_for_each_dev+0x5c/0x90 [ 385.698277] bus_add_driver+0x16d/0x260 [ 385.698282] driver_register+0x57/0xc0 [ 385.698287] do_one_initcall+0x3e/0x160 [ 385.698292] do_init_module+0x5b/0x1fa [ 385.698297] load_module+0x2374/0x2dc0 [ 385.698302] SyS_finit_module+0xaa/0xe0 [ 385.698307] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 385.698311] -> #1 (&dev->struct_mutex){+.+.}: [ 385.698320] __mutex_lock+0x86/0x9b0 [ 385.698361] i915_mutex_lock_interruptible+0x4c/0x130 [i915] [ 385.698403] i915_gem_fault+0x206/0x760 [i915] [ 385.698409] __do_fault+0x1a/0x70 [ 385.698413] __handle_mm_fault+0x7c4/0xdb0 [ 385.698417] handle_mm_fault+0x154/0x300 [ 385.698440] __do_page_fault+0x2d6/0x570 [ 385.698445] page_fault+0x22/0x30 [ 385.698449] -> #0 (&mm->mmap_sem){++++}: [ 385.698459] lock_acquire+0xaf/0x200 [ 385.698464] __might_fault+0x68/0x90 [ 385.698470] _copy_to_user+0x1e/0x70 [ 385.698475] perf_read+0x1aa/0x290 [ 385.698480] __vfs_read+0x23/0x120 [ 385.698484] vfs_read+0xa3/0x150 [ 385.698488] SyS_read+0x45/0xb0 [ 385.698493] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 385.698497] other info that might help us debug this: [ 385.698505] Chain exists of: &mm->mmap_sem --> pmus_lock --> &cpuctx_mutex [ 385.698517] Possible unsafe locking scenario: [ 385.698522] CPU0 CPU1 [ 385.698526] ---- ---- [ 385.698529] lock(&cpuctx_mutex); [ 385.698553] lock(pmus_lock); [ 385.698558] lock(&cpuctx_mutex); [ 385.698564] lock(&mm->mmap_sem); [ 385.698568] *** DEADLOCK *** [ 385.698574] 1 lock held by perf_pmu/2631: [ 385.698578] #0: (&cpuctx_mutex){+.+.}, at: [] perf_event_ctx_lock_nested+0xbc/0x1d0 [ 385.698589] stack backtrace: [ 385.698595] CPU: 3 PID: 2631 Comm: perf_pmu Tainted: G U 4.14.0-CI-Patchwork_7234+ #1 [ 385.698602] Hardware name: /NUC6CAYB, BIOS AYAPLCEL.86A.0040.2017.0619.1722 06/19/2017 [ 385.698609] Call Trace: [ 385.698615] dump_stack+0x5f/0x86 [ 385.698621] print_circular_bug.isra.18+0x1d0/0x2c0 [ 385.698627] __lock_acquire+0x19c3/0x1b60 [ 385.698634] ? generic_exec_single+0x77/0xe0 [ 385.698640] ? lock_acquire+0xaf/0x200 [ 385.698644] lock_acquire+0xaf/0x200 [ 385.698650] ? __might_fault+0x3e/0x90 [ 385.698655] __might_fault+0x68/0x90 [ 385.698660] ? __might_fault+0x3e/0x90 [ 385.698665] _copy_to_user+0x1e/0x70 [ 385.698670] perf_read+0x1aa/0x290 [ 385.698675] __vfs_read+0x23/0x120 [ 385.698682] ? __fget+0x101/0x1f0 [ 385.698686] vfs_read+0xa3/0x150 [ 385.698691] SyS_read+0x45/0xb0 [ 385.698696] entry_SYSCALL_64_fastpath+0x1c/0xb1 [ 385.698701] RIP: 0033:0x7ff1c46876ed [ 385.698705] RSP: 002b:00007fff13552f90 EFLAGS: 00000293 ORIG_RAX: 0000000000000000 [ 385.698712] RAX: ffffffffffffffda RBX: ffffc90000647ff0 RCX: 00007ff1c46876ed [ 385.698718] RDX: 0000000000000010 RSI: 00007fff13552fa0 RDI: 0000000000000005 [ 385.698723] RBP: 000056063d300580 R08: 0000000000000000 R09: 0000000000000060 [ 385.698729] R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000000046 [ 385.698734] R13: 00007fff13552c6f R14: 00007ff1c6279d00 R15: 00007ff1c6279a40 Testcase: igt/perf_pmu Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20171122172621.16158-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_gem.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 21ca680e9e63..e03d6c2554e2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5116,8 +5116,6 @@ int i915_gem_init(struct drm_i915_private *dev_priv) { int ret; - mutex_lock(&dev_priv->drm.struct_mutex); - /* * We need to fallback to 4K pages since gvt gtt handling doesn't * support huge page entries - we will need to check either hypervisor @@ -5137,18 +5135,19 @@ int i915_gem_init(struct drm_i915_private *dev_priv) dev_priv->gt.cleanup_engine = intel_engine_cleanup; } + ret = i915_gem_init_userptr(dev_priv); + if (ret) + return ret; + /* This is just a security blanket to placate dragons. * On some systems, we very sporadically observe that the first TLBs * used by the CS may be stale, despite us poking the TLB reset. If * we hold the forcewake during initialisation these problems * just magically go away. */ + mutex_lock(&dev_priv->drm.struct_mutex); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - ret = i915_gem_init_userptr(dev_priv); - if (ret) - goto out_unlock; - ret = i915_gem_init_ggtt(dev_priv); if (ret) goto out_unlock; -- cgit From b4e3c935b2313b3e557066b630efd0367c7fb34c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 22 Nov 2017 22:25:10 +0000 Subject: drm/i915: Save/restore irq state for vlv_residency_raw() Since commit 6060b6aec03c ("drm/i915/pmu: Add RC6 residency metrics"), vlv_residency_raw() may be called from an irq-disabled context (via perf event sampling on remote cpu). As such, we can no longer assume that we are called from process context and must save/restore the irq state for the spinlock. Fixes: 6060b6aec03c ("drm/i915/pmu: Add RC6 residency metrics") Testcase: igt/perf_pmu/other-init-3 Signed-off-by: Chris Wilson Cc: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171122222510.22627-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7d41aad79166..03d67d8ab647 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9396,12 +9396,13 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, const i915_reg_t reg) { u32 lower, upper, tmp; + unsigned long flags; int loop = 2; /* The register accessed do not need forcewake. We borrow * uncore lock to prevent concurrent access to range reg. */ - spin_lock_irq(&dev_priv->uncore.lock); + spin_lock_irqsave(&dev_priv->uncore.lock, flags); /* vlv and chv residency counters are 40 bits in width. * With a control bit, we can choose between upper or lower @@ -9432,7 +9433,7 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, * now. */ - spin_unlock_irq(&dev_priv->uncore.lock); + spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); return lower | (u64)upper << 8; } @@ -9451,7 +9452,6 @@ u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, mul = 1000000; div = dev_priv->czclk_freq; time_hw = vlv_residency_raw(dev_priv, reg); - } else { /* 833.33ns units on Gen9LP, 1.28us elsewhere. */ if (IS_GEN9_LP(dev_priv)) { -- cgit From 4f0aa1fa3e3849caee450ee5d14fcc289cf16703 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Thu, 9 Nov 2017 10:51:43 -0800 Subject: drm/i915/dmc: DMC 1.04 for Kabylake There is a new version of DMC available for KBL. The release notes mentions: 1. Fix for the issue where DC_STATE was getting enabled even when disabled by driver causing data corruption. v2: Remove pull request from commit message (Rodrigo). Cc: Rodrigo Vivi Signed-off-by: Anusha Srivatsa Reviewed-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1510253503-12634-1-git-send-email-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/intel_csr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 77d8b3d483ca..07e4f7bc4412 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -40,9 +40,9 @@ #define I915_CSR_CNL "i915/cnl_dmc_ver1_06.bin" #define CNL_CSR_VERSION_REQUIRED CSR_VERSION(1, 6) -#define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin" +#define I915_CSR_KBL "i915/kbl_dmc_ver1_04.bin" MODULE_FIRMWARE(I915_CSR_KBL); -#define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 1) +#define KBL_CSR_VERSION_REQUIRED CSR_VERSION(1, 4) #define I915_CSR_SKL "i915/skl_dmc_ver1_26.bin" MODULE_FIRMWARE(I915_CSR_SKL); -- cgit From b552ae444e454eb3254c958e05b69820c0ef346d Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 23 Nov 2017 10:07:01 +0000 Subject: drm/i915/pmu: Drop I915_ENGINE_SAMPLE_MAX from uapi headers We have agreed during the engine classes discussion that fields marked as non-ABI are better left out altogether from uapi headers. v2: Use a local define for maintanability. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171123100701.18430-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 43473e6d1a4f..d38d059285dc 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -358,6 +358,7 @@ struct intel_engine_cs { * * Our internal timer stores the current counters in this field. */ +#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; /** * @busy_stats: Has enablement of engine stats tracking been -- cgit From fbba5559d91e812db0fd446fb383a37fde48b1cb Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 23 Nov 2017 10:26:54 +0000 Subject: drm/i915/pmu: Clear the previous sample value when parking When turning off the engines, and the pmu sampling, clear the previous value as the current measurement should be 0. v2: Use a for-loop v3: * Move clearing to timer self-dis-arm to avoid race with parking. * Clear frequency samples as well. v4: * Init frequency to idle_freq. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Reviewed-by: Chris Wilson (v3) Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171123102654.29296-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 1071935bfa67..6a42e7f7967d 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -262,13 +262,31 @@ static void frequency_sample(struct drm_i915_private *dev_priv) } } +static void pmu_init_previous_samples(struct drm_i915_private *i915) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; + unsigned int i; + + for_each_engine(engine, i915, id) { + for (i = 0; i < ARRAY_SIZE(engine->pmu.sample); i++) + engine->pmu.sample[i].prev = 0; + } + + for (i = 0; i < ARRAY_SIZE(i915->pmu.sample); i++) + i915->pmu.sample[i].prev = i915->gt_pm.rps.idle_freq; +} + static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) { struct drm_i915_private *i915 = container_of(hrtimer, struct drm_i915_private, pmu.timer); - if (!READ_ONCE(i915->pmu.timer_enabled)) + if (!READ_ONCE(i915->pmu.timer_enabled)) { + pmu_init_previous_samples(i915); + return HRTIMER_NORESTART; + } engines_sample(i915); frequency_sample(i915); @@ -839,6 +857,8 @@ void i915_pmu_register(struct drm_i915_private *i915) hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); i915->pmu.timer.function = i915_sample; + pmu_init_previous_samples(i915); + for_each_engine(engine, i915, id) INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats, __disable_busy_stats); -- cgit From 42e5e65765265485ecf2a480c244d76c2c624449 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 13 Nov 2017 17:01:40 +0100 Subject: drm/i915: sync dp link status checks against atomic commmits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bits: - check actual atomic state, the legacy stuff can only be looked at from within the atomic_commit_tail function, since it's only protected by ordering and not by any locks. - Make sure we don't wreak the work an ongoing nonblocking commit is doing. v2: We need the crtc lock too, because a plane update might change it without having to acquire the connection_mutex (Maarten). Use Maarten's changes for this locking, while keeping the logic that uses the connection->commit->hw_done signal for syncing with nonblocking commits. v3: The initial state objects from the hw state readout do not have a commit object. Check for that (spotted by CI). v4: Fix deadlock from jumping to put_power with locks still held. (mlankhorst) Cc: Manasi Navare Cc: Maarten Lankhorst Cc: Ville Syrjälä References: https://bugs.freedesktop.org/show_bug.cgi?id=103336 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99272 Signed-off-by: Daniel Vetter Signed-off-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171113160140.22679-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 61 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bc61f38b131d..dd0b3a018792 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4277,6 +4277,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; + struct drm_connector_state *conn_state = + intel_dp->attached_connector->base.state; u8 link_status[DP_LINK_STATUS_SIZE]; WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); @@ -4286,10 +4288,16 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) return; } - if (!intel_encoder->base.crtc) + if (!conn_state->crtc) return; - if (!to_intel_crtc(intel_encoder->base.crtc)->active) + WARN_ON(!drm_modeset_is_locked(&conn_state->crtc->mutex)); + + if (!conn_state->crtc->state->active) + return; + + if (conn_state->commit && + !try_wait_for_completion(&conn_state->commit->hw_done)) return; /* @@ -4364,9 +4372,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL); intel_dp_check_link_status(intel_dp); - drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); + if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { DRM_DEBUG_KMS("Link Training Compliance Test requested\n"); /* Send a Hotplug Uevent to userspace to start modeset */ @@ -4814,8 +4821,19 @@ intel_dp_detect(struct drm_connector *connector, connector->base.id, connector->name); /* If full detect is not performed yet, do a full detect */ - if (!intel_dp->detect_done) + if (!intel_dp->detect_done) { + struct drm_crtc *crtc; + int ret; + + crtc = connector->state->crtc; + if (crtc) { + ret = drm_modeset_lock(&crtc->mutex, ctx); + if (ret) + return ret; + } + status = intel_dp_long_pulse(intel_dp->attached_connector); + } intel_dp->detect_done = false; @@ -5097,7 +5115,38 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) } if (!intel_dp->is_mst) { - if (!intel_dp_short_pulse(intel_dp)) { + struct drm_modeset_acquire_ctx ctx; + struct drm_connector *connector = &intel_dp->attached_connector->base; + struct drm_crtc *crtc; + int iret; + bool handled = false; + + drm_modeset_acquire_init(&ctx, 0); +retry: + iret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, &ctx); + if (iret) + goto err; + + crtc = connector->state->crtc; + if (crtc) { + iret = drm_modeset_lock(&crtc->mutex, &ctx); + if (iret) + goto err; + } + + handled = intel_dp_short_pulse(intel_dp); + +err: + if (iret == -EDEADLK) { + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + WARN(iret, "Acquiring modeset locks failed with %i\n", iret); + + if (!handled) { intel_dp->detect_done = false; goto put_power; } -- cgit From 6a44e1772177ed9f987447bb6c601ee7451eeb52 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 21 Nov 2017 10:42:41 +0100 Subject: drm/i915: remove stale comment from sanitize_encoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This goes back to pre-atomic, where due to intermediate dpms states connectors and encoder states might indeed not have matched. With atomic that's all smashed together (and hopefully no bios ever enables a vga output in dpms standby/suspedn state or we're toast). In commit 873ffe69a9097fb241fff2967ea6f0bf2c179195 Author: Maarten Lankhorst Date: Wed Aug 5 12:37:07 2015 +0200 drm/i915: Remove connectors_active from sanitization, v2. sanitize_encoders was changed to disable the encoder in all cases, which made the comment obsolete. Remove the misleading comment. Reported-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Maarten Lankhorst Reviewed-by: Maarten Lankhorst Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171121094241.9129-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/intel_display.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5ca7b33554ef..fec267dfc062 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14909,8 +14909,6 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) connector->base.dpms = DRM_MODE_DPMS_OFF; connector->base.encoder = NULL; } - /* Enabled encoders without active connectors will be fixed in - * the crtc fixup. */ } void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv) -- cgit From 621d07b20eb8e7c47381178fc0f5724caa49afcd Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 23 Nov 2017 13:54:20 +0000 Subject: drm/i915/selftests: rein in igt_write_huge Rather than repeat the test for each engine, which takes a long time, let's try alternating between the engines in some randomized order. v2: fix gen2 blunder fix !order blunder more cunning permutation construction! Suggested-by: Chris Wilson Signed-off-by: Matthew Auld Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171123135421.17967-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/selftests/huge_pages.c | 111 +++++++++++++++++----------- 1 file changed, 66 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index db7a0a1f2960..83b3a27370a4 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -27,6 +27,7 @@ #include #include "mock_drm.h" +#include "i915_random.h" static const unsigned int page_sizes[] = { I915_GTT_PAGE_SIZE_2M, @@ -1044,7 +1045,10 @@ static int igt_write_huge(struct i915_gem_context *ctx, { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + static struct intel_engine_cs *engines[I915_NUM_ENGINES]; struct intel_engine_cs *engine; + I915_RND_STATE(prng); + IGT_TIMEOUT(end_time); struct i915_vma *vma; unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; unsigned int max_page_size; @@ -1052,6 +1056,8 @@ static int igt_write_huge(struct i915_gem_context *ctx, u64 max; u64 num; u64 size; + int *order; + int i, n; int err = 0; GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); @@ -1067,67 +1073,81 @@ static int igt_write_huge(struct i915_gem_context *ctx, if (IS_ERR(vma)) return PTR_ERR(vma); + n = 0; for_each_engine(engine, i915, id) { - IGT_TIMEOUT(end_time); - if (!intel_engine_can_store_dword(engine)) { - pr_info("store-dword-imm not supported on engine=%u\n", - id); + pr_info("store-dword-imm not supported on engine=%u\n", id); continue; } + engines[n++] = engine; + } - /* - * Try various offsets until we timeout -- we want to avoid - * issues hidden by effectively always using offset = 0. - */ - for_each_prime_number_from(num, 0, max) { - u64 offset = num * max_page_size; - u32 dword; + if (!n) + return 0; - err = i915_vma_unbind(vma); - if (err) - goto out_vma_close; + /* + * To keep things interesting when alternating between engines in our + * randomized order, lets also make feeding to the same engine a few + * times in succession a possibility by enlarging the permutation array. + */ + order = i915_random_order(n * I915_NUM_ENGINES, &prng); + if (!order) + return -ENOMEM; - err = i915_vma_pin(vma, size, max_page_size, flags | offset); - if (err) { - /* - * The ggtt may have some pages reserved so - * refrain from erroring out. - */ - if (err == -ENOSPC && i915_is_ggtt(vm)) { - err = 0; - continue; - } + /* + * Try various offsets until we timeout -- we want to avoid + * issues hidden by effectively always using offset = 0. + */ + i = 0; + for_each_prime_number_from(num, 0, max) { + u64 offset = num * max_page_size; + u32 dword; - goto out_vma_close; + err = i915_vma_unbind(vma); + if (err) + goto out_vma_close; + + err = i915_vma_pin(vma, size, max_page_size, flags | offset); + if (err) { + /* + * The ggtt may have some pages reserved so + * refrain from erroring out. + */ + if (err == -ENOSPC && i915_is_ggtt(vm)) { + err = 0; + continue; } - err = igt_check_page_sizes(vma); - if (err) - goto out_vma_unpin; + goto out_vma_close; + } - dword = offset_in_page(num) / 4; + err = igt_check_page_sizes(vma); + if (err) + goto out_vma_unpin; - err = gpu_write(vma, ctx, engine, dword, num + 1); - if (err) { - pr_err("gpu-write failed at offset=%llx", offset); - goto out_vma_unpin; - } + dword = offset_in_page(num) / 4; - err = cpu_check(obj, dword, num + 1); - if (err) { - pr_err("cpu-check failed at offset=%llx", offset); - goto out_vma_unpin; - } + engine = engines[order[i] % n]; + i = (i + 1) % (n * I915_NUM_ENGINES); - i915_vma_unpin(vma); + err = gpu_write(vma, ctx, engine, dword, num + 1); + if (err) { + pr_err("gpu-write failed at offset=%llx", offset); + goto out_vma_unpin; + } - if (num > 0 && - igt_timeout(end_time, - "%s timed out on engine=%u at offset=%llx, max_page_size=%x\n", - __func__, id, offset, max_page_size)) - break; + err = cpu_check(obj, dword, num + 1); + if (err) { + pr_err("cpu-check failed at offset=%llx", offset); + goto out_vma_unpin; } + + i915_vma_unpin(vma); + + if (igt_timeout(end_time, + "%s timed out on engine=%u at offset=%llx, max_page_size=%x\n", + __func__, engine->id, offset, max_page_size)) + break; } out_vma_unpin: @@ -1135,6 +1155,7 @@ out_vma_unpin: i915_vma_unpin(vma); out_vma_close: i915_vma_close(vma); + kfree(order); return err; } -- cgit From c83a8d4a2ec93c53f78e109dee5e21953485cbfd Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 23 Nov 2017 13:54:21 +0000 Subject: drm/i915/selftests: test descending addresses For igt_write_huge make sure the higher gtt offsets don't feel left out, which is especially true when dealing with the 48b PPGTT, where we timeout long before we are able exhaust the address space. v2: just use IGT_TIMEOUT Suggested-by: Chris Wilson Signed-off-by: Matthew Auld Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171123135421.17967-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/selftests/huge_pages.c | 123 ++++++++++++++++------------ 1 file changed, 70 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 83b3a27370a4..df1befe2c793 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -1040,6 +1040,62 @@ static int cpu_check(struct drm_i915_gem_object *obj, u32 dword, u32 val) return err; } +static int __igt_write_huge(struct i915_gem_context *ctx, + struct intel_engine_cs *engine, + struct drm_i915_gem_object *obj, + u64 size, u64 offset, + u32 dword, u32 val) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; + struct i915_vma *vma; + int err; + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + err = i915_vma_unbind(vma); + if (err) + goto out_vma_close; + + err = i915_vma_pin(vma, size, 0, flags | offset); + if (err) { + /* + * The ggtt may have some pages reserved so + * refrain from erroring out. + */ + if (err == -ENOSPC && i915_is_ggtt(vm)) + err = 0; + + goto out_vma_close; + } + + err = igt_check_page_sizes(vma); + if (err) + goto out_vma_unpin; + + err = gpu_write(vma, ctx, engine, dword, val); + if (err) { + pr_err("gpu-write failed at offset=%llx\n", offset); + goto out_vma_unpin; + } + + err = cpu_check(obj, dword, val); + if (err) { + pr_err("cpu-check failed at offset=%llx\n", offset); + goto out_vma_unpin; + } + +out_vma_unpin: + i915_vma_unpin(vma); +out_vma_close: + i915_vma_close(vma); + + return err; +} + static int igt_write_huge(struct i915_gem_context *ctx, struct drm_i915_gem_object *obj) { @@ -1049,8 +1105,6 @@ static int igt_write_huge(struct i915_gem_context *ctx, struct intel_engine_cs *engine; I915_RND_STATE(prng); IGT_TIMEOUT(end_time); - struct i915_vma *vma; - unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; unsigned int max_page_size; unsigned int id; u64 max; @@ -1069,10 +1123,6 @@ static int igt_write_huge(struct i915_gem_context *ctx, max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg); max = div_u64((vm->total - size), max_page_size); - vma = i915_vma_instance(obj, vm, NULL); - if (IS_ERR(vma)) - return PTR_ERR(vma); - n = 0; for_each_engine(engine, i915, id) { if (!intel_engine_can_store_dword(engine)) { @@ -1095,66 +1145,33 @@ static int igt_write_huge(struct i915_gem_context *ctx, return -ENOMEM; /* - * Try various offsets until we timeout -- we want to avoid - * issues hidden by effectively always using offset = 0. + * Try various offsets in an ascending/descending fashion until we + * timeout -- we want to avoid issues hidden by effectively always using + * offset = 0. */ i = 0; for_each_prime_number_from(num, 0, max) { - u64 offset = num * max_page_size; - u32 dword; - - err = i915_vma_unbind(vma); - if (err) - goto out_vma_close; - - err = i915_vma_pin(vma, size, max_page_size, flags | offset); - if (err) { - /* - * The ggtt may have some pages reserved so - * refrain from erroring out. - */ - if (err == -ENOSPC && i915_is_ggtt(vm)) { - err = 0; - continue; - } - - goto out_vma_close; - } - - err = igt_check_page_sizes(vma); - if (err) - goto out_vma_unpin; - - dword = offset_in_page(num) / 4; + u64 offset_low = num * max_page_size; + u64 offset_high = (max - num) * max_page_size; + u32 dword = offset_in_page(num) / 4; engine = engines[order[i] % n]; i = (i + 1) % (n * I915_NUM_ENGINES); - err = gpu_write(vma, ctx, engine, dword, num + 1); - if (err) { - pr_err("gpu-write failed at offset=%llx", offset); - goto out_vma_unpin; - } - - err = cpu_check(obj, dword, num + 1); - if (err) { - pr_err("cpu-check failed at offset=%llx", offset); - goto out_vma_unpin; - } + err = __igt_write_huge(ctx, engine, obj, size, offset_low, dword, num + 1); + if (err) + break; - i915_vma_unpin(vma); + err = __igt_write_huge(ctx, engine, obj, size, offset_high, dword, num + 1); + if (err) + break; if (igt_timeout(end_time, - "%s timed out on engine=%u at offset=%llx, max_page_size=%x\n", - __func__, engine->id, offset, max_page_size)) + "%s timed out on engine=%u, offset_low=%llx offset_high=%llx, max_page_size=%x\n", + __func__, engine->id, offset_low, offset_high, max_page_size)) break; } -out_vma_unpin: - if (i915_vma_is_pinned(vma)) - i915_vma_unpin(vma); -out_vma_close: - i915_vma_close(vma); kfree(order); return err; -- cgit From b1c24a6137af11fca49192a42face03cacbd7fc5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 15:26:30 +0000 Subject: drm/i915: Unwind incomplete legacy context switches The legacy context switch for ringbuffer submission is multistaged, where each of those stages may fail. However, we were updating global state after some stages, and so we had to force the incomplete request to be submitted because we could not unwind. Save the global state before performing the switches, and so enable us to unwind back to the previous global state should any phase fail. We then must cancel the request instead of submitting it should the construction fail. v2: s/saved_ctx/from_ctx/; s/ctx/to_ctx/ etc. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171123152631.31385-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 173 +++++++++++--------------------- drivers/gpu/drm/i915/i915_gem_request.c | 18 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 65 insertions(+), 128 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6ca56e482d79..da4a64b3484c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -507,6 +507,7 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) { engine->legacy_active_context = NULL; + engine->legacy_active_ppgtt = NULL; if (!engine->last_retired_context) continue; @@ -681,68 +682,49 @@ static int remap_l3(struct drm_i915_gem_request *req, int slice) return 0; } -static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt, - struct intel_engine_cs *engine, - struct i915_gem_context *to) -{ - if (to->remap_slice) - return false; - - if (ppgtt && (intel_engine_flag(engine) & ppgtt->pd_dirty_rings)) - return false; - - return to == engine->legacy_active_context; -} - -static bool -needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt, struct intel_engine_cs *engine) -{ - struct i915_gem_context *from = engine->legacy_active_context; - - if (!ppgtt) - return false; - - /* Always load the ppgtt on first use */ - if (!from) - return true; - - /* Same context without new entries, skip */ - if ((!from->ppgtt || from->ppgtt == ppgtt) && - !(intel_engine_flag(engine) & ppgtt->pd_dirty_rings)) - return false; - - if (engine->id != RCS) - return true; - - return true; -} - -static int do_rcs_switch(struct drm_i915_gem_request *req) +/** + * i915_switch_context() - perform a GPU context switch. + * @rq: request for which we'll execute the context switch + * + * The context life cycle is simple. The context refcount is incremented and + * decremented by 1 on create and destroy. If the context is in use by the GPU, + * it will have a refcount > 1. This allows us to destroy the context abstract + * object while letting the normal object tracking destroy the backing BO. + * + * This function should not be used in execlists mode. Instead the context is + * switched by writing to the ELSP and requests keep a reference to their + * context. + */ +int i915_switch_context(struct drm_i915_gem_request *rq) { - struct i915_gem_context *to = req->ctx; - struct intel_engine_cs *engine = req->engine; - struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt; - struct i915_gem_context *from = engine->legacy_active_context; - u32 hw_flags; + struct intel_engine_cs *engine = rq->engine; + struct i915_gem_context *to_ctx = rq->ctx; + struct i915_hw_ppgtt *to_mm = + to_ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; + struct i915_gem_context *from_ctx = engine->legacy_active_context; + struct i915_hw_ppgtt *from_mm = engine->legacy_active_ppgtt; + u32 hw_flags = 0; int ret, i; - GEM_BUG_ON(engine->id != RCS); + lockdep_assert_held(&rq->i915->drm.struct_mutex); + GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); - if (skip_rcs_switch(ppgtt, engine, to)) - return 0; - - if (needs_pd_load_pre(ppgtt, engine)) { - /* Older GENs and non render rings still want the load first, - * "PP_DCLV followed by PP_DIR_BASE register through Load - * Register Immediate commands in Ring Buffer before submitting - * a context."*/ - trace_switch_mm(engine, to); - ret = ppgtt->switch_mm(ppgtt, req); + if (to_mm != from_mm || + (to_mm && intel_engine_flag(engine) & to_mm->pd_dirty_rings)) { + trace_switch_mm(engine, to_ctx); + ret = to_mm->switch_mm(to_mm, rq); if (ret) - return ret; + goto err; + + to_mm->pd_dirty_rings &= ~intel_engine_flag(engine); + engine->legacy_active_ppgtt = to_mm; + hw_flags = MI_FORCE_RESTORE; } - if (i915_gem_context_is_kernel(to)) + if (to_ctx->engine[engine->id].state && + (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { + GEM_BUG_ON(engine->id != RCS); + /* * The kernel context(s) is treated as pure scratch and is not * expected to retain any state (as we sacrifice it during @@ -750,78 +732,37 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) * as nothing actually executes using the kernel context; it * is purely used for flushing user contexts. */ - hw_flags = MI_RESTORE_INHIBIT; - else if (ppgtt && intel_engine_flag(engine) & ppgtt->pd_dirty_rings) - hw_flags = MI_FORCE_RESTORE; - else - hw_flags = 0; + if (i915_gem_context_is_kernel(to_ctx)) + hw_flags = MI_RESTORE_INHIBIT; - if (to != from || (hw_flags & MI_FORCE_RESTORE)) { - ret = mi_set_context(req, hw_flags); + ret = mi_set_context(rq, hw_flags); if (ret) - return ret; + goto err_mm; - engine->legacy_active_context = to; + engine->legacy_active_context = to_ctx; } - if (ppgtt) - ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); + if (to_ctx->remap_slice) { + for (i = 0; i < MAX_L3_SLICES; i++) { + if (!(to_ctx->remap_slice & BIT(i))) + continue; - for (i = 0; i < MAX_L3_SLICES; i++) { - if (!(to->remap_slice & (1<remap_slice &= ~(1< 1. This allows us to destroy the context abstract - * object while letting the normal object tracking destroy the backing BO. - * - * This function should not be used in execlists mode. Instead the context is - * switched by writing to the ELSP and requests keep a reference to their - * context. - */ -int i915_switch_context(struct drm_i915_gem_request *req) -{ - struct intel_engine_cs *engine = req->engine; - - lockdep_assert_held(&req->i915->drm.struct_mutex); - GEM_BUG_ON(HAS_EXECLISTS(req->i915)); - - if (!req->ctx->engine[engine->id].state) { - struct i915_gem_context *to = req->ctx; - struct i915_hw_ppgtt *ppgtt = - to->ppgtt ?: req->i915->mm.aliasing_ppgtt; - - if (needs_pd_load_pre(ppgtt, engine)) { - int ret; - - trace_switch_mm(engine, to); - ret = ppgtt->switch_mm(ppgtt, req); + ret = remap_l3(rq, i); if (ret) - return ret; - - ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); + goto err_ctx; } - engine->legacy_active_context = to; - return 0; + to_ctx->remap_slice = 0; } - return do_rcs_switch(req); + return 0; + +err_ctx: + engine->legacy_active_context = from_ctx; +err_mm: + engine->legacy_active_ppgtt = from_mm; +err: + return ret; } static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 7325469ce754..a90bdd26571f 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -719,25 +719,19 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, /* Unconditionally invalidate GPU caches and TLBs. */ ret = engine->emit_flush(req, EMIT_INVALIDATE); if (ret) - goto err_ctx; + goto err_unwind; ret = engine->request_alloc(req); - if (ret) { - /* - * Past the point-of-no-return. Since we may have updated - * global state after partially completing the request alloc, - * we need to commit any commands so far emitted in the - * request to the HW. - */ - __i915_add_request(req, false); - return ERR_PTR(ret); - } + if (ret) + goto err_unwind; /* Check that we didn't interrupt ourselves with a new request */ GEM_BUG_ON(req->timeline->seqno != req->fence.seqno); return req; -err_ctx: +err_unwind: + req->ring->emit = req->head; + /* Make sure we didn't add ourselves to external state before freeing */ GEM_BUG_ON(!list_empty(&req->active_list)); GEM_BUG_ON(!list_empty(&req->priotree.signalers_list)); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index bfa11a84e476..a904b0353bec 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -591,6 +591,7 @@ static void reset_ring_common(struct intel_engine_cs *engine, request->ring->head = request->postfix; } else { engine->legacy_active_context = NULL; + engine->legacy_active_ppgtt = NULL; } } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index d38d059285dc..ef304c99954c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -531,6 +531,7 @@ struct intel_engine_cs { * stream (ring). */ struct i915_gem_context *legacy_active_context; + struct i915_hw_ppgtt *legacy_active_ppgtt; /* status_notifier: list of callbacks for context-switch changes */ struct atomic_notifier_head context_status_notifier; -- cgit From 8911a31c813275882fdc15554235a914e678759e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 15:26:31 +0000 Subject: drm/i915: Move mi_set_context() into the legacy ringbuffer submission The legacy i915_switch_context() is only applicable to the legacy ringbuffer submission method, so move it from the general i915_gem_context.c to intel_ringbuffer.c (rename pending!). Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171123152631.31385-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 198 -------------------------------- drivers/gpu/drm/i915/intel_ringbuffer.c | 186 +++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 199 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index da4a64b3484c..aee0f6d72d33 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -567,204 +567,6 @@ void i915_gem_context_close(struct drm_file *file) idr_destroy(&file_priv->context_idr); } -static inline int -mi_set_context(struct drm_i915_gem_request *req, u32 flags) -{ - struct drm_i915_private *dev_priv = req->i915; - struct intel_engine_cs *engine = req->engine; - enum intel_engine_id id; - const int num_rings = - /* Use an extended w/a on gen7 if signalling from other rings */ - (HAS_LEGACY_SEMAPHORES(dev_priv) && IS_GEN7(dev_priv)) ? - INTEL_INFO(dev_priv)->num_rings - 1 : - 0; - int len; - u32 *cs; - - flags |= MI_MM_SPACE_GTT; - if (IS_HASWELL(dev_priv)) - /* These flags are for resource streamer on HSW+ */ - flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN; - else - flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN; - - len = 4; - if (IS_GEN7(dev_priv)) - len += 2 + (num_rings ? 4*num_rings + 6 : 0); - - cs = intel_ring_begin(req, len); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ - if (IS_GEN7(dev_priv)) { - *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; - if (num_rings) { - struct intel_engine_cs *signaller; - - *cs++ = MI_LOAD_REGISTER_IMM(num_rings); - for_each_engine(signaller, dev_priv, id) { - if (signaller == engine) - continue; - - *cs++ = i915_mmio_reg_offset( - RING_PSMI_CTL(signaller->mmio_base)); - *cs++ = _MASKED_BIT_ENABLE( - GEN6_PSMI_SLEEP_MSG_DISABLE); - } - } - } - - *cs++ = MI_NOOP; - *cs++ = MI_SET_CONTEXT; - *cs++ = i915_ggtt_offset(req->ctx->engine[RCS].state) | flags; - /* - * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP - * WaMiSetContext_Hang:snb,ivb,vlv - */ - *cs++ = MI_NOOP; - - if (IS_GEN7(dev_priv)) { - if (num_rings) { - struct intel_engine_cs *signaller; - i915_reg_t last_reg = {}; /* keep gcc quiet */ - - *cs++ = MI_LOAD_REGISTER_IMM(num_rings); - for_each_engine(signaller, dev_priv, id) { - if (signaller == engine) - continue; - - last_reg = RING_PSMI_CTL(signaller->mmio_base); - *cs++ = i915_mmio_reg_offset(last_reg); - *cs++ = _MASKED_BIT_DISABLE( - GEN6_PSMI_SLEEP_MSG_DISABLE); - } - - /* Insert a delay before the next switch! */ - *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; - *cs++ = i915_mmio_reg_offset(last_reg); - *cs++ = i915_ggtt_offset(engine->scratch); - *cs++ = MI_NOOP; - } - *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; - } - - intel_ring_advance(req, cs); - - return 0; -} - -static int remap_l3(struct drm_i915_gem_request *req, int slice) -{ - u32 *cs, *remap_info = req->i915->l3_parity.remap_info[slice]; - int i; - - if (!remap_info) - return 0; - - cs = intel_ring_begin(req, GEN7_L3LOG_SIZE/4 * 2 + 2); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - /* - * Note: We do not worry about the concurrent register cacheline hang - * here because no other code should access these registers other than - * at initialization time. - */ - *cs++ = MI_LOAD_REGISTER_IMM(GEN7_L3LOG_SIZE/4); - for (i = 0; i < GEN7_L3LOG_SIZE/4; i++) { - *cs++ = i915_mmio_reg_offset(GEN7_L3LOG(slice, i)); - *cs++ = remap_info[i]; - } - *cs++ = MI_NOOP; - intel_ring_advance(req, cs); - - return 0; -} - -/** - * i915_switch_context() - perform a GPU context switch. - * @rq: request for which we'll execute the context switch - * - * The context life cycle is simple. The context refcount is incremented and - * decremented by 1 on create and destroy. If the context is in use by the GPU, - * it will have a refcount > 1. This allows us to destroy the context abstract - * object while letting the normal object tracking destroy the backing BO. - * - * This function should not be used in execlists mode. Instead the context is - * switched by writing to the ELSP and requests keep a reference to their - * context. - */ -int i915_switch_context(struct drm_i915_gem_request *rq) -{ - struct intel_engine_cs *engine = rq->engine; - struct i915_gem_context *to_ctx = rq->ctx; - struct i915_hw_ppgtt *to_mm = - to_ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; - struct i915_gem_context *from_ctx = engine->legacy_active_context; - struct i915_hw_ppgtt *from_mm = engine->legacy_active_ppgtt; - u32 hw_flags = 0; - int ret, i; - - lockdep_assert_held(&rq->i915->drm.struct_mutex); - GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); - - if (to_mm != from_mm || - (to_mm && intel_engine_flag(engine) & to_mm->pd_dirty_rings)) { - trace_switch_mm(engine, to_ctx); - ret = to_mm->switch_mm(to_mm, rq); - if (ret) - goto err; - - to_mm->pd_dirty_rings &= ~intel_engine_flag(engine); - engine->legacy_active_ppgtt = to_mm; - hw_flags = MI_FORCE_RESTORE; - } - - if (to_ctx->engine[engine->id].state && - (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { - GEM_BUG_ON(engine->id != RCS); - - /* - * The kernel context(s) is treated as pure scratch and is not - * expected to retain any state (as we sacrifice it during - * suspend and on resume it may be corrupted). This is ok, - * as nothing actually executes using the kernel context; it - * is purely used for flushing user contexts. - */ - if (i915_gem_context_is_kernel(to_ctx)) - hw_flags = MI_RESTORE_INHIBIT; - - ret = mi_set_context(rq, hw_flags); - if (ret) - goto err_mm; - - engine->legacy_active_context = to_ctx; - } - - if (to_ctx->remap_slice) { - for (i = 0; i < MAX_L3_SLICES; i++) { - if (!(to_ctx->remap_slice & BIT(i))) - continue; - - ret = remap_l3(rq, i); - if (ret) - goto err_ctx; - } - - to_ctx->remap_slice = 0; - } - - return 0; - -err_ctx: - engine->legacy_active_context = from_ctx; -err_mm: - engine->legacy_active_ppgtt = from_mm; -err: - return ret; -} - static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine) { struct i915_gem_timeline *timeline; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a904b0353bec..e2085820b586 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1385,6 +1385,190 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) intel_ring_reset(engine->buffer, 0); } +static inline int mi_set_context(struct drm_i915_gem_request *rq, u32 flags) +{ + struct drm_i915_private *i915 = rq->i915; + struct intel_engine_cs *engine = rq->engine; + enum intel_engine_id id; + const int num_rings = + /* Use an extended w/a on gen7 if signalling from other rings */ + (HAS_LEGACY_SEMAPHORES(i915) && IS_GEN7(i915)) ? + INTEL_INFO(i915)->num_rings - 1 : + 0; + int len; + u32 *cs; + + flags |= MI_MM_SPACE_GTT; + if (IS_HASWELL(i915)) + /* These flags are for resource streamer on HSW+ */ + flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN; + else + flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN; + + len = 4; + if (IS_GEN7(i915)) + len += 2 + (num_rings ? 4*num_rings + 6 : 0); + + cs = intel_ring_begin(rq, len); + if (IS_ERR(cs)) + return PTR_ERR(cs); + + /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ + if (IS_GEN7(i915)) { + *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; + if (num_rings) { + struct intel_engine_cs *signaller; + + *cs++ = MI_LOAD_REGISTER_IMM(num_rings); + for_each_engine(signaller, i915, id) { + if (signaller == engine) + continue; + + *cs++ = i915_mmio_reg_offset( + RING_PSMI_CTL(signaller->mmio_base)); + *cs++ = _MASKED_BIT_ENABLE( + GEN6_PSMI_SLEEP_MSG_DISABLE); + } + } + } + + *cs++ = MI_NOOP; + *cs++ = MI_SET_CONTEXT; + *cs++ = i915_ggtt_offset(rq->ctx->engine[RCS].state) | flags; + /* + * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP + * WaMiSetContext_Hang:snb,ivb,vlv + */ + *cs++ = MI_NOOP; + + if (IS_GEN7(i915)) { + if (num_rings) { + struct intel_engine_cs *signaller; + i915_reg_t last_reg = {}; /* keep gcc quiet */ + + *cs++ = MI_LOAD_REGISTER_IMM(num_rings); + for_each_engine(signaller, i915, id) { + if (signaller == engine) + continue; + + last_reg = RING_PSMI_CTL(signaller->mmio_base); + *cs++ = i915_mmio_reg_offset(last_reg); + *cs++ = _MASKED_BIT_DISABLE( + GEN6_PSMI_SLEEP_MSG_DISABLE); + } + + /* Insert a delay before the next switch! */ + *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; + *cs++ = i915_mmio_reg_offset(last_reg); + *cs++ = i915_ggtt_offset(engine->scratch); + *cs++ = MI_NOOP; + } + *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; + } + + intel_ring_advance(rq, cs); + + return 0; +} + +static int remap_l3(struct drm_i915_gem_request *rq, int slice) +{ + u32 *cs, *remap_info = rq->i915->l3_parity.remap_info[slice]; + int i; + + if (!remap_info) + return 0; + + cs = intel_ring_begin(rq, GEN7_L3LOG_SIZE/4 * 2 + 2); + if (IS_ERR(cs)) + return PTR_ERR(cs); + + /* + * Note: We do not worry about the concurrent register cacheline hang + * here because no other code should access these registers other than + * at initialization time. + */ + *cs++ = MI_LOAD_REGISTER_IMM(GEN7_L3LOG_SIZE/4); + for (i = 0; i < GEN7_L3LOG_SIZE/4; i++) { + *cs++ = i915_mmio_reg_offset(GEN7_L3LOG(slice, i)); + *cs++ = remap_info[i]; + } + *cs++ = MI_NOOP; + intel_ring_advance(rq, cs); + + return 0; +} + +static int switch_context(struct drm_i915_gem_request *rq) +{ + struct intel_engine_cs *engine = rq->engine; + struct i915_gem_context *to_ctx = rq->ctx; + struct i915_hw_ppgtt *to_mm = + to_ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt; + struct i915_gem_context *from_ctx = engine->legacy_active_context; + struct i915_hw_ppgtt *from_mm = engine->legacy_active_ppgtt; + u32 hw_flags = 0; + int ret, i; + + lockdep_assert_held(&rq->i915->drm.struct_mutex); + GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); + + if (to_mm != from_mm || + (to_mm && intel_engine_flag(engine) & to_mm->pd_dirty_rings)) { + trace_switch_mm(engine, to_ctx); + ret = to_mm->switch_mm(to_mm, rq); + if (ret) + goto err; + + to_mm->pd_dirty_rings &= ~intel_engine_flag(engine); + engine->legacy_active_ppgtt = to_mm; + hw_flags = MI_FORCE_RESTORE; + } + + if (to_ctx->engine[engine->id].state && + (to_ctx != from_ctx || hw_flags & MI_FORCE_RESTORE)) { + GEM_BUG_ON(engine->id != RCS); + + /* + * The kernel context(s) is treated as pure scratch and is not + * expected to retain any state (as we sacrifice it during + * suspend and on resume it may be corrupted). This is ok, + * as nothing actually executes using the kernel context; it + * is purely used for flushing user contexts. + */ + if (i915_gem_context_is_kernel(to_ctx)) + hw_flags = MI_RESTORE_INHIBIT; + + ret = mi_set_context(rq, hw_flags); + if (ret) + goto err_mm; + + engine->legacy_active_context = to_ctx; + } + + if (to_ctx->remap_slice) { + for (i = 0; i < MAX_L3_SLICES; i++) { + if (!(to_ctx->remap_slice & BIT(i))) + continue; + + ret = remap_l3(rq, i); + if (ret) + goto err_ctx; + } + + to_ctx->remap_slice = 0; + } + + return 0; + +err_ctx: + engine->legacy_active_context = from_ctx; +err_mm: + engine->legacy_active_ppgtt = from_mm; +err: + return ret; +} + static int ring_request_alloc(struct drm_i915_gem_request *request) { int ret; @@ -1401,7 +1585,7 @@ static int ring_request_alloc(struct drm_i915_gem_request *request) if (ret) return ret; - ret = i915_switch_context(request); + ret = switch_context(request); if (ret) return ret; -- cgit From b7d3aabf900728b6b13b860157026fd26099208a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 21:17:51 +0000 Subject: drm/i915/pmu: Hide the (unsigned long)ptr cast We pretend the PMU config id is a pointer value when encoding it into the device parameters for presentation via sysfs. This requires casting of an unsigned long into and out of the pointer member, which annoys smatch: drivers/gpu/drm/i915/i915_pmu.c:684 i915_pmu_event_show() warn: argument 3 to %lx specifier is cast from pointer Instead of abusing a generic dev_ext_attribute, define our own typesafe attributes. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20171123211751.2885-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_pmu.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 6a42e7f7967d..5170a46893d7 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -650,19 +650,24 @@ static int i915_pmu_event_event_idx(struct perf_event *event) return 0; } +struct i915_str_attribute { + struct device_attribute attr; + const char *str; +}; + static ssize_t i915_pmu_format_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *eattr; + struct i915_str_attribute *eattr; - eattr = container_of(attr, struct dev_ext_attribute, attr); - return sprintf(buf, "%s\n", (char *)eattr->var); + eattr = container_of(attr, struct i915_str_attribute, attr); + return sprintf(buf, "%s\n", eattr->str); } #define I915_PMU_FORMAT_ATTR(_name, _config) \ - (&((struct dev_ext_attribute[]) { \ + (&((struct i915_str_attribute[]) { \ { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \ - .var = (void *)_config, } \ + .str = _config, } \ })[0].attr.attr) static struct attribute *i915_pmu_format_attrs[] = { @@ -675,19 +680,24 @@ static const struct attribute_group i915_pmu_format_attr_group = { .attrs = i915_pmu_format_attrs, }; +struct i915_ext_attribute { + struct device_attribute attr; + unsigned long val; +}; + static ssize_t i915_pmu_event_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *eattr; + struct i915_ext_attribute *eattr; - eattr = container_of(attr, struct dev_ext_attribute, attr); - return sprintf(buf, "config=0x%lx\n", (unsigned long)eattr->var); + eattr = container_of(attr, struct i915_ext_attribute, attr); + return sprintf(buf, "config=0x%lx\n", eattr->val); } #define I915_EVENT_ATTR(_name, _config) \ - (&((struct dev_ext_attribute[]) { \ + (&((struct i915_ext_attribute[]) { \ { .attr = __ATTR(_name, 0444, i915_pmu_event_show, NULL), \ - .var = (void *)_config, } \ + .val = _config, } \ })[0].attr.attr) #define I915_EVENT_STR(_name, _str) \ -- cgit From e7e5da7127d5c9c076f05d6ed71bdf6826fc536c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 23:37:12 +0000 Subject: drm/i915/selftests: Hold rpm wakeref for request + ggtt usage Since the removal of the delayed rc6 enabling, we now setup and drop the early rpm wakeref during modules initialisation before we start the live selftests. As such, we are now detecting errors in the tests where we were not holding the required wakeref for various actions. As rpm is not the primary goal of the tests involved, take a coarse and convenient rpm wakeref around the tests. Signed-off-by: Chris Wilson Cc: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20171123233712.21836-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- drivers/gpu/drm/i915/selftests/huge_pages.c | 2 ++ drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index df1befe2c793..e6b31041cc88 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -1749,6 +1749,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv) return PTR_ERR(file); mutex_lock(&dev_priv->drm.struct_mutex); + intel_runtime_pm_get(dev_priv); ctx = live_context(dev_priv, file); if (IS_ERR(ctx)) { @@ -1759,6 +1760,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv) err = i915_subtests(tests, ctx); out_unlock: + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); mock_file_free(dev_priv, file); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index f463105ff48d..e1ddad635d73 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -355,6 +355,7 @@ static int igt_evict_contexts(void *arg) return 0; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); /* Reserve a block so that we know we have enough to fit a few rq */ memset(&hole, 0, sizeof(hole)); @@ -463,6 +464,7 @@ out_locked: } if (drm_mm_node_allocated(&hole)) drm_mm_remove_node(&hole); + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; -- cgit From 141a0895d5ad3d2540c3d08651f2b63443fb8dfd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 12:34:31 +0000 Subject: drm/i915/pmu: Remove conditional HOTPLUG_CPU registration Even for static CPU configurations, the hotplug CPU framework is still used to determine the CPU topology, and is still being used by the perf event register to check for valid CPUs. Fixes: b46a33e271ed ("drm/i915/pmu: Expose a PMU interface for perf queries") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Dmitry Rogozhkin Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20171123123432.25035-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 5170a46893d7..21006e8065a0 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -40,7 +40,7 @@ #define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS) -static cpumask_t i915_pmu_cpumask = CPU_MASK_NONE; +static cpumask_t i915_pmu_cpumask; static u8 engine_config_sample(u64 config) { @@ -770,7 +770,6 @@ static const struct attribute_group *i915_pmu_attr_groups[] = { NULL }; -#ifdef CONFIG_HOTPLUG_CPU static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) { struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); @@ -806,11 +805,9 @@ static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node) } static enum cpuhp_state cpuhp_slot = CPUHP_INVALID; -#endif static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915) { -#ifdef CONFIG_HOTPLUG_CPU enum cpuhp_state slot; int ret; @@ -829,17 +826,14 @@ static int i915_pmu_register_cpuhp_state(struct drm_i915_private *i915) } cpuhp_slot = slot; -#endif return 0; } static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915) { -#ifdef CONFIG_HOTPLUG_CPU WARN_ON(cpuhp_slot == CPUHP_INVALID); WARN_ON(cpuhp_state_remove_instance(cpuhp_slot, &i915->pmu.node)); cpuhp_remove_multi_state(cpuhp_slot); -#endif } void i915_pmu_register(struct drm_i915_private *i915) -- cgit From 0426c046546140fc42db5addeb7e2298dd0b6fb1 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 23 Nov 2017 12:34:32 +0000 Subject: drm/i915/pmu: Only allow running on a single CPU We do two things, both of which are purely to simplify and clarify the implementation: 1. Simplify the CPU online callback so it is more obvious that the purpose there is to set a single CPU mask bit for the first CPU which comes online. Using cpumask_weight for this reads more obvious than the trick with cpumask_and_any. 2. Modify the event init so that events can be created only on a single CPU. This removes looking at the requested CPU thread siblings, and only allows creating on the current active CPU. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Dmitry Rogozhkin Tested-by: Chris Wilson Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171123123432.25035-2-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 21006e8065a0..2b7a4779f184 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -344,7 +344,7 @@ static int i915_pmu_event_init(struct perf_event *event) { struct drm_i915_private *i915 = container_of(event->pmu, typeof(*i915), pmu.base); - int cpu, ret; + int ret; if (event->attr.type != event->pmu->type) return -ENOENT; @@ -359,9 +359,8 @@ static int i915_pmu_event_init(struct perf_event *event) if (event->cpu < 0) return -EINVAL; - cpu = cpumask_any_and(&i915_pmu_cpumask, - topology_sibling_cpumask(event->cpu)); - if (cpu >= nr_cpu_ids) + /* only allow running on one cpu at a time */ + if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask)) return -ENODEV; if (is_engine_event(event)) { @@ -396,7 +395,6 @@ static int i915_pmu_event_init(struct perf_event *event) if (ret) return ret; - event->cpu = cpu; if (!event->parent) event->destroy = i915_pmu_event_destroy; @@ -773,13 +771,11 @@ static const struct attribute_group *i915_pmu_attr_groups[] = { static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node) { struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), node); - unsigned int target; GEM_BUG_ON(!pmu->base.event_init); - target = cpumask_any_and(&i915_pmu_cpumask, &i915_pmu_cpumask); /* Select the first online CPU as a designated reader. */ - if (target >= nr_cpu_ids) + if (!cpumask_weight(&i915_pmu_cpumask)) cpumask_set_cpu(cpu, &i915_pmu_cpumask); return 0; -- cgit From 95c71769811cb3ca55ecbb9f6a7fc126a35c1500 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Fri, 24 Nov 2017 13:50:50 +0530 Subject: drm/i915/guc: Update header guard name of intel_guc_submission.h While renaming i915_guc_submission.h to intel_guc_submission.h, update of header guard name to _INTEL_GUC_SUBMISSION_H_ was missed. References: a269574489d4 (drm/i915/guc: Rename i915_guc_submission.c|h to intel_guc_submission.c|h) Signed-off-by: Sagar Arun Kamble Cc: Joonas Lahtinen Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/1511511650-13756-1-git-send-email-sagar.a.kamble@intel.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_guc_submission.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_submission.h b/drivers/gpu/drm/i915/intel_guc_submission.h index e901192ee469..021fe85c8f71 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.h +++ b/drivers/gpu/drm/i915/intel_guc_submission.h @@ -22,8 +22,8 @@ * */ -#ifndef _I915_GUC_SUBMISSION_H_ -#define _I915_GUC_SUBMISSION_H_ +#ifndef _INTEL_GUC_SUBMISSION_H_ +#define _INTEL_GUC_SUBMISSION_H_ #include -- cgit From 3e8f5b0805e5f93770e420e3f455b7d14d08173f Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 24 Nov 2017 09:53:40 +0000 Subject: drm/i915/guc: Rename i915_guc_reg.h to intel_guc_reg.h We are using intel_ prefix for all file names with hardware related definitions. GuC registers also fall into this category. Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Sagar Arun Kamble Reviewed-by: Sagar Arun Kamble Link: https://patchwork.freedesktop.org/patch/msgid/20171124095340.1500-1-michal.wajdeczko@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_guc_reg.h | 119 ----------------------------------- drivers/gpu/drm/i915/intel_guc.h | 2 +- drivers/gpu/drm/i915/intel_guc_reg.h | 119 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 120 deletions(-) delete mode 100644 drivers/gpu/drm/i915/i915_guc_reg.h create mode 100644 drivers/gpu/drm/i915/intel_guc_reg.h (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h deleted file mode 100644 index bc1ae7d8f424..000000000000 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - */ -#ifndef _I915_GUC_REG_H_ -#define _I915_GUC_REG_H_ - -/* Definitions of GuC H/W registers, bits, etc */ - -#define GUC_STATUS _MMIO(0xc000) -#define GS_RESET_SHIFT 0 -#define GS_MIA_IN_RESET (0x01 << GS_RESET_SHIFT) -#define GS_BOOTROM_SHIFT 1 -#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT) -#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT) -#define GS_BOOTROM_JUMP_PASSED (0x76 << GS_BOOTROM_SHIFT) -#define GS_UKERNEL_SHIFT 8 -#define GS_UKERNEL_MASK (0xFF << GS_UKERNEL_SHIFT) -#define GS_UKERNEL_LAPIC_DONE (0x30 << GS_UKERNEL_SHIFT) -#define GS_UKERNEL_DPC_ERROR (0x60 << GS_UKERNEL_SHIFT) -#define GS_UKERNEL_READY (0xF0 << GS_UKERNEL_SHIFT) -#define GS_MIA_SHIFT 16 -#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT) -#define GS_MIA_CORE_STATE (0x01 << GS_MIA_SHIFT) -#define GS_MIA_HALT_REQUESTED (0x02 << GS_MIA_SHIFT) -#define GS_MIA_ISR_ENTRY (0x04 << GS_MIA_SHIFT) -#define GS_AUTH_STATUS_SHIFT 30 -#define GS_AUTH_STATUS_MASK (0x03 << GS_AUTH_STATUS_SHIFT) -#define GS_AUTH_STATUS_BAD (0x01 << GS_AUTH_STATUS_SHIFT) -#define GS_AUTH_STATUS_GOOD (0x02 << GS_AUTH_STATUS_SHIFT) - -#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4) -#define SOFT_SCRATCH_COUNT 16 - -#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4) -#define UOS_RSA_SCRATCH_MAX_COUNT 64 -#define DMA_ADDR_0_LOW _MMIO(0xc300) -#define DMA_ADDR_0_HIGH _MMIO(0xc304) -#define DMA_ADDR_1_LOW _MMIO(0xc308) -#define DMA_ADDR_1_HIGH _MMIO(0xc30c) -#define DMA_ADDRESS_SPACE_WOPCM (7 << 16) -#define DMA_ADDRESS_SPACE_GTT (8 << 16) -#define DMA_COPY_SIZE _MMIO(0xc310) -#define DMA_CTRL _MMIO(0xc314) -#define HUC_UKERNEL (1<<9) -#define UOS_MOVE (1<<4) -#define START_DMA (1<<0) -#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) -#define HUC_LOADING_AGENT_VCR (0<<1) -#define HUC_LOADING_AGENT_GUC (1<<1) -#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ -#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) - -#define HUC_STATUS2 _MMIO(0xD3B0) -#define HUC_FW_VERIFIED (1<<7) - -/* Defines WOPCM space available to GuC firmware */ -#define GUC_WOPCM_SIZE _MMIO(0xc050) -/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ -#define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ -#define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ - -/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ -#define GUC_GGTT_TOP 0xFEE00000 - -#define GEN8_GT_PM_CONFIG _MMIO(0x138140) -#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) -#define GEN9_GT_PM_CONFIG _MMIO(0x13816c) -#define GT_DOORBELL_ENABLE (1<<0) - -#define GEN8_GTCR _MMIO(0x4274) -#define GEN8_GTCR_INVALIDATE (1<<0) - -#define GUC_ARAT_C6DIS _MMIO(0xA178) - -#define GUC_SHIM_CONTROL _MMIO(0xc064) -#define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0) -#define GUC_ENABLE_READ_CACHE_LOGIC (1<<1) -#define GUC_ENABLE_MIA_CACHING (1<<2) -#define GUC_GEN10_MSGCH_ENABLE (1<<4) -#define GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA (1<<9) -#define GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA (1<<10) -#define GUC_ENABLE_MIA_CLOCK_GATING (1<<15) -#define GUC_GEN10_SHIM_WC_ENABLE (1<<21) - -#define GUC_SEND_INTERRUPT _MMIO(0xc4c8) -#define GUC_SEND_TRIGGER (1<<0) - -#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8) -#define GEN8_DRB_VALID (1<<0) -#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4) - -#define DE_GUCRMR _MMIO(0x44054) - -#define GUC_BCS_RCS_IER _MMIO(0xC550) -#define GUC_VCS2_VCS1_IER _MMIO(0xC554) -#define GUC_WD_VECS_IER _MMIO(0xC558) -#define GUC_PM_P24C_IER _MMIO(0xC55C) - -#endif diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index 75c4cfefdaff..59856726d2bc 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -30,8 +30,8 @@ #include "intel_guc_fwif.h" #include "intel_guc_ct.h" #include "intel_guc_log.h" +#include "intel_guc_reg.h" #include "intel_uc_fw.h" -#include "i915_guc_reg.h" #include "i915_vma.h" struct guc_preempt_work { diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h new file mode 100644 index 000000000000..0a8ff03d026f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc_reg.h @@ -0,0 +1,119 @@ +/* + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ +#ifndef _INTEL_GUC_REG_H_ +#define _INTEL_GUC_REG_H_ + +/* Definitions of GuC H/W registers, bits, etc */ + +#define GUC_STATUS _MMIO(0xc000) +#define GS_RESET_SHIFT 0 +#define GS_MIA_IN_RESET (0x01 << GS_RESET_SHIFT) +#define GS_BOOTROM_SHIFT 1 +#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT) +#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT) +#define GS_BOOTROM_JUMP_PASSED (0x76 << GS_BOOTROM_SHIFT) +#define GS_UKERNEL_SHIFT 8 +#define GS_UKERNEL_MASK (0xFF << GS_UKERNEL_SHIFT) +#define GS_UKERNEL_LAPIC_DONE (0x30 << GS_UKERNEL_SHIFT) +#define GS_UKERNEL_DPC_ERROR (0x60 << GS_UKERNEL_SHIFT) +#define GS_UKERNEL_READY (0xF0 << GS_UKERNEL_SHIFT) +#define GS_MIA_SHIFT 16 +#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT) +#define GS_MIA_CORE_STATE (0x01 << GS_MIA_SHIFT) +#define GS_MIA_HALT_REQUESTED (0x02 << GS_MIA_SHIFT) +#define GS_MIA_ISR_ENTRY (0x04 << GS_MIA_SHIFT) +#define GS_AUTH_STATUS_SHIFT 30 +#define GS_AUTH_STATUS_MASK (0x03 << GS_AUTH_STATUS_SHIFT) +#define GS_AUTH_STATUS_BAD (0x01 << GS_AUTH_STATUS_SHIFT) +#define GS_AUTH_STATUS_GOOD (0x02 << GS_AUTH_STATUS_SHIFT) + +#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4) +#define SOFT_SCRATCH_COUNT 16 + +#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4) +#define UOS_RSA_SCRATCH_MAX_COUNT 64 +#define DMA_ADDR_0_LOW _MMIO(0xc300) +#define DMA_ADDR_0_HIGH _MMIO(0xc304) +#define DMA_ADDR_1_LOW _MMIO(0xc308) +#define DMA_ADDR_1_HIGH _MMIO(0xc30c) +#define DMA_ADDRESS_SPACE_WOPCM (7 << 16) +#define DMA_ADDRESS_SPACE_GTT (8 << 16) +#define DMA_COPY_SIZE _MMIO(0xc310) +#define DMA_CTRL _MMIO(0xc314) +#define HUC_UKERNEL (1<<9) +#define UOS_MOVE (1<<4) +#define START_DMA (1<<0) +#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340) +#define HUC_LOADING_AGENT_VCR (0<<1) +#define HUC_LOADING_AGENT_GUC (1<<1) +#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ +#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4) + +#define HUC_STATUS2 _MMIO(0xD3B0) +#define HUC_FW_VERIFIED (1<<7) + +/* Defines WOPCM space available to GuC firmware */ +#define GUC_WOPCM_SIZE _MMIO(0xc050) +/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */ +#define GUC_WOPCM_TOP (0x80 << 12) /* 512KB */ +#define BXT_GUC_WOPCM_RC6_RESERVED (0x10 << 12) /* 64KB */ + +/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */ +#define GUC_GGTT_TOP 0xFEE00000 + +#define GEN8_GT_PM_CONFIG _MMIO(0x138140) +#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140) +#define GEN9_GT_PM_CONFIG _MMIO(0x13816c) +#define GT_DOORBELL_ENABLE (1<<0) + +#define GEN8_GTCR _MMIO(0x4274) +#define GEN8_GTCR_INVALIDATE (1<<0) + +#define GUC_ARAT_C6DIS _MMIO(0xA178) + +#define GUC_SHIM_CONTROL _MMIO(0xc064) +#define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0) +#define GUC_ENABLE_READ_CACHE_LOGIC (1<<1) +#define GUC_ENABLE_MIA_CACHING (1<<2) +#define GUC_GEN10_MSGCH_ENABLE (1<<4) +#define GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA (1<<9) +#define GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA (1<<10) +#define GUC_ENABLE_MIA_CLOCK_GATING (1<<15) +#define GUC_GEN10_SHIM_WC_ENABLE (1<<21) + +#define GUC_SEND_INTERRUPT _MMIO(0xc4c8) +#define GUC_SEND_TRIGGER (1<<0) + +#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8) +#define GEN8_DRB_VALID (1<<0) +#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4) + +#define DE_GUCRMR _MMIO(0x44054) + +#define GUC_BCS_RCS_IER _MMIO(0xC550) +#define GUC_VCS2_VCS1_IER _MMIO(0xC554) +#define GUC_WD_VECS_IER _MMIO(0xC558) +#define GUC_PM_P24C_IER _MMIO(0xC55C) + +#endif -- cgit From 1b2b659141cfa7c96c62c79516662a34ad112284 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 12 Oct 2017 10:21:47 +0100 Subject: drm/i915: Select DEBUG_FS for our test suite Ensure that we build our test kernels with DEBUG_FS enabled as many of our igt tests require poking around debugfs/dri. This should also fixup the kbuild complaint that we tried to select SW_SYNC without meeting its dependencies. Reported-by: kbuild-all@01.org Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171012092147.28986-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 9e53edbc713b..fa36491495b1 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -18,6 +18,7 @@ config DRM_I915_WERROR config DRM_I915_DEBUG bool "Enable additional driver debugging" depends on DRM_I915 + select DEBUG_FS select PREEMPT_COUNT select I2C_CHARDEV select DRM_DP_AUX_CHARDEV -- cgit From 8ee4f19c47031f23340055da4d9f2af537de23f4 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 24 Nov 2017 09:49:59 +0000 Subject: drm/i915/pmu: Stop averaging with the previous sample Averaging with the previous sample brings a small statistical improvement to sampling counters, but can leek a little bit of state from a current client to the next which mulls the border between past and present for observing clients. This is because on event enable clients record the current counter value and use it as reference, but with rapid off-on event cycles, and due the delayed nature of sampling timer self-disarm, previous sample value does not get cleared under these circumstances. Solution is to stop averaging with the previous sample. This has a small downside of losing some precision with short and spiky signals, but the alternatives look too complicated for the benefit. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Sagar Arun Kamble Reviewed-by: Chris Wilson Tested-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171124094959.10725-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 29 ++--------------------------- drivers/gpu/drm/i915/i915_pmu.h | 1 - 2 files changed, 2 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 2b7a4779f184..39310cf13c3a 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -181,12 +181,7 @@ static bool grab_forcewake(struct drm_i915_private *i915, bool fw) static void update_sample(struct i915_pmu_sample *sample, u32 unit, u32 val) { - /* - * Since we are doing stochastic sampling for these counters, - * average the delta with the previous value for better accuracy. - */ - sample->cur += div_u64(mul_u32_u32(sample->prev + val, unit), 2); - sample->prev = val; + sample->cur += mul_u32_u32(val, unit); } static void engines_sample(struct drm_i915_private *dev_priv) @@ -262,31 +257,13 @@ static void frequency_sample(struct drm_i915_private *dev_priv) } } -static void pmu_init_previous_samples(struct drm_i915_private *i915) -{ - struct intel_engine_cs *engine; - enum intel_engine_id id; - unsigned int i; - - for_each_engine(engine, i915, id) { - for (i = 0; i < ARRAY_SIZE(engine->pmu.sample); i++) - engine->pmu.sample[i].prev = 0; - } - - for (i = 0; i < ARRAY_SIZE(i915->pmu.sample); i++) - i915->pmu.sample[i].prev = i915->gt_pm.rps.idle_freq; -} - static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) { struct drm_i915_private *i915 = container_of(hrtimer, struct drm_i915_private, pmu.timer); - if (!READ_ONCE(i915->pmu.timer_enabled)) { - pmu_init_previous_samples(i915); - + if (!READ_ONCE(i915->pmu.timer_enabled)) return HRTIMER_NORESTART; - } engines_sample(i915); frequency_sample(i915); @@ -857,8 +834,6 @@ void i915_pmu_register(struct drm_i915_private *i915) hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); i915->pmu.timer.function = i915_sample; - pmu_init_previous_samples(i915); - for_each_engine(engine, i915, id) INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats, __disable_busy_stats); diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index e209783a4c5f..40c154d13565 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -41,7 +41,6 @@ enum { struct i915_pmu_sample { u64 cur; - u32 prev; }; struct i915_pmu { -- cgit From c4deb62d7821672265b87952bcd1c808f3bf3e8f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 23 Nov 2017 21:41:56 +0200 Subject: drm/i915: Don't try indexed reads to alternate slave addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can only specify the one slave address to indexed reads/writes. Make sure the messages we check are destined to the same slave address before deciding to do an indexed transfer. Cc: stable@vger.kernel.org Cc: Daniel Kurtz Cc: Chris Wilson Cc: Daniel Vetter Cc: Sean Paul Fixes: 56f9eac05489 ("drm/i915/intel_i2c: use INDEX cycles for i2c read transactions") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171123194157.25367-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_i2c.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index eb5827110d8f..8affd47b98b8 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -438,6 +438,7 @@ static bool gmbus_is_index_read(struct i2c_msg *msgs, int i, int num) { return (i + 1 < num && + msgs[i].addr == msgs[i + 1].addr && !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 && (msgs[i + 1].flags & I2C_M_RD)); } -- cgit From bb9e0d4bca50f429152e74a459160b41f3d60fb2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 23 Nov 2017 21:41:57 +0200 Subject: drm/i915: Prevent zero length "index" write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware always writes one or two bytes in the index portion of an indexed transfer. Make sure the message we send as the index doesn't have a zero length. Cc: stable@vger.kernel.org Cc: Daniel Kurtz Cc: Chris Wilson Cc: Daniel Vetter Cc: Sean Paul Fixes: 56f9eac05489 ("drm/i915/intel_i2c: use INDEX cycles for i2c read transactions") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171123194157.25367-3-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_i2c.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 8affd47b98b8..49fdf09f9919 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -439,7 +439,8 @@ gmbus_is_index_read(struct i2c_msg *msgs, int i, int num) { return (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && - !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 && + !(msgs[i].flags & I2C_M_RD) && + (msgs[i].len == 1 || msgs[i].len == 2) && (msgs[i + 1].flags & I2C_M_RD)); } -- cgit From aa34a6fc2722f042e372741661c0fae8640245ac Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 24 Nov 2017 13:37:44 +0000 Subject: drm/i915/guc: Advance over port[0] if set and not preempting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our execlist emulation is intended to only use a maximum of 2 ports per engine, so as to not overflow the wq. (By knowing the limits, we can avoid having to handle the wq exhaustion.) However, upon adding preemption, we lost the skip over the first port if set for the non-preemption path. Restore it. Reported-by: Mika Kuoppala Fixes: c41937fd994a ("drm/i915/guc: Preemption! With GuC") Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171124133745.5173-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala Reviewed-by: Michał Winiarski --- drivers/gpu/drm/i915/intel_guc_submission.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index cbf5a96f5806..70e64bdb73dd 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -743,23 +743,26 @@ static void guc_dequeue(struct intel_engine_cs *engine) if (!rb) goto unlock; - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && port_isset(port)) { - struct guc_preempt_work *preempt_work = - &engine->i915->guc.preempt_work[engine->id]; - - if (rb_entry(rb, struct i915_priolist, node)->priority > - max(port_request(port)->priotree.priority, 0)) { - execlists_set_active(execlists, - EXECLISTS_ACTIVE_PREEMPT); - queue_work(engine->i915->guc.preempt_wq, - &preempt_work->work); - goto unlock; - } else if (port_isset(last_port)) { - goto unlock; + if (port_isset(port)) { + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { + struct guc_preempt_work *preempt_work = + &engine->i915->guc.preempt_work[engine->id]; + + if (rb_entry(rb, struct i915_priolist, node)->priority > + max(port_request(port)->priotree.priority, 0)) { + execlists_set_active(execlists, + EXECLISTS_ACTIVE_PREEMPT); + queue_work(engine->i915->guc.preempt_wq, + &preempt_work->work); + goto unlock; + } } port++; + if (port_isset(port)) + goto unlock; } + GEM_BUG_ON(port_isset(port)); do { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); -- cgit From 8c5da3bbcfd9cf763623f2d9515ace8eb3f01307 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 24 Nov 2017 13:00:29 +0000 Subject: drm/i915/guc: Tidy ELSP port assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we know that the port is empty, we do not need to extract the count from the old request it and copy it over to the new request, or attempt to unref the NULL old request pointer. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Michał Winiarski Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20171124130031.20761-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_guc_submission.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 70e64bdb73dd..cf1cc2cb6722 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -718,12 +718,9 @@ static void guc_submit(struct intel_engine_cs *engine) static void port_assign(struct execlist_port *port, struct drm_i915_gem_request *rq) { - GEM_BUG_ON(rq == port_request(port)); - - if (port_isset(port)) - i915_gem_request_put(port_request(port)); + GEM_BUG_ON(port_isset(port)); - port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); + port_set(port, i915_gem_request_get(rq)); } static void guc_dequeue(struct intel_engine_cs *engine) -- cgit From a54b1873c0e3ffec3041cf72cb10d986d6bc4fe5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 24 Nov 2017 13:00:30 +0000 Subject: drm/i915: Use exponential backoff for wait_for() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of sleeping for a fixed 1ms (roughly, depending on timer slack), start with a small sleep and exponentially increase the sleep on each cycle. A good example of a beneficiary is the guc mmio communication channel. Typically we expect (and so spin) for 10us for a quick response, but this doesn't cover everything and so sometimes we fallback to the millisecond+ sleep. This incurs a significant delay in time-critical operations like preemption (igt/gem_exec_latency), which can be improved significantly by using a small sleep after the spin fails. We've made this suggestion many times, but had little experimental data to support adding the complexity. v2: Bump the minimum usleep to 10us on advice of Documentation/timers/timers-howto.txt (Tvrko) v3: Specify min, max range for usleep intervals -- some code may crucially depend upon and so want to specify the sleep pattern. References: 1758b90e38f5 ("drm/i915: Use a hybrid scheme for fast register waits") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: John Harrison Cc: Michał Winiarski Cc: Ville Syrjala Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20171124130031.20761-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_drv.h | 11 +++++++---- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 635a96fcd788..c00441a3d649 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -48,8 +48,9 @@ * having timed out, since the timeout could be due to preemption or similar and * we've never had a chance to check the condition before the timeout. */ -#define _wait_for(COND, US, W) ({ \ +#define _wait_for(COND, US, Wmin, Wmax) ({ \ unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ + long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ int ret__; \ might_sleep(); \ for (;;) { \ @@ -62,12 +63,14 @@ ret__ = -ETIMEDOUT; \ break; \ } \ - usleep_range((W), (W) * 2); \ + usleep_range(wait__, wait__ * 2); \ + if (wait__ < (Wmax)) \ + wait__ <<= 1; \ } \ ret__; \ }) -#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 1000) +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ #if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) @@ -116,7 +119,7 @@ int ret__; \ BUILD_BUG_ON(!__builtin_constant_p(US)); \ if ((US) > 10) \ - ret__ = _wait_for((COND), (US), 10); \ + ret__ = _wait_for((COND), (US), 10, 10); \ else \ ret__ = _wait_for_atomic((COND), (US), 0); \ ret__; \ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 03d67d8ab647..a80c322c5b43 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9294,7 +9294,7 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request, ret = 0; goto out; } - ret = _wait_for(COND, timeout_base_ms * 1000, 10); + ret = _wait_for(COND, timeout_base_ms * 1000, 10, 10); if (!ret) goto out; -- cgit From 3452fa3095e91acbcb1f6290e0d70fa7d3695a3a Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 24 Nov 2017 17:13:31 +0000 Subject: drm/i915/pmu: Aggregate all RC6 states into one counter Chris has discovered that RC6, RC6p and RC6pp counters are mutually exclusive, and even that on some SNB SKUs you get RC6p increasing, and on the others RC6. Furthermore RC6p and RC6pp were only present starting from GEN6 until, GEN7, not including Haswell. All this combined makes it questionable whether we need to reserve new ABI for these counters. One idea was to just combine them all under the RC6 counter to simplify things for userspace. So that is what this patch does. Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171124171331.17981-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 39310cf13c3a..3357b690ce90 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -359,11 +359,6 @@ static int i915_pmu_event_init(struct perf_event *event) if (!HAS_RC6(i915)) ret = -ENODEV; break; - case I915_PMU_RC6p_RESIDENCY: - case I915_PMU_RC6pp_RESIDENCY: - if (!HAS_RC6p(i915)) - ret = -ENODEV; - break; default: ret = -ENOENT; break; @@ -421,16 +416,12 @@ static u64 __i915_pmu_event_read(struct perf_event *event) IS_VALLEYVIEW(i915) ? VLV_GT_RENDER_RC6 : GEN6_GT_GFX_RC6); - intel_runtime_pm_put(i915); - break; - case I915_PMU_RC6p_RESIDENCY: - intel_runtime_pm_get(i915); - val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); - intel_runtime_pm_put(i915); - break; - case I915_PMU_RC6pp_RESIDENCY: - intel_runtime_pm_get(i915); - val = intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); + if (HAS_RC6p(i915)) { + val += intel_rc6_residency_ns(i915, + GEN6_GT_GFX_RC6p); + val += intel_rc6_residency_ns(i915, + GEN6_GT_GFX_RC6pp); + } intel_runtime_pm_put(i915); break; } @@ -708,8 +699,6 @@ static struct attribute *i915_pmu_events_attrs[] = { I915_EVENT_ATTR(interrupts, I915_PMU_INTERRUPTS), I915_EVENT(rc6-residency, I915_PMU_RC6_RESIDENCY, "ns"), - I915_EVENT(rc6p-residency, I915_PMU_RC6p_RESIDENCY, "ns"), - I915_EVENT(rc6pp-residency, I915_PMU_RC6pp_RESIDENCY, "ns"), NULL, }; -- cgit From 53fa54a6ef4fa5a261468d13dc0f54739adaa456 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Fri, 24 Nov 2017 17:02:39 +0000 Subject: drm/i915/guc: Use consistent name for scratch register count We should be consistent on naming of similar definitions. Signed-off-by: Michal Wajdeczko Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Sagar Arun Kamble Link: https://patchwork.freedesktop.org/patch/msgid/20171124170239.29360-1-michal.wajdeczko@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/intel_guc_fw.c | 4 ++-- drivers/gpu/drm/i915/intel_guc_reg.h | 3 ++- drivers/gpu/drm/i915/intel_uc_fw.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index 69ba01599575..bbab4e1106f3 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -130,14 +130,14 @@ static int guc_xfer_rsa(struct intel_guc *guc, struct i915_vma *vma) struct drm_i915_private *dev_priv = guc_to_i915(guc); struct intel_uc_fw *guc_fw = &guc->fw; struct sg_table *sg = vma->pages; - u32 rsa[UOS_RSA_SCRATCH_MAX_COUNT]; + u32 rsa[UOS_RSA_SCRATCH_COUNT]; int i; if (sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), guc_fw->rsa_offset) != sizeof(rsa)) return -EINVAL; - for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++) + for (i = 0; i < UOS_RSA_SCRATCH_COUNT; i++) I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]); return 0; diff --git a/drivers/gpu/drm/i915/intel_guc_reg.h b/drivers/gpu/drm/i915/intel_guc_reg.h index 0a8ff03d026f..19a9247c5664 100644 --- a/drivers/gpu/drm/i915/intel_guc_reg.h +++ b/drivers/gpu/drm/i915/intel_guc_reg.h @@ -52,7 +52,8 @@ #define SOFT_SCRATCH_COUNT 16 #define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4) -#define UOS_RSA_SCRATCH_MAX_COUNT 64 +#define UOS_RSA_SCRATCH_COUNT 64 + #define DMA_ADDR_0_LOW _MMIO(0xc300) #define DMA_ADDR_0_HIGH _MMIO(0xc304) #define DMA_ADDR_1_LOW _MMIO(0xc308) diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c index 4bc82d3005ff..b376dd3b28cc 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/intel_uc_fw.c @@ -105,7 +105,7 @@ void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, } /* now RSA */ - if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { + if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) { DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n", intel_uc_fw_type_repr(uc_fw->type), css->key_size_dw); err = -ENOEXEC; -- cgit From ad88d7fc6c032ddfb32b8d496a070ab71de3a64f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 25 Nov 2017 19:41:55 +0000 Subject: drm/i915/fbdev: Serialise early hotplug events with async fbdev config As both the hotplug event and fbdev configuration run asynchronously, it is possible for them to run concurrently. If configuration fails, we were freeing the fbdev causing a use-after-free in the hotplug event. <7>[ 3069.935211] [drm:intel_fb_initial_config [i915]] Not using firmware configuration <7>[ 3069.935225] [drm:drm_setup_crtcs] looking for cmdline mode on connector 77 <7>[ 3069.935229] [drm:drm_setup_crtcs] looking for preferred mode on connector 77 0 <7>[ 3069.935233] [drm:drm_setup_crtcs] found mode 3200x1800 <7>[ 3069.935236] [drm:drm_setup_crtcs] picking CRTCs for 8192x8192 config <7>[ 3069.935253] [drm:drm_setup_crtcs] desired mode 3200x1800 set on crtc 43 (0,0) <7>[ 3069.935323] [drm:intelfb_create [i915]] no BIOS fb, allocating a new one <4>[ 3069.967737] general protection fault: 0000 [#1] PREEMPT SMP <0>[ 3069.977453] --------------------------------- <4>[ 3069.977457] Modules linked in: i915(+) vgem snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm r8169 mei_me mii prime_numbers mei i2c_hid pinctrl_geminilake pinctrl_intel [last unloaded: i915] <4>[ 3069.977492] CPU: 1 PID: 15414 Comm: kworker/1:0 Tainted: G U 4.14.0-CI-CI_DRM_3388+ #1 <4>[ 3069.977497] Hardware name: Intel Corp. Geminilake/GLK RVP1 DDR4 (05), BIOS GELKRVPA.X64.0062.B30.1708222146 08/22/2017 <4>[ 3069.977508] Workqueue: events output_poll_execute <4>[ 3069.977512] task: ffff880177734e40 task.stack: ffffc90001fe4000 <4>[ 3069.977519] RIP: 0010:__lock_acquire+0x109/0x1b60 <4>[ 3069.977523] RSP: 0018:ffffc90001fe7bb0 EFLAGS: 00010002 <4>[ 3069.977526] RAX: 6b6b6b6b6b6b6b6b RBX: 0000000000000282 RCX: 0000000000000000 <4>[ 3069.977530] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880170d4efd0 <4>[ 3069.977534] RBP: ffffc90001fe7c70 R08: 0000000000000001 R09: 0000000000000000 <4>[ 3069.977538] R10: 0000000000000000 R11: ffffffff81899609 R12: ffff880170d4efd0 <4>[ 3069.977542] R13: ffff880177734e40 R14: 0000000000000001 R15: 0000000000000000 <4>[ 3069.977547] FS: 0000000000000000(0000) GS:ffff88017fc80000(0000) knlGS:0000000000000000 <4>[ 3069.977551] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 3069.977555] CR2: 00007f7e8b7bcf04 CR3: 0000000003e0f000 CR4: 00000000003406e0 <4>[ 3069.977559] Call Trace: <4>[ 3069.977565] ? mark_held_locks+0x64/0x90 <4>[ 3069.977571] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977575] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977579] ? trace_hardirqs_on_caller+0xde/0x1c0 <4>[ 3069.977583] ? _raw_spin_unlock_irq+0x2f/0x50 <4>[ 3069.977588] ? finish_task_switch+0xa5/0x210 <4>[ 3069.977592] ? lock_acquire+0xaf/0x200 <4>[ 3069.977596] lock_acquire+0xaf/0x200 <4>[ 3069.977600] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977604] _raw_spin_lock+0x2a/0x40 <4>[ 3069.977608] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977612] __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977616] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977621] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977625] drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977630] output_poll_execute+0x8d/0x180 <4>[ 3069.977635] process_one_work+0x22e/0x660 <4>[ 3069.977640] worker_thread+0x48/0x3a0 <4>[ 3069.977644] ? _raw_spin_unlock_irqrestore+0x4c/0x60 <4>[ 3069.977649] kthread+0x102/0x140 <4>[ 3069.977653] ? process_one_work+0x660/0x660 <4>[ 3069.977657] ? kthread_create_on_node+0x40/0x40 <4>[ 3069.977662] ret_from_fork+0x27/0x40 <4>[ 3069.977666] Code: 8d 62 f8 c3 49 81 3c 24 e0 fa 3c 82 41 be 00 00 00 00 45 0f 45 f0 83 fe 01 77 86 89 f0 49 8b 44 c4 08 48 85 c0 0f 84 76 ff ff ff ff 80 38 01 00 00 8b 1d 62 f9 e8 01 45 8b 85 b8 08 00 00 85 <1>[ 3069.977707] RIP: __lock_acquire+0x109/0x1b60 RSP: ffffc90001fe7bb0 <4>[ 3069.977712] ---[ end trace 4ad012eb3af62df7 ]--- In order to keep the dev_priv->ifbdev alive after failure, we have to avoid the free and leave it empty until we unload the module (which is less than ideal, but a necessary evil for simplicity). Then we can use intel_fbdev_sync() to serialise the hotplug event with the configuration. The serialisation between the two was removed in commit 934458c2c95d ("Revert "drm/i915: Fix races on fbdev""), but the use after free is much older, commit 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 934458c2c95d ("Revert "drm/i915: Fix races on fbdev"") Signed-off-by: Chris Wilson Cc: Lukas Wunner Cc: Joonas Lahtinen Cc: Daniel Vetter Cc: stable@vger.kernel.org Reviewed-by: Lukas Wunner Link: https://patchwork.freedesktop.org/patch/msgid/20171125194155.355-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_fbdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index b8af35187d22..ea96682568e8 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -697,10 +697,8 @@ static void intel_fbdev_initial_config(void *data, async_cookie_t cookie) /* Due to peculiar init order wrt to hpd handling this is separate. */ if (drm_fb_helper_initial_config(&ifbdev->helper, - ifbdev->preferred_bpp)) { + ifbdev->preferred_bpp)) intel_fbdev_unregister(to_i915(ifbdev->helper.dev)); - intel_fbdev_fini(to_i915(ifbdev->helper.dev)); - } } void intel_fbdev_initial_config_async(struct drm_device *dev) @@ -800,7 +798,11 @@ void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; - if (ifbdev) + if (!ifbdev) + return; + + intel_fbdev_sync(ifbdev); + if (ifbdev->vma) drm_fb_helper_hotplug_event(&ifbdev->helper); } -- cgit From 2de2d0b063b08becb2c67a2c338c44e37bdcffee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2017 16:10:27 +0100 Subject: drm/i915: fix intel_backlight_device_register declaration The alternative intel_backlight_device_register() definition apparently never got used, but I have now run into a case of i915 being compiled without CONFIG_BACKLIGHT_CLASS_DEVICE, resulting in a number of identical warnings: drivers/gpu/drm/i915/intel_drv.h:1739:12: error: 'intel_backlight_device_register' defined but not used [-Werror=unused-function] This marks the function as 'inline', which was surely the original intention here. Fixes: 1ebaa0b9c2d4 ("drm/i915: Move backlight registration to connector registration") Signed-off-by: Arnd Bergmann Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171127151239.1813673-1-arnd@arndb.de --- drivers/gpu/drm/i915/intel_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c00441a3d649..c679df99d530 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1750,7 +1750,7 @@ extern struct drm_display_mode *intel_find_panel_downclock( int intel_backlight_device_register(struct intel_connector *connector); void intel_backlight_device_unregister(struct intel_connector *connector); #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ -static int intel_backlight_device_register(struct intel_connector *connector) +static inline int intel_backlight_device_register(struct intel_connector *connector) { return 0; } -- cgit From fd94d53e55bd487368dfee9f1af24da78b2bb582 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Nov 2017 16:10:28 +0100 Subject: drm/i915: hide unused intel_panel_set_backlight function Building i915 without backlight support results in a harmless warning for intel_panel_set_backlight: drivers/gpu/drm/i915/intel_panel.c:653:13: error: 'intel_panel_set_backlight' defined but not used [-Werror=unused-function] This moves it into the CONFIG_BACKLIGHT_CLASS_DEVICE section that its caller is in. Signed-off-by: Arnd Bergmann Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20171127151239.1813673-2-arnd@arndb.de --- drivers/gpu/drm/i915/intel_panel.c | 88 +++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index adc51e452e3e..fa6831f8c004 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -543,25 +543,6 @@ static u32 pwm_get_backlight(struct intel_connector *connector) return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); } -static u32 intel_panel_get_backlight(struct intel_connector *connector) -{ - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_panel *panel = &connector->panel; - u32 val = 0; - - mutex_lock(&dev_priv->backlight_lock); - - if (panel->backlight.enabled) { - val = panel->backlight.get(connector); - val = intel_panel_compute_brightness(connector, val); - } - - mutex_unlock(&dev_priv->backlight_lock); - - DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); - return val; -} - static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); @@ -649,31 +630,6 @@ intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state, panel->backlight.set(conn_state, level); } -/* set backlight brightness to level in range [0..max], scaling wrt hw min */ -static void intel_panel_set_backlight(const struct drm_connector_state *conn_state, - u32 user_level, u32 user_max) -{ - struct intel_connector *connector = to_intel_connector(conn_state->connector); - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_panel *panel = &connector->panel; - u32 hw_level; - - if (!panel->backlight.present) - return; - - mutex_lock(&dev_priv->backlight_lock); - - WARN_ON(panel->backlight.max == 0); - - hw_level = scale_user_to_hw(connector, user_level, user_max); - panel->backlight.level = hw_level; - - if (panel->backlight.enabled) - intel_panel_actually_set_backlight(conn_state, hw_level); - - mutex_unlock(&dev_priv->backlight_lock); -} - /* set backlight brightness to level in range [0..max], assuming hw min is * respected. */ @@ -1182,6 +1138,50 @@ void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, } #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +static u32 intel_panel_get_backlight(struct intel_connector *connector) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; + u32 val = 0; + + mutex_lock(&dev_priv->backlight_lock); + + if (panel->backlight.enabled) { + val = panel->backlight.get(connector); + val = intel_panel_compute_brightness(connector, val); + } + + mutex_unlock(&dev_priv->backlight_lock); + + DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); + return val; +} + +/* set backlight brightness to level in range [0..max], scaling wrt hw min */ +static void intel_panel_set_backlight(const struct drm_connector_state *conn_state, + u32 user_level, u32 user_max) +{ + struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; + u32 hw_level; + + if (!panel->backlight.present) + return; + + mutex_lock(&dev_priv->backlight_lock); + + WARN_ON(panel->backlight.max == 0); + + hw_level = scale_user_to_hw(connector, user_level, user_max); + panel->backlight.level = hw_level; + + if (panel->backlight.enabled) + intel_panel_actually_set_backlight(conn_state, hw_level); + + mutex_unlock(&dev_priv->backlight_lock); +} + static int intel_backlight_device_update_status(struct backlight_device *bd) { struct intel_connector *connector = bl_get_data(bd); -- cgit From c82297fcfaff2862686094061772070e6763e00c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 26 Nov 2017 21:48:56 +0000 Subject: drm/i915: Flush everything on switching to the kernel_context Even though all rendering should have been flushed at the end of the previous requests, add an extra flush after switching to the kernel_context. As the switch to the kernel_context is used when idling the gpu (e.g. suspend), having an extra layer of paranoia to ensure everything is flushed to memory seems sensible. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171126214856.23702-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_context.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index aee0f6d72d33..ce3139e5ec4c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -620,7 +620,14 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) GFP_KERNEL); } - i915_add_request(req); + /* + * Force a flush after the switch to ensure that all rendering + * and operations prior to switching to the kernel context hits + * memory. This should be guaranteed by the previous request, + * but an extra layer of paranoia before we declare the system + * idle (on suspend etc) is advisable! + */ + __i915_add_request(req, true); } return 0; -- cgit From 4e90a6e222720dd0ec529f87eca990c736ba8ede Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 26 Nov 2017 22:09:01 +0000 Subject: drm/i915: Record default HW state in the GPU error state It may be of interest to both compare the active HW context against the default (aka NULL) context, to see what has been changed and if either are corrupt. v2: Rename the fake vma as fake. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20171126220901.14735-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d575a56fc100..50a945d3c11d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1009,6 +1009,7 @@ struct i915_gpu_state { long user_bo_count; struct drm_i915_error_object *wa_ctx; + struct drm_i915_error_object *default_state; struct drm_i915_error_request { long jiffies; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3d18d67d065f..876be8f1d930 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -791,6 +791,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, print_error_obj(m, dev_priv->engine[i], "WA batchbuffer", ee->wa_batchbuffer); + + print_error_obj(m, dev_priv->engine[i], + "NULL context", ee->default_state); } if (error->overlay) @@ -1414,6 +1417,23 @@ static void request_record_user_bo(struct drm_i915_gem_request *request, ee->user_bo_count = count; } +static struct drm_i915_error_object * +capture_object(struct drm_i915_private *dev_priv, + struct drm_i915_gem_object *obj) +{ + if (obj && i915_gem_object_has_pages(obj)) { + struct i915_vma fake = { + .node = { .start = U64_MAX, .size = obj->base.size }, + .pages = obj->mm.pages, + .obj = obj, + }; + + return i915_error_object_create(dev_priv, &fake); + } else { + return NULL; + } +} + static void i915_gem_record_rings(struct drm_i915_private *dev_priv, struct i915_gpu_state *error) { @@ -1485,6 +1505,9 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, ee->wa_ctx = i915_error_object_create(dev_priv, engine->wa_ctx.vma); + + ee->default_state = + capture_object(dev_priv, engine->default_state); } } -- cgit From 848b365d5d1f0d41d07773c6a69149b2561f29de Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 11:53:37 +0000 Subject: drm/i915: Rename shrinker init/cleanup to match driver initialisation phase Since the shrinker is registered and unregistered during i915_driver_register and i915_driver_unregister, respectively, rename the init/cleanup functions to match. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171123115338.10270-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_gem_shrinker.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0793a27e2b95..9c519aa4f550 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1215,7 +1215,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; - i915_gem_shrinker_init(dev_priv); + i915_gem_shrinker_register(dev_priv); i915_pmu_register(dev_priv); /* @@ -1277,7 +1277,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) i915_guc_log_unregister(dev_priv); drm_dev_unregister(&dev_priv->drm); - i915_gem_shrinker_cleanup(dev_priv); + i915_gem_shrinker_unregister(dev_priv); } /** diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 50a945d3c11d..2dd32de47f9a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3921,8 +3921,8 @@ unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv, #define I915_SHRINK_ACTIVE 0x8 #define I915_SHRINK_VMAPS 0x10 unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv); -void i915_gem_shrinker_init(struct drm_i915_private *dev_priv); -void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv); +void i915_gem_shrinker_register(struct drm_i915_private *dev_priv); +void i915_gem_shrinker_unregister(struct drm_i915_private *dev_priv); /* i915_gem_tiling.c */ diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 3770e3323fc8..7205dc123d92 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -494,12 +494,12 @@ out: } /** - * i915_gem_shrinker_init - Initialize i915 shrinker + * i915_gem_shrinker_register - Register the i915 shrinker * @dev_priv: i915 device * * This function registers and sets up the i915 shrinker and OOM handler. */ -void i915_gem_shrinker_init(struct drm_i915_private *dev_priv) +void i915_gem_shrinker_register(struct drm_i915_private *dev_priv) { dev_priv->mm.shrinker.scan_objects = i915_gem_shrinker_scan; dev_priv->mm.shrinker.count_objects = i915_gem_shrinker_count; @@ -515,12 +515,12 @@ void i915_gem_shrinker_init(struct drm_i915_private *dev_priv) } /** - * i915_gem_shrinker_cleanup - Clean up i915 shrinker + * i915_gem_shrinker_unregister - Unregisters the i915 shrinker * @dev_priv: i915 device * * This function unregisters the i915 shrinker and OOM handler. */ -void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv) +void i915_gem_shrinker_unregister(struct drm_i915_private *dev_priv) { WARN_ON(unregister_vmap_purge_notifier(&dev_priv->mm.vmap_notifier)); WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); -- cgit From 56fa4bf2b2f08405739a9166f306ceaea421447f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Nov 2017 11:53:38 +0000 Subject: drm/i915: Update shrinker drm_i915_private naming convention Switch over from the non-descript dev_priv locals to i915. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171123115338.10270-2-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 8 +- drivers/gpu/drm/i915/i915_gem_shrinker.c | 134 +++++++++++++++---------------- 2 files changed, 71 insertions(+), 71 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2dd32de47f9a..bddd65839f60 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3911,7 +3911,7 @@ i915_gem_object_create_internal(struct drm_i915_private *dev_priv, phys_addr_t size); /* i915_gem_shrinker.c */ -unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv, +unsigned long i915_gem_shrink(struct drm_i915_private *i915, unsigned long target, unsigned long *nr_scanned, unsigned flags); @@ -3920,9 +3920,9 @@ unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv, #define I915_SHRINK_BOUND 0x4 #define I915_SHRINK_ACTIVE 0x8 #define I915_SHRINK_VMAPS 0x10 -unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv); -void i915_gem_shrinker_register(struct drm_i915_private *dev_priv); -void i915_gem_shrinker_unregister(struct drm_i915_private *dev_priv); +unsigned long i915_gem_shrink_all(struct drm_i915_private *i915); +void i915_gem_shrinker_register(struct drm_i915_private *i915); +void i915_gem_shrinker_unregister(struct drm_i915_private *i915); /* i915_gem_tiling.c */ diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 7205dc123d92..9029ed04879c 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -35,9 +35,9 @@ #include "i915_drv.h" #include "i915_trace.h" -static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock) +static bool shrinker_lock(struct drm_i915_private *i915, bool *unlock) { - switch (mutex_trylock_recursive(&dev_priv->drm.struct_mutex)) { + switch (mutex_trylock_recursive(&i915->drm.struct_mutex)) { case MUTEX_TRYLOCK_RECURSIVE: *unlock = false; return true; @@ -47,7 +47,7 @@ static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock) preempt_disable(); do { cpu_relax(); - if (mutex_trylock(&dev_priv->drm.struct_mutex)) { + if (mutex_trylock(&i915->drm.struct_mutex)) { *unlock = true; break; } @@ -63,12 +63,12 @@ static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock) BUG(); } -static void shrinker_unlock(struct drm_i915_private *dev_priv, bool unlock) +static void shrinker_unlock(struct drm_i915_private *i915, bool unlock) { if (!unlock) return; - mutex_unlock(&dev_priv->drm.struct_mutex); + mutex_unlock(&i915->drm.struct_mutex); } static bool swap_available(void) @@ -118,7 +118,7 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) /** * i915_gem_shrink - Shrink buffer object caches - * @dev_priv: i915 device + * @i915: i915 device * @target: amount of memory to make available, in pages * @nr_scanned: optional output for number of pages scanned (incremental) * @flags: control flags for selecting cache types @@ -142,7 +142,7 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) * The number of pages of backing storage actually released. */ unsigned long -i915_gem_shrink(struct drm_i915_private *dev_priv, +i915_gem_shrink(struct drm_i915_private *i915, unsigned long target, unsigned long *nr_scanned, unsigned flags) @@ -151,15 +151,15 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, struct list_head *list; unsigned int bit; } phases[] = { - { &dev_priv->mm.unbound_list, I915_SHRINK_UNBOUND }, - { &dev_priv->mm.bound_list, I915_SHRINK_BOUND }, + { &i915->mm.unbound_list, I915_SHRINK_UNBOUND }, + { &i915->mm.bound_list, I915_SHRINK_BOUND }, { NULL, 0 }, }, *phase; unsigned long count = 0; unsigned long scanned = 0; bool unlock; - if (!shrinker_lock(dev_priv, &unlock)) + if (!shrinker_lock(i915, &unlock)) return 0; /* @@ -172,10 +172,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, * we will free as much as we can and hope to get a second chance. */ if (flags & I915_SHRINK_ACTIVE) - i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); + i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED); - trace_i915_gem_shrink(dev_priv, target, flags); - i915_gem_retire_requests(dev_priv); + trace_i915_gem_shrink(i915, target, flags); + i915_gem_retire_requests(i915); /* * Unbinding of objects will require HW access; Let us not wake the @@ -183,7 +183,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, * we will force the wake during oom-notifier. */ if ((flags & I915_SHRINK_BOUND) && - !intel_runtime_pm_get_if_in_use(dev_priv)) + !intel_runtime_pm_get_if_in_use(i915)) flags &= ~I915_SHRINK_BOUND; /* @@ -221,7 +221,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, * to be able to shrink their pages, so they remain on * the unbound/bound list until actually freed. */ - spin_lock(&dev_priv->mm.obj_lock); + spin_lock(&i915->mm.obj_lock); while (count < target && (obj = list_first_entry_or_null(phase->list, typeof(*obj), @@ -244,7 +244,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if (!can_release_pages(obj)) continue; - spin_unlock(&dev_priv->mm.obj_lock); + spin_unlock(&i915->mm.obj_lock); if (unsafe_drop_pages(obj)) { /* May arrive from get_pages on another bo */ @@ -258,18 +258,18 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, } scanned += obj->base.size >> PAGE_SHIFT; - spin_lock(&dev_priv->mm.obj_lock); + spin_lock(&i915->mm.obj_lock); } list_splice_tail(&still_in_list, phase->list); - spin_unlock(&dev_priv->mm.obj_lock); + spin_unlock(&i915->mm.obj_lock); } if (flags & I915_SHRINK_BOUND) - intel_runtime_pm_put(dev_priv); + intel_runtime_pm_put(i915); - i915_gem_retire_requests(dev_priv); + i915_gem_retire_requests(i915); - shrinker_unlock(dev_priv, unlock); + shrinker_unlock(i915, unlock); if (nr_scanned) *nr_scanned += scanned; @@ -278,7 +278,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, /** * i915_gem_shrink_all - Shrink buffer object caches completely - * @dev_priv: i915 device + * @i915: i915 device * * This is a simple wraper around i915_gem_shrink() to aggressively shrink all * caches completely. It also first waits for and retires all outstanding @@ -290,16 +290,16 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, * Returns: * The number of pages of backing storage actually released. */ -unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) +unsigned long i915_gem_shrink_all(struct drm_i915_private *i915) { unsigned long freed; - intel_runtime_pm_get(dev_priv); - freed = i915_gem_shrink(dev_priv, -1UL, NULL, + intel_runtime_pm_get(i915); + freed = i915_gem_shrink(i915, -1UL, NULL, I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_ACTIVE); - intel_runtime_pm_put(dev_priv); + intel_runtime_pm_put(i915); return freed; } @@ -347,53 +347,53 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) static unsigned long i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) { - struct drm_i915_private *dev_priv = + struct drm_i915_private *i915 = container_of(shrinker, struct drm_i915_private, mm.shrinker); unsigned long freed; bool unlock; sc->nr_scanned = 0; - if (!shrinker_lock(dev_priv, &unlock)) + if (!shrinker_lock(i915, &unlock)) return SHRINK_STOP; - freed = i915_gem_shrink(dev_priv, + freed = i915_gem_shrink(i915, sc->nr_to_scan, &sc->nr_scanned, I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE); if (freed < sc->nr_to_scan) - freed += i915_gem_shrink(dev_priv, + freed += i915_gem_shrink(i915, sc->nr_to_scan - sc->nr_scanned, &sc->nr_scanned, I915_SHRINK_BOUND | I915_SHRINK_UNBOUND); if (freed < sc->nr_to_scan && current_is_kswapd()) { - intel_runtime_pm_get(dev_priv); - freed += i915_gem_shrink(dev_priv, + intel_runtime_pm_get(i915); + freed += i915_gem_shrink(i915, sc->nr_to_scan - sc->nr_scanned, &sc->nr_scanned, I915_SHRINK_ACTIVE | I915_SHRINK_BOUND | I915_SHRINK_UNBOUND); - intel_runtime_pm_put(dev_priv); + intel_runtime_pm_put(i915); } - shrinker_unlock(dev_priv, unlock); + shrinker_unlock(i915, unlock); return sc->nr_scanned ? freed : SHRINK_STOP; } static bool -shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv, bool *unlock, +shrinker_lock_uninterruptible(struct drm_i915_private *i915, bool *unlock, int timeout_ms) { unsigned long timeout = jiffies + msecs_to_jiffies_timeout(timeout_ms); do { - if (i915_gem_wait_for_idle(dev_priv, 0) == 0 && - shrinker_lock(dev_priv, unlock)) + if (i915_gem_wait_for_idle(i915, 0) == 0 && + shrinker_lock(i915, unlock)) break; schedule_timeout_killable(1); @@ -412,32 +412,32 @@ shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv, bool *unlock, static int i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) { - struct drm_i915_private *dev_priv = + struct drm_i915_private *i915 = container_of(nb, struct drm_i915_private, mm.oom_notifier); struct drm_i915_gem_object *obj; unsigned long unevictable, bound, unbound, freed_pages; - freed_pages = i915_gem_shrink_all(dev_priv); + freed_pages = i915_gem_shrink_all(i915); /* Because we may be allocating inside our own driver, we cannot * assert that there are no objects with pinned pages that are not * being pointed to by hardware. */ unbound = bound = unevictable = 0; - spin_lock(&dev_priv->mm.obj_lock); - list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) { + spin_lock(&i915->mm.obj_lock); + list_for_each_entry(obj, &i915->mm.unbound_list, mm.link) { if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else unbound += obj->base.size >> PAGE_SHIFT; } - list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) { + list_for_each_entry(obj, &i915->mm.bound_list, mm.link) { if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else bound += obj->base.size >> PAGE_SHIFT; } - spin_unlock(&dev_priv->mm.obj_lock); + spin_unlock(&i915->mm.obj_lock); if (freed_pages || unbound || bound) pr_info("Purging GPU memory, %lu pages freed, " @@ -455,39 +455,39 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) static int i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) { - struct drm_i915_private *dev_priv = + struct drm_i915_private *i915 = container_of(nb, struct drm_i915_private, mm.vmap_notifier); struct i915_vma *vma, *next; unsigned long freed_pages = 0; bool unlock; int ret; - if (!shrinker_lock_uninterruptible(dev_priv, &unlock, 5000)) + if (!shrinker_lock_uninterruptible(i915, &unlock, 5000)) return NOTIFY_DONE; /* Force everything onto the inactive lists */ - ret = i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); + ret = i915_gem_wait_for_idle(i915, I915_WAIT_LOCKED); if (ret) goto out; - intel_runtime_pm_get(dev_priv); - freed_pages += i915_gem_shrink(dev_priv, -1UL, NULL, + intel_runtime_pm_get(i915); + freed_pages += i915_gem_shrink(i915, -1UL, NULL, I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_ACTIVE | I915_SHRINK_VMAPS); - intel_runtime_pm_put(dev_priv); + intel_runtime_pm_put(i915); /* We also want to clear any cached iomaps as they wrap vmap */ list_for_each_entry_safe(vma, next, - &dev_priv->ggtt.base.inactive_list, vm_link) { + &i915->ggtt.base.inactive_list, vm_link) { unsigned long count = vma->node.size >> PAGE_SHIFT; if (vma->iomap && i915_vma_unbind(vma) == 0) freed_pages += count; } out: - shrinker_unlock(dev_priv, unlock); + shrinker_unlock(i915, unlock); *(unsigned long *)ptr += freed_pages; return NOTIFY_DONE; @@ -495,34 +495,34 @@ out: /** * i915_gem_shrinker_register - Register the i915 shrinker - * @dev_priv: i915 device + * @i915: i915 device * * This function registers and sets up the i915 shrinker and OOM handler. */ -void i915_gem_shrinker_register(struct drm_i915_private *dev_priv) +void i915_gem_shrinker_register(struct drm_i915_private *i915) { - dev_priv->mm.shrinker.scan_objects = i915_gem_shrinker_scan; - dev_priv->mm.shrinker.count_objects = i915_gem_shrinker_count; - dev_priv->mm.shrinker.seeks = DEFAULT_SEEKS; - dev_priv->mm.shrinker.batch = 4096; - WARN_ON(register_shrinker(&dev_priv->mm.shrinker)); + i915->mm.shrinker.scan_objects = i915_gem_shrinker_scan; + i915->mm.shrinker.count_objects = i915_gem_shrinker_count; + i915->mm.shrinker.seeks = DEFAULT_SEEKS; + i915->mm.shrinker.batch = 4096; + WARN_ON(register_shrinker(&i915->mm.shrinker)); - dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; - WARN_ON(register_oom_notifier(&dev_priv->mm.oom_notifier)); + i915->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; + WARN_ON(register_oom_notifier(&i915->mm.oom_notifier)); - dev_priv->mm.vmap_notifier.notifier_call = i915_gem_shrinker_vmap; - WARN_ON(register_vmap_purge_notifier(&dev_priv->mm.vmap_notifier)); + i915->mm.vmap_notifier.notifier_call = i915_gem_shrinker_vmap; + WARN_ON(register_vmap_purge_notifier(&i915->mm.vmap_notifier)); } /** * i915_gem_shrinker_unregister - Unregisters the i915 shrinker - * @dev_priv: i915 device + * @i915: i915 device * * This function unregisters the i915 shrinker and OOM handler. */ -void i915_gem_shrinker_unregister(struct drm_i915_private *dev_priv) +void i915_gem_shrinker_unregister(struct drm_i915_private *i915) { - WARN_ON(unregister_vmap_purge_notifier(&dev_priv->mm.vmap_notifier)); - WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier)); - unregister_shrinker(&dev_priv->mm.shrinker); + WARN_ON(unregister_vmap_purge_notifier(&i915->mm.vmap_notifier)); + WARN_ON(unregister_oom_notifier(&i915->mm.oom_notifier)); + unregister_shrinker(&i915->mm.shrinker); } -- cgit From d02a1d830880b611000aaa0df8a8d7aabf1d8718 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 27 Nov 2017 12:30:54 +0000 Subject: drm/i915: Rename i915_gem_timelines_mark_idle The kerneldoc markup for i915_gem_timelines_mark_idle() was incorrect, so take the opportunity to also convert it from the "mark_idle" to "park" naming scheme. drivers/gpu/drm/i915/i915_gem_timeline.c:120: warning: No description found for parameter 'i915' Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171127123054.20966-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- drivers/gpu/drm/i915/i915_gem_timeline.c | 6 +++--- drivers/gpu/drm/i915/i915_gem_timeline.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e03d6c2554e2..354b0546a191 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3371,7 +3371,8 @@ i915_gem_idle_work_handler(struct work_struct *work) synchronize_irq(dev_priv->drm.irq); intel_engines_park(dev_priv); - i915_gem_timelines_mark_idle(dev_priv); + i915_gem_timelines_park(dev_priv); + i915_pmu_gt_parked(dev_priv); GEM_BUG_ON(!dev_priv->gt.awake); diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c index c597ce277a04..c01905d6450c 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/i915_gem_timeline.c @@ -107,8 +107,8 @@ int i915_gem_timeline_init__global(struct drm_i915_private *i915) } /** - * i915_gem_timelines_mark_idle -- called when the driver idles - * @i915 - the drm_i915_private device + * i915_gem_timelines_park - called when the driver idles + * @i915: the drm_i915_private device * * When the driver is completely idle, we know that all of our sync points * have been signaled and our tracking is then entirely redundant. Any request @@ -116,7 +116,7 @@ int i915_gem_timeline_init__global(struct drm_i915_private *i915) * the fence is signaled and therefore we will not even look them up in the * sync point map. */ -void i915_gem_timelines_mark_idle(struct drm_i915_private *i915) +void i915_gem_timelines_park(struct drm_i915_private *i915) { struct i915_gem_timeline *timeline; int i; diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h index bfb5eb94c64d..b5a22400a01f 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h @@ -93,7 +93,7 @@ int i915_gem_timeline_init(struct drm_i915_private *i915, struct i915_gem_timeline *tl, const char *name); int i915_gem_timeline_init__global(struct drm_i915_private *i915); -void i915_gem_timelines_mark_idle(struct drm_i915_private *i915); +void i915_gem_timelines_park(struct drm_i915_private *i915); void i915_gem_timeline_fini(struct i915_gem_timeline *tl); static inline int __intel_timeline_sync_set(struct intel_timeline *tl, -- cgit From 448aa9117cfa6591c4e18cb32a0329a66b9cd3b7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Nov 2017 11:01:47 +0000 Subject: drm/i915: Enable hotplug polling after registering the outputs Previously we would enable hotplug polling on the outputs immediately upon construction. This would allow a very early hotplug event to trigger before we had finishing setting up the driver to handle it. Instead, move the output polling to the last step of registration, after we have set up all handlers, including the fbdev configuration. v2: Symmetrically turnoff the hotplug helper in unregister after the fbdev is first synchronised then finalized. This stops a late hotplug event being processed after the interrupts are disabled. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Ville Syrjala Cc: Maarten Lankhorst Reviewed-by: Maarten Lankhorst #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20171128110147.28654-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 16 ++++++++++++++-- drivers/gpu/drm/i915/intel_display.c | 5 +---- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9c519aa4f550..1c419893e3a9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -693,8 +693,6 @@ static int i915_load_modeset_init(struct drm_device *dev) /* Only enable hotplug handling once the fbdev is fully set up. */ intel_hpd_init(dev_priv); - drm_kms_helper_poll_init(dev); - return 0; cleanup_gem: @@ -1255,6 +1253,13 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) * cannot run before the connectors are registered. */ intel_fbdev_initial_config_async(dev); + + /* + * We need to coordinate the hotplugs with the asynchronous fbdev + * configuration, for which we use the fbdev->async_cookie. + */ + if (INTEL_INFO(dev_priv)->num_pipes) + drm_kms_helper_poll_init(dev); } /** @@ -1266,6 +1271,13 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) intel_fbdev_unregister(dev_priv); intel_audio_deinit(dev_priv); + /* + * After flushing the fbdev (incl. a late async config which will + * have delayed queuing of a hotplug event), then flush the hotplug + * events. + */ + drm_kms_helper_poll_fini(&dev_priv->drm); + intel_gpu_ips_teardown(); acpi_video_unregister(); intel_opregion_unregister(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fec267dfc062..76c75d34e799 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15276,10 +15276,7 @@ static void intel_hpd_poll_fini(struct drm_device *dev) struct intel_connector *connector; struct drm_connector_list_iter conn_iter; - /* First disable polling... */ - drm_kms_helper_poll_fini(dev); - - /* Then kill the work that may have been queued by hpd. */ + /* Kill all the work that may have been queued by hpd. */ drm_connector_list_iter_begin(dev, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { if (connector->modeset_retry_work.func) -- cgit From 00a797225e53a4f488ab725e0b438c2970aa41d7 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 28 Nov 2017 10:55:15 +0000 Subject: drm/i915/pmu: Return -EINVAL when selecting the inactive CPU In commit 0426c0465461 ("drm/i915/pmu: Only allow running on a single CPU") I attempted to clarify the CPU hotplug logic in our PMU implementation, but missed that a more logical error to return, when attempting to initialize an event on a currently inactive CPU, is -EINVAL rather than -ENODEV. This is because i915 PMU explicitly disallows running counters on more than one CPU at a time, and is not reporting that the requested CPU does not exist, or is off-line. Signed-off-by: Tvrtko Ursulin Reported-by: Chris Wilson Cc: Chris Wilson Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20171128105515.21998-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 3357b690ce90..1c0ee9d68b04 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -338,7 +338,7 @@ static int i915_pmu_event_init(struct perf_event *event) /* only allow running on one cpu at a time */ if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask)) - return -ENODEV; + return -EINVAL; if (is_engine_event(event)) { ret = engine_event_init(event); -- cgit From 9987da4b5dcfc8b94b702d4bb94b30955eb73c75 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Mon, 27 Nov 2017 11:12:33 +0200 Subject: drm/i915: Disable THP until we have a GPU read BW W/A We seem to be missing some W/A for 2M pages and are getting a hit on raw GPU read bandwidths (even 30%) even though the GPU write bandwidths improve (even 10%). For now, disable THP, which is our only practical source of 2M pages until we have a W/A for the issue. v2: - Be explicit that we talk about GPU bandwidths (Eero) - s/deny/never/ because that's why (Chris) Reported-by: Valtteri Rantala Fixes: b901bb89324a ("drm/i915/gemfs: enable THP") Signed-off-by: Joonas Lahtinen Cc: Matthew Auld Cc: Chris Wilson Cc: Jani Nikula Cc: Rodrigo Vivi Cc: Valtteri Rantala Cc: Eero Tamminen Reviewed-by: Chris Wilson Reviewed-by: Matthew Auld Tested-by: Valtteri Rantala Link: https://patchwork.freedesktop.org/patch/msgid/20171127091233.7001-1-joonas.lahtinen@linux.intel.com --- drivers/gpu/drm/i915/i915_gemfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gemfs.c b/drivers/gpu/drm/i915/i915_gemfs.c index e2993857df37..888b7d3f04c3 100644 --- a/drivers/gpu/drm/i915/i915_gemfs.c +++ b/drivers/gpu/drm/i915/i915_gemfs.c @@ -52,7 +52,8 @@ int i915_gemfs_init(struct drm_i915_private *i915) if (has_transparent_hugepage()) { struct super_block *sb = gemfs->mnt_sb; - char options[] = "huge=within_size"; + /* FIXME: Disabled until we get W/A for read BW issue. */ + char options[] = "huge=never"; int flags = 0; int err; -- cgit From 439e2ee4ca520e72870e4fa44aa0076060ad6857 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 29 Nov 2017 08:24:09 +0000 Subject: drm/i915: Move engine->needs_cmd_parser to engine->flags Will be adding a new per-engine flags shortly so it makes sense to consolidate. v2: Keep the original code flow in intel_engine_cleanup_cmd_parser. (Joonas Lahtinen) Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Reviewed-by: Sagar Arun Kamble Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171129082409.18189-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_cmd_parser.c | 7 ++++--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.h | 8 +++++++- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index b11629beeb63..ccb5ba043b63 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -26,6 +26,7 @@ */ #include "i915_drv.h" +#include "intel_ringbuffer.h" /** * DOC: batch buffer command parser @@ -940,7 +941,7 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine) return; } - engine->needs_cmd_parser = true; + engine->flags |= I915_ENGINE_NEEDS_CMD_PARSER; } /** @@ -952,7 +953,7 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine) */ void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine) { - if (!engine->needs_cmd_parser) + if (!intel_engine_needs_cmd_parser(engine)) return; fini_hash_table(engine); @@ -1350,7 +1351,7 @@ int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv) /* If the command parser is not enabled, report 0 - unsupported */ for_each_engine(engine, dev_priv, id) { - if (engine->needs_cmd_parser) { + if (intel_engine_needs_cmd_parser(engine)) { active = true; break; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 14d9e61a1e06..70ccd63cbf8e 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -271,7 +271,7 @@ static inline u64 gen8_noncanonical_addr(u64 address) static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { - return eb->engine->needs_cmd_parser && eb->batch_len; + return intel_engine_needs_cmd_parser(eb->engine) && eb->batch_len; } static int eb_create(struct i915_execbuffer *eb) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index ef304c99954c..2b978b363c0b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -538,7 +538,8 @@ struct intel_engine_cs { struct intel_engine_hangcheck hangcheck; - bool needs_cmd_parser; +#define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) + unsigned int flags; /* * Table of commands the command parser needs to know about @@ -597,6 +598,11 @@ struct intel_engine_cs { } stats; }; +static inline bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) +{ + return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; +} + static inline void execlists_set_active(struct intel_engine_execlists *execlists, unsigned int bit) -- cgit From cf669b4e9fdce4cf1a7bef4e7ab8b3db0da021a2 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 29 Nov 2017 10:28:05 +0000 Subject: drm/i915: Consolidate checks for engine stats availability Sagar noticed the check can be consolidated between the engine stats implementation and the PMU. My first choice was a static inline helper but that got into include ordering mess quickly fast so I went with a macro instead. At some point we should perhaps looking into taking out the non-ringubffer bits from intel_ringbuffer.h into a new intel_engine.h or something. v2: Use engine->flags. (Chris Wilson) v3: Rebase and mark GuC as not yet supported. (Chris Wilson) v4: Move flag setting to intel_engines_reset_default_submission. (Chris Wilson) v5: Move flag setting to logical_ring_setup. v6: intel_engines_reset_default_submission is the wrong place to set the flag - it needs to be in execlists_set_default_submission. (Sagar) v7: Flag setting in logical_ring_setup is not required. (Chris) Signed-off-by: Tvrtko Ursulin Suggested-by: Sagar Arun Kamble Cc: Sagar Arun Kamble Reviewed-by: Chris Wilson Reviewed-by: Sagar Arun Kamble (v6) Link: https://patchwork.freedesktop.org/patch/msgid/20171129102805.22690-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 11 ++++------- drivers/gpu/drm/i915/intel_engine_cs.c | 4 ++-- drivers/gpu/drm/i915/intel_guc_submission.c | 2 ++ drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 6 ++++++ 5 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 1c0ee9d68b04..e8e2faf4982f 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -90,11 +90,6 @@ static unsigned int event_enabled_bit(struct perf_event *event) return config_enabled_bit(event->attr.config); } -static bool supports_busy_stats(struct drm_i915_private *i915) -{ - return INTEL_GEN(i915) >= 8; -} - static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active) { u64 enable; @@ -123,8 +118,10 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active) /* * Also there is software busyness tracking available we do not * need the timer for I915_SAMPLE_BUSY counter. + * + * Use RCS as proxy for all engines. */ - else if (supports_busy_stats(i915)) + else if (intel_engine_supports_stats(i915->engine[RCS])) enable &= ~BIT(I915_SAMPLE_BUSY); /* @@ -447,7 +444,7 @@ again: static bool engine_needs_busy_stats(struct intel_engine_cs *engine) { - return supports_busy_stats(engine->i915) && + return intel_engine_supports_stats(engine) && (engine->pmu.enable & BIT(I915_SAMPLE_BUSY)); } diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index fede62daf3e1..cffd0c812b7e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1863,7 +1863,7 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) { unsigned long flags; - if (INTEL_GEN(engine->i915) < 8) + if (!intel_engine_supports_stats(engine)) return -ENODEV; spin_lock_irqsave(&engine->stats.lock, flags); @@ -1924,7 +1924,7 @@ void intel_disable_engine_stats(struct intel_engine_cs *engine) { unsigned long flags; - if (INTEL_GEN(engine->i915) < 8) + if (!intel_engine_supports_stats(engine)) return; spin_lock_irqsave(&engine->stats.lock, flags); diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index cf1cc2cb6722..912ff143d531 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -1453,6 +1453,8 @@ int intel_guc_submission_enable(struct intel_guc *guc) execlists->tasklet.func = guc_submission_tasklet; engine->park = guc_submission_park; engine->unpark = guc_submission_unpark; + + engine->flags &= ~I915_ENGINE_SUPPORTS_STATS; } return 0; diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 570864583e28..2a8160f603ab 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1919,6 +1919,8 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) engine->park = NULL; engine->unpark = NULL; + + engine->flags |= I915_ENGINE_SUPPORTS_STATS; } static void diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 2b978b363c0b..3d097bbeb2d9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -539,6 +539,7 @@ struct intel_engine_cs { struct intel_engine_hangcheck hangcheck; #define I915_ENGINE_NEEDS_CMD_PARSER BIT(0) +#define I915_ENGINE_SUPPORTS_STATS BIT(1) unsigned int flags; /* @@ -603,6 +604,11 @@ static inline bool intel_engine_needs_cmd_parser(struct intel_engine_cs *engine) return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER; } +static inline bool intel_engine_supports_stats(struct intel_engine_cs *engine) +{ + return engine->flags & I915_ENGINE_SUPPORTS_STATS; +} + static inline void execlists_set_active(struct intel_engine_execlists *execlists, unsigned int bit) -- cgit From 580b9d05a34ef81ecab6a55e068ab269b148b32e Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 29 Nov 2017 21:49:09 +0530 Subject: drm/i915/guc: Change default GuC FW for SKL to v9.33 This patch makes v9.33 firmware as default firmware for SKL. Note: GuC logging control is changed with this firmware. GuC is expecting i915 to set control bit to enable "default logging" while using GuC action UK_LOG_ENABLE_LOGGING. However i915 is currently not doing this because it is version specific change and can be handled entirely in GuC. It will need to be fixed in future firmwares. This update includes (since v6.1): - HuC RSA Keys updated. - Adding per engine preemption support in GuC scheduler - Minor bug fixes. - Added support to log media reset count for host to read it - Sub-feature level control for power management features. - Minor clean-up for power management interface. - Unified power management interface and scheduler interface into 1 file using same version. - Bug Fix for multi context scheduler flag. - DCC spec changes for BXT + DCT enabling - SB based Pre-ETM/ETM flow enabling for debug signed GuC/HuC - Moving GuC non_critical r/w data to lower SRAM 64KB - Media engine Reset fix. Correctly marking context for resubmission in Media Reset case. - ABT Disable bug fix. Disabled Evaluation mode on context change. - Async FW in Engine Schedule feature (not enabled from KMD) - GuC clean up to align developer build in line to production build. - DCC consistency fix for SKL - Disable ARAT interrupt before programming ARAT delta. - Memory range check in Parse to avoid failure due to overflow. - Enabled WA for MSGCH hang issue - Clear forcewake in CSB when SQ is empty. - Move UkGuckmdInterface.h file from 2016 folders to common 2016 folder. - This is file location change.No functional change done as part of this check in. - Enable decoupled freq for SKL GT4 - 3 tries of wake request needed from GuC2CSME for ME to wake up. Request has come from ME spec - During reset one parameter was not getting accounted - Enabling Guc Log changes for ultra low logging for OCA - Enabling build failure check to catch critical section overflow. - Disable build.bat redundant prints. - Move few least used functions to non-critical section. - Rearrange GuC documentation folder structure. - Synchronize SLPC internal debug interface with other branches. - Fixing Issue with Default Guc Log changes for OCA using special Control Bit v2: Rebase. Updated commit message. Signed-off-by: Jeff McGee Signed-off-by: Sagar Arun Kamble Cc: Spotswood John A Cc: Anusha Srivatsa Cc: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Joonas Lahtinen Reviewed-by: Anusha Srivatsa Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1511972351-574-2-git-send-email-sagar.a.kamble@intel.com --- drivers/gpu/drm/i915/intel_guc_fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index bbab4e1106f3..631e932c9953 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -30,8 +30,8 @@ #include "intel_guc_fw.h" #include "i915_drv.h" -#define SKL_FW_MAJOR 6 -#define SKL_FW_MINOR 1 +#define SKL_FW_MAJOR 9 +#define SKL_FW_MINOR 33 #define BXT_FW_MAJOR 8 #define BXT_FW_MINOR 7 -- cgit From d416ac780eecc76511fcf15974f54f5e9520cea6 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 29 Nov 2017 21:49:10 +0530 Subject: drm/i915/guc: Change default GuC FW for BXT to v9.29 This patch makes v9.29 firmware as default firmware for BXT. Note: GuC logging control is changed with this firmware. GuC is expecting i915 to set control bit to enable "default logging" while using GuC action UK_LOG_ENABLE_LOGGING. However i915 is currently not doing this because it is version specific change and can be handled entirely in GuC. It will need to be fixed in future firmwares. This update includes (since v8.7): - Added support to log media reset count for host to read it - BXT WA for fixing MTP hangs. WaDisableDOPRenderClkGatingAtSubmit - Sub-feature level control for power management features. - Minor clean-up for power management interface. - Unified power management interface and scheduler interface into 1 file using same version. - Bug Fix for multi context scheduler flag. - DCC spec changes for BXT + DCT enabling - Springboard based Pre-ETM/ETM flow enabling for debug signed GuC/HuC - Moving GuC non_critical r/w data to lower SRAM 64KB - Enabled IBC for BXT - Media engine Reset fix. Correctly marking context for resubmission in Media Reset case. - SLPC Dynamic RPe fix to resolve issues where incorrect frequency was set. - ABT Disable bug fix. Disabled Evaluation mode on context change. - GuC clean up to align developer build in line to production build. - Disable ARAT interrupt before programming ARAT delta. - Memory range check in Parse to avoid failure due to overflow. - Clear forcewake in CSB when SQ is empty. - SLPC IBC 1.6 for APL to ensure multiplier does not cap IA below Pe. - Move UkGuckmdInterface.h file from 2016 folders to common 2016 folder. - This is file location change. No functional change done as part of this check in. - 3 tries of wake request needed from GuC2CSME for ME to wake up. Request has come from ME spec - During reset one parameter was not getting accounted - Enabling Guc Log changes for ultra low logging for OCA - Disable build.bat redundant prints. - Move few least used functions to non-critical section. - Rearrange GuC documentation folder structure. - Fixing Issue with Default Guc Log changes for OCA using special Control Bit v2: Rebase. Updated commit message. Signed-off-by: Jeff McGee Signed-off-by: Sagar Arun Kamble Cc: Spotswood John A Cc: Anusha Srivatsa Cc: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Joonas Lahtinen Reviewed-by: Anusha Srivatsa Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1511972351-574-3-git-send-email-sagar.a.kamble@intel.com --- drivers/gpu/drm/i915/intel_guc_fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index 631e932c9953..df2ff965655a 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -33,8 +33,8 @@ #define SKL_FW_MAJOR 9 #define SKL_FW_MINOR 33 -#define BXT_FW_MAJOR 8 -#define BXT_FW_MINOR 7 +#define BXT_FW_MAJOR 9 +#define BXT_FW_MINOR 29 #define KBL_FW_MAJOR 9 #define KBL_FW_MINOR 14 -- cgit From cc44085616a94a998dc8f708e37ec9df2df97a87 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 29 Nov 2017 21:49:11 +0530 Subject: drm/i915/guc: Change default GuC FW for KBL to v9.39 This patch makes v9.39 firmware as default firmware for KBL. Note: GuC logging control is changed with this firmware. GuC is expecting i915 to set control bit to enable "default logging" while using GuC action UK_LOG_ENABLE_LOGGING. However i915 is currently not doing this because it is version specific change and can be handled entirely in GuC. It will need to be fixed in future firmwares. This update includes (since v9.14): - DCC spec changes for BXT + DCT enabling - Bug Fix for power conservation feature SLPC_DCC - Scheduler 1-element submission during DCC cycles. - SB based Pre-ETM/ETM flow enabling for debug signed GuC/HuC - Moving GuC non_critical r/w data to lower SRAM 64KB - Media engine Reset fix. Correctly marking context for resubmission in Media Reset case. - ABT Disable bug fix. Disabled Evaluation mode on context change. - Async FW in Engine Schedule feature (not enabled from KMD) - GuC clean up to align developer build in line to production build. - Disable ARAT interrupt before programming ARAT delta. - Memory range check in Parse to avoid failure due to overflow. - GuC Msg Channel Hang WA - Stall GUC for mmio access when IDI is low during CPD flow. - Fix for submit queue over flow issue - Enabling IBC on KBL GT3 15W, GT4 45W - Disabling wrong device ID WA in production signed kernel - Enabling WA for MSGCH hang issue upto required KBL stepping - Clear forcewake in CSB when SQ is empty. - 3Tries of GuC2CSME wake request - During reset one parameter was not getting accounted - Disable DCC 1-elem mode submission - Move UkGuckmdInterface.h file from 2016 folders to common 2016 folder. - This is file location change.No functional change done as part of this check in. - Enabling Guc Log changes for ultra low logging for OCA - Enabling Dynamic Render Power Well Hysteresis Programming for Compute Worklaods - Enabling build failure check to catch critical section overflow. - Disable build.bat redundant prints. - Move few least used functions to non-critical section. - Rearrange GuC documentation folder structure. - Synchronize SLPC internal debug interface with other branches. - Fixing Issue with Default Guc Log changes for OCA using special Control Bit - Aggressive DCC implementation for supported platforms. v2: Rebase. Updated commit message. Signed-off-by: Jeff McGee Signed-off-by: Sagar Arun Kamble Cc: Spotswood John A Cc: Anusha Srivatsa Cc: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Joonas Lahtinen Reviewed-by: Anusha Srivatsa Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1511972351-574-4-git-send-email-sagar.a.kamble@intel.com --- drivers/gpu/drm/i915/intel_guc_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index df2ff965655a..89862fa8ab42 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -37,7 +37,7 @@ #define BXT_FW_MINOR 29 #define KBL_FW_MAJOR 9 -#define KBL_FW_MINOR 14 +#define KBL_FW_MINOR 39 #define GLK_FW_MAJOR 10 #define GLK_FW_MINOR 56 -- cgit From 7436830c8d1a3aab61d131d5e0494e2dbb9e55bd Mon Sep 17 00:00:00 2001 From: Valtteri Rantala Date: Tue, 28 Nov 2017 16:45:05 +0200 Subject: drm/i915/glk: Apply WaProgramL3SqcReg1DefaultForPerf for GLK too Testing the texture read performance shows that the same tuning for the SQ credits is needed on GLK as on BXT/APL. This has been also confirmed by Altug from the HW team. V4: Rebase + fix Signed-off-by: Valtteri Rantala Reviewed-by: David Weinehall (v1) Reviewed-by: Rodrigo Vivi Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/1511880305-12166-1-git-send-email-valtteri.rantala@intel.com --- drivers/gpu/drm/i915/intel_engine_cs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index cffd0c812b7e..86d4c85c8725 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1067,6 +1067,15 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); + /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ + if (IS_GEN9_LP(dev_priv)) { + u32 val = I915_READ(GEN8_L3SQCREG1); + + val &= ~L3_PRIO_CREDITS_MASK; + val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); + I915_WRITE(GEN8_L3SQCREG1, val); + } + /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES)); @@ -1184,7 +1193,6 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) static int bxt_init_workarounds(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - u32 val; int ret; ret = gen9_init_workarounds(engine); @@ -1199,12 +1207,6 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(FF_SLICE_CS_CHICKEN2, _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); - /* WaProgramL3SqcReg1DefaultForPerf:bxt */ - val = I915_READ(GEN8_L3SQCREG1); - val &= ~L3_PRIO_CREDITS_MASK; - val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); - I915_WRITE(GEN8_L3SQCREG1, val); - /* WaToEnableHwFixForPushConstHWBug:bxt */ WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); -- cgit From ecf73eb2d27d43b2153bb80671768a06d35521f1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Nov 2017 10:29:51 +0000 Subject: drm/i915: Skip switch-to-kernel-context on suspend when wedged If the HW is already wedged, attempting to submit a request will generate an -EIO. If we tried this during suspend, we would abort whereas all we want to do is to go sleep and throw away the corrupt state. Fixes: 5ab57c702069 ("drm/i915: Flush logical context image out to memory upon suspend") Testcase: igt/gem_eio/suspend Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171130102951.14965-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 354b0546a191..e083f242b8dc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4774,17 +4774,19 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) * state. Fortunately, the kernel_context is disposable and we do * not rely on its state. */ - ret = i915_gem_switch_to_kernel_context(dev_priv); - if (ret) - goto err_unlock; + if (!i915_terminally_wedged(&dev_priv->gpu_error)) { + ret = i915_gem_switch_to_kernel_context(dev_priv); + if (ret) + goto err_unlock; - ret = i915_gem_wait_for_idle(dev_priv, - I915_WAIT_INTERRUPTIBLE | - I915_WAIT_LOCKED); - if (ret && ret != -EIO) - goto err_unlock; + ret = i915_gem_wait_for_idle(dev_priv, + I915_WAIT_INTERRUPTIBLE | + I915_WAIT_LOCKED); + if (ret && ret != -EIO) + goto err_unlock; - assert_kernel_context_is_current(dev_priv); + assert_kernel_context_is_current(dev_priv); + } i915_gem_contexts_lost(dev_priv); mutex_unlock(&dev->struct_mutex); -- cgit From 5643205c6340b565a3be0fe0e7305dc4aa551c74 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 29 Nov 2017 19:51:37 +0200 Subject: drm/i915: Avoid PPS HW/SW state mismatch due to rounding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We store a SW state of the t11_t12 timing in 100usec units but have to program it in 100msec as required by HW. The rounding used during programming means there will be a mismatch between the SW and HW states of this value triggering a "PPS state mismatch" error. Avoid this by storing the already rounded-up value in the SW state. Note that we still calculate panel_power_cycle_delay with the finer 100usec granularity to avoid any needless waits using that version of the delay. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103903 Cc: joks Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129175137.2889-1-imre.deak@intel.com --- drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index dd0b3a018792..c603d4c903e1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5355,6 +5355,12 @@ intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp) */ final->t8 = 1; final->t9 = 1; + + /* + * HW has only a 100msec granularity for t11_t12 so round it up + * accordingly. + */ + final->t11_t12 = roundup(final->t11_t12, 100 * 10); } static void -- cgit From 24f2845056892b297fa95edbddceefd38acc0e62 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 22 Nov 2017 19:39:01 +0100 Subject: drm/i915: Make ips_enabled a property depending on whether IPS is enabled, v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ips_enabled was used as a variable of whether IPS can be enabled or not, but should be used to test whether IPS is actually enabled. Changes since v1: - Call needs_modeset on new crtc state. (Ville) - IPS can be enabled with sprite plane enabled too. (Ville) - Fix CDCLK vs IPS workaround. (Ville) Changes since v2: - Only re-enable fastset when inheriting mode. (Ville) - Put the conditions for enabling and disabling IPS in a helper. Changes since v3: - Keep the max_cdclk workaround working. (Ville) - Also check logical cdclk out of paranoia. - Remove planes check from IPS disable function for initial disable. - Remove assert_plane_enabled/disabled checks and use crtc_state->active_planes for hsw_enable_ips only, always allow calling hsw_disable_ips to disable it initially in hw. Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20171122183901.47720-1-maarten.lankhorst@linux.intel.com [mlankhorst: pipe_config -> crtc_state (Ville)] Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 168 ++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pipe_crc.c | 2 - 4 files changed, 109 insertions(+), 64 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index e8884c2ade98..9c5ceb98d48f 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -1896,7 +1896,7 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) min_cdclk = intel_pixel_rate_to_cdclk(dev_priv, crtc_state->pixel_rate); /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ - if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled) + if (IS_BROADWELL(dev_priv) && hsw_crtc_state_ips_capable(crtc_state)) min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95); /* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 76c75d34e799..68f101c0e909 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -489,7 +489,7 @@ static const struct intel_limit intel_limits_bxt = { }; static bool -needs_modeset(struct drm_crtc_state *state) +needs_modeset(const struct drm_crtc_state *state) { return drm_atomic_crtc_needs_modeset(state); } @@ -4833,7 +4833,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - if (!crtc->config->ips_enabled) + if (!crtc_state->ips_enabled) return; /* @@ -4841,8 +4841,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state) * This function is called from post_plane_update, which is run after * a vblank wait. */ - - assert_plane_enabled(to_intel_plane(crtc->base.primary)); + WARN_ON(!(crtc_state->active_planes & ~BIT(PLANE_CURSOR))); if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->pcu_lock); @@ -4877,8 +4876,6 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state) if (!crtc_state->ips_enabled) return; - assert_plane_enabled(to_intel_plane(crtc->base.primary)); - if (IS_BROADWELL(dev_priv)) { mutex_lock(&dev_priv->pcu_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); @@ -4931,14 +4928,6 @@ intel_post_enable_primary(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - hsw_enable_ips(new_crtc_state); - /* * Gen2 reports pipe underruns whenever all planes are disabled. * So don't enable underrun reporting before at least some planes @@ -4954,10 +4943,9 @@ intel_post_enable_primary(struct drm_crtc *crtc, intel_check_pch_fifo_underruns(dev_priv); } -/* FIXME move all this to pre_plane_update() with proper state tracking */ +/* FIXME get rid of this and use pre_plane_update */ static void -intel_pre_disable_primary(struct drm_crtc *crtc, - const struct intel_crtc_state *old_crtc_state) +intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = to_i915(dev); @@ -4966,32 +4954,12 @@ intel_pre_disable_primary(struct drm_crtc *crtc, /* * Gen2 reports pipe underruns whenever all planes are disabled. - * So diasble underrun reporting before all the planes get disabled. - * FIXME: Need to fix the logic to work when we turn off all planes - * but leave the pipe running. + * So disable underrun reporting before all the planes get disabled. */ if (IS_GEN2(dev_priv)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - hsw_disable_ips(old_crtc_state); -} - -/* FIXME get rid of this and use pre_plane_update */ -static void -intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - - intel_pre_disable_primary(crtc, to_intel_crtc_state(crtc->state)); + hsw_disable_ips(to_intel_crtc_state(crtc->state)); /* * Vblank time updates from the shadow to live plane control register @@ -5007,6 +4975,38 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) intel_wait_for_vblank(dev_priv, pipe); } +static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + if (!old_crtc_state->ips_enabled) + return false; + + if (needs_modeset(&new_crtc_state->base)) + return true; + + return !new_crtc_state->ips_enabled; +} + +static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + if (!new_crtc_state->ips_enabled) + return false; + + if (needs_modeset(&new_crtc_state->base)) + return true; + + /* + * We can't read out IPS on broadwell, assume the worst and + * forcibly enable IPS on the first fastset. + */ + if (new_crtc_state->update_pipe && + old_crtc_state->base.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED) + return true; + + return !old_crtc_state->ips_enabled; +} + static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); @@ -5023,6 +5023,9 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) if (pipe_config->update_wm_post && pipe_config->base.active) intel_update_watermarks(crtc); + if (hsw_post_update_enable_ips(old_crtc_state, pipe_config)) + hsw_enable_ips(pipe_config); + if (old_pri_state) { struct intel_plane_state *primary_state = intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state), @@ -5053,6 +5056,9 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, struct intel_atomic_state *old_intel_state = to_intel_atomic_state(old_state); + if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config)) + hsw_disable_ips(old_crtc_state); + if (old_pri_state) { struct intel_plane_state *primary_state = intel_atomic_get_new_plane_state(old_intel_state, @@ -5061,10 +5067,13 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state, to_intel_plane_state(old_pri_state); intel_fbc_pre_update(crtc, pipe_config, primary_state); - - if (old_primary_state->base.visible && + /* + * Gen2 reports pipe underruns whenever all planes are disabled. + * So disable underrun reporting before all the planes get disabled. + */ + if (IS_GEN2(dev_priv) && old_primary_state->base.visible && (modeset || !primary_state->base.visible)) - intel_pre_disable_primary(&crtc->base, old_crtc_state); + intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); } /* @@ -6195,18 +6204,20 @@ retry: return ret; } -static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv, - struct intel_crtc_state *pipe_config) +bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) { - if (pipe_config->ips_force_disable) + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + + /* IPS only exists on ULT machines and is tied to pipe A. */ + if (!hsw_crtc_supports_ips(crtc)) return false; - if (pipe_config->pipe_bpp > 24) + if (!i915_modparams.enable_ips) return false; - /* HSW can handle pixel rate up to cdclk? */ - if (IS_HASWELL(dev_priv)) - return true; + if (crtc_state->pipe_bpp > 24) + return false; /* * We compare against max which means we must take @@ -6215,19 +6226,41 @@ static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv, * * Should measure whether using a lower cdclk w/o IPS */ - return pipe_config->pixel_rate <= - dev_priv->max_cdclk_freq * 95 / 100; + if (IS_BROADWELL(dev_priv) && + crtc_state->pixel_rate > dev_priv->max_cdclk_freq * 95 / 100) + return false; + + return true; } -static void hsw_compute_ips_config(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = + to_i915(crtc_state->base.crtc->dev); + struct intel_atomic_state *intel_state = + to_intel_atomic_state(crtc_state->base.state); - pipe_config->ips_enabled = i915_modparams.enable_ips && - hsw_crtc_supports_ips(crtc) && - pipe_config_supports_ips(dev_priv, pipe_config); + if (!hsw_crtc_state_ips_capable(crtc_state)) + return false; + + if (crtc_state->ips_force_disable) + return false; + + /* + * FIXME IPS should be fine as long as one plane is + * enabled, but in practice it seems to have problems + * when going from primary only to sprite only and vice + * versa. + */ + if (!(crtc_state->active_planes & BIT(PLANE_PRIMARY))) + return false; + + /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ + if (IS_BROADWELL(dev_priv) && + crtc_state->pixel_rate > intel_state->cdclk.logical.cdclk * 95 / 100) + return false; + + return true; } static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) @@ -6345,9 +6378,6 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, intel_crtc_compute_pixel_rate(pipe_config); - if (HAS_IPS(dev_priv)) - hsw_compute_ips_config(crtc, pipe_config); - if (pipe_config->has_pch_encoder) return ironlake_fdi_compute_config(crtc, pipe_config); @@ -9183,6 +9213,19 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, ironlake_get_pfit_config(crtc, pipe_config); } + if (hsw_crtc_supports_ips(crtc)) { + if (IS_HASWELL(dev_priv)) + pipe_config->ips_enabled = I915_READ(IPS_CTL) & IPS_ENABLE; + else { + /* + * We cannot readout IPS state on broadwell, set to + * true so we can set it to a defined state on first + * commit. + */ + pipe_config->ips_enabled = true; + } + } + if (pipe_config->cpu_transcoder != TRANSCODER_EDP && !transcoder_is_dsi(pipe_config->cpu_transcoder)) { pipe_config->pixel_multiplier = @@ -10435,6 +10478,9 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, pipe_config); } + if (HAS_IPS(dev_priv)) + pipe_config->ips_enabled = hsw_compute_ips_config(pipe_config); + return ret; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c679df99d530..64426d3e078e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1488,6 +1488,7 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, int chv_calc_dpll_params(int refclk, struct dpll *pll_clock); bool intel_crtc_active(struct intel_crtc *crtc); +bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state); void hsw_enable_ips(const struct intel_crtc_state *crtc_state); void hsw_disable_ips(const struct intel_crtc_state *crtc_state); enum intel_display_power_domain intel_port_to_power_domain(enum port port); diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 61641d479b93..1f5cd572a7ff 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -541,8 +541,6 @@ retry: * completely disable it. */ pipe_config->ips_force_disable = enable; - if (pipe_config->ips_enabled == enable) - pipe_config->base.connectors_changed = true; } if (IS_HASWELL(dev_priv)) { -- cgit From adbe5c5cd32c732a4ea1d4c5f41714fa836d69b6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 22 Nov 2017 19:39:06 +0100 Subject: drm/i915: Enable IPS with only sprite plane visible too, v4. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This comment predates atomic, and I think with the way we currently track IPS, it's safe to enable this for the case we switch too. Changes since v1: - Keep IPS enabled when switching planes. Changes since v2: - Enable IPS when at least one plane is enabled. (Ville) Changes since v3: - Actually do what was advertised in v3, sigh! (Ville, CI) Signed-off-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20171122183906.47767-1-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_display.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 68f101c0e909..601c23be8264 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6246,13 +6246,8 @@ static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state) if (crtc_state->ips_force_disable) return false; - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - if (!(crtc_state->active_planes & BIT(PLANE_PRIMARY))) + /* IPS should be fine as long as at least one plane is enabled. */ + if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR))) return false; /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ -- cgit From 8bd099a71db660f3bd000dd2256032dbf49a6e84 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Nov 2017 12:52:53 +0000 Subject: drm/i915: Tidy up signed/unsigned comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/i915_irq.c|3096 col 29| error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] Signed-off-by: Chris Wilson Cc: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171130125253.21405-1-chris@chris-wilson.co.uk Reviewed-by: Michal Wajdeczko --- drivers/gpu/drm/i915/i915_irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4fb183ae7a07..7cac07db89b9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3068,7 +3068,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) i9xx_pipestat_irq_reset(dev_priv); GEN3_IRQ_RESET(VLV_); - dev_priv->irq_mask = ~0; + dev_priv->irq_mask = ~0u; } static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) @@ -3093,7 +3093,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | I915_LPE_PIPE_C_INTERRUPT; - WARN_ON(dev_priv->irq_mask != ~0); + WARN_ON(dev_priv->irq_mask != ~0u); dev_priv->irq_mask = ~enable_mask; -- cgit From b5e0a9418e09a7b6df1728a26832c7c34aa1adf8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Dec 2017 00:15:36 +0000 Subject: drm/i915: Set fake_vma.size as well as fake_vma.node.size for capture When capturing the bo, we allocate an error object with an array of min(vma->size, vma->node.size) pages, plus a bit for compression overhead. However, when creating the fake vma to describe the bo, only one of the sizes was filled in, resulting in a too small array. Through my and CI testing, this was sufficient for the mostly empty NULL context as it compressed well (or the out-of-bounds access simply didn't cause an issue). However, in real workloads on Cannonlake, we were overflowing that array and causing havoc with the random memory corruption. Reported-by: Rafael Antognolli Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103964 Fixes: 4e90a6e22272 ("drm/i915: Record default HW state in the GPU error state") Signed-off-by: Chris Wilson Cc: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Tested-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20171201001536.13941-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_gpu_error.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 876be8f1d930..48418fb81066 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1424,6 +1424,7 @@ capture_object(struct drm_i915_private *dev_priv, if (obj && i915_gem_object_has_pages(obj)) { struct i915_vma fake = { .node = { .start = U64_MAX, .size = obj->base.size }, + .size = obj->base.size, .pages = obj->mm.pages, .obj = obj, }; -- cgit From b37aef5f1b5a4788eca662de6cb33e1521a7e404 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Nov 2017 09:42:31 +0000 Subject: drm/i915/selftests: Wake the device before executing requests on the GPU To execute a requests requires us to have first woken the device, using the rpm wakeref (as the request needs to write to hardware to setup the context/ppGTT and execute on the GPU). So call intel_runtime_pm_get() around queuing the request; the request itself will then carry a wakeref until completion. References: https://bugs.freedesktop.org/show_bug.cgi?id=103994 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20171130094231.10405-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index ec1eff739e01..56a803d11916 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -376,7 +376,9 @@ static int igt_ctx_exec(void *arg) } } + intel_runtime_pm_get(i915); err = gpu_fill(obj, ctx, engine, dw); + intel_runtime_pm_put(i915); if (err) { pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n", ndwords, dw, max_dwords(obj), -- cgit From 20ff39fa4312dfaee8d1314a208e6a5a3ee51cbc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 18:43:01 +0200 Subject: drm/i915: Disable DP audio for g4x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently g4x doesn't support audio over DP. Bspec lists the bit as "Reserved for Audio Output Enable", and empirical evidence tells us that the bit won't stick. So stop trying to enable DP audio on g4x. Link: https://patchwork.freedesktop.org/patch/msgid/20171129164303.18793-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103989 Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c603d4c903e1..01c848bbd795 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1643,7 +1643,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, pipe_config->has_pch_encoder = true; pipe_config->has_drrs = false; - if (port == PORT_A) + if (IS_G4X(dev_priv) || port == PORT_A) pipe_config->has_audio = false; else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) pipe_config->has_audio = intel_dp->has_audio; -- cgit From 68ec0736a00d38f2ac4907ffe8ad141ead15c075 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 18:43:02 +0200 Subject: drm/i915: Don't add the "force audio" property to DP connectors that don't support audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in adding the "force audio" property to DP connectors that don't support audio (g4x or port A). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129164303.18793-2-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 01c848bbd795..bf93991c2fcc 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5180,8 +5180,11 @@ static void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->dev); + enum port port = dp_to_dig_port(intel_dp)->base.port; + + if (!IS_G4X(dev_priv) && port != PORT_A) + intel_attach_force_audio_property(connector); - intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); if (intel_dp_is_edp(intel_dp)) { -- cgit From 2085cc5d3ccdc804eb320d1403be31cf28650552 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 18:43:03 +0200 Subject: drm/i915: Fix has_audio readout for DDI A MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Transcoder EDP does not support audio. Let's not try to read the state of the audio enable bit HSW_AUD_PIN_ELD_CP_VLD based on the pipe when using transcoder EDP. While at it make the function static and flatten it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129164303.18793-3-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_ddi.c | 20 ++++++++++---------- drivers/gpu/drm/i915/intel_drv.h | 2 -- 2 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index eff3b51872eb..48ba9b7fdc78 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2513,17 +2513,17 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) udelay(600); } -bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc) +static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, + enum transcoder cpu_transcoder) { - u32 temp; + if (cpu_transcoder == TRANSCODER_EDP) + return false; - if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { - temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); - if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) - return true; - } - return false; + if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) + return false; + + return I915_READ(HSW_AUD_PIN_ELD_CP_VLD) & + AUDIO_OUTPUT_ENABLE(cpu_transcoder); } void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, @@ -2616,7 +2616,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, } pipe_config->has_audio = - intel_ddi_is_audio_enabled(dev_priv, intel_crtc); + intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 64426d3e078e..82d637d20d5d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1288,8 +1288,6 @@ intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state); void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state); void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp); bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); -bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, - struct intel_crtc *intel_crtc); void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config); -- cgit From 5816d9cbc0a0fbf232fe297cefcb85361a3cde90 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 14:54:11 +0200 Subject: drm/i915: Fix deadlock in i830_disable_pipe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i830_disable_pipe() gets called from the power well code, and thus we're already holding the power domain mutex. That means we can't call plane->get_hw_state() as it will also try to grab the same mutex and will thus deadlock. Replace the assert_plane() calls (which calls ->get_hw_state()) with just raw register reads in i830_disable_pipe(). As a bonus we can now get a warning if plane C is enabled even though we don't even expose it as a drm plane. v2: Do a separate WARN_ON() for each plane (Chris) Cc: Chris Wilson Reviewed-by: Chris Wilson Fixes: 51f5a0963984 ("drm/i915: Add .get_hw_state() method for planes") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129125411.29055-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 601c23be8264..7a1f60869b24 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14770,8 +14770,11 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n", pipe_name(pipe)); - assert_planes_disabled(intel_get_crtc_for_pipe(dev_priv, PIPE_A)); - assert_planes_disabled(intel_get_crtc_for_pipe(dev_priv, PIPE_B)); + WARN_ON(I915_READ(DSPCNTR(PLANE_A)) & DISPLAY_PLANE_ENABLE); + WARN_ON(I915_READ(DSPCNTR(PLANE_B)) & DISPLAY_PLANE_ENABLE); + WARN_ON(I915_READ(DSPCNTR(PLANE_C)) & DISPLAY_PLANE_ENABLE); + WARN_ON(I915_READ(CURCNTR(PIPE_A)) & CURSOR_MODE); + WARN_ON(I915_READ(CURCNTR(PIPE_B)) & CURSOR_MODE); I915_WRITE(PIPECONF(pipe), 0); POSTING_READ(PIPECONF(pipe)); -- cgit From 8fedd64dabc86d0f31a0d1e152be3aa23c323553 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 17:37:30 +0200 Subject: drm/i915: Fix vblank timestamp/frame counter jumps on gen2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously I was under the impression that the scanline counter reads 0 when the pipe is off. Turns out that's not correct, and instead the scanline counter simply stops when the pipe stops, and it retains it's last value until the pipe starts up again, at which point the scanline counter jumps to vblank start. These jumps can cause the timestamp to jump backwards by one frame. Since we use the timestamps to guesstimage also the frame counter value on gen2, that would cause the frame counter to also jump backwards, which leads to a massice difference from the previous value. The end result is that flips/vblank events don't appear to complete as they're stuck waiting for the frame counter to catch up to that massive difference. Fix the problem properly by actually making sure the scanline counter has started to move before we assume that it's safe to enable vblank processing. v2: Less pointless duplication in the code (Chris) Cc: stable@vger.kernel.org Cc: Daniel Vetter Cc: Chris Wilson Reviewed-by: Chris Wilson Fixes: b7792d8b54cc ("drm/i915: Wait for pipe to start before sampling vblank timestamps on gen2") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129153732.3612-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 51 +++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7a1f60869b24..f712418594ed 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -998,7 +998,8 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, return crtc->config->cpu_transcoder; } -static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe) +static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, + enum pipe pipe) { i915_reg_t reg = PIPEDSL(pipe); u32 line1, line2; @@ -1013,7 +1014,28 @@ static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe) msleep(5); line2 = I915_READ(reg) & line_mask; - return line1 == line2; + return line1 != line2; +} + +static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + + /* Wait for the display line to settle/start moving */ + if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) + DRM_ERROR("pipe %c scanline %s wait timed out\n", + pipe_name(pipe), onoff(state)); +} + +static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, false); +} + +static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) +{ + wait_for_pipe_scanline_moving(crtc, true); } /* @@ -1036,7 +1058,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; - enum pipe pipe = crtc->pipe; if (INTEL_GEN(dev_priv) >= 4) { i915_reg_t reg = PIPECONF(cpu_transcoder); @@ -1047,9 +1068,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc) 100)) WARN(1, "pipe_off wait timed out\n"); } else { - /* Wait for the display line to settle */ - if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100)) - WARN(1, "pipe_off wait timed out\n"); + intel_wait_for_pipe_scanline_stopped(crtc); } } @@ -1862,15 +1881,14 @@ static void intel_enable_pipe(struct intel_crtc *crtc) POSTING_READ(reg); /* - * Until the pipe starts DSL will read as 0, which would cause - * an apparent vblank timestamp jump, which messes up also the - * frame count when it's derived from the timestamps. So let's - * wait for the pipe to start properly before we call - * drm_crtc_vblank_on() + * Until the pipe starts PIPEDSL reads will return a stale value, + * which causes an apparent vblank timestamp jump when PIPEDSL + * resets to its proper value. That also messes up the frame count + * when it's derived from the timestamps. So let's wait for the + * pipe to start properly before we call drm_crtc_vblank_on() */ - if (dev->max_vblank_count == 0 && - wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50)) - DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe)); + if (dev->max_vblank_count == 0) + intel_wait_for_pipe_scanline_moving(crtc); } /** @@ -14767,6 +14785,8 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); + DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n", pipe_name(pipe)); @@ -14779,8 +14799,7 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) I915_WRITE(PIPECONF(pipe), 0); POSTING_READ(PIPECONF(pipe)); - if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100)) - DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe)); + intel_wait_for_pipe_scanline_stopped(crtc); I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS); POSTING_READ(DPLL(pipe)); -- cgit From d5fb43cb7fffc8f6863d68456252bcf3f06a070a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 17:37:31 +0200 Subject: drm/i915: Wait for pipe to start on i830 as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should make sure the pipe has fully started when we enable it from the i830 "power well". Otherwise theoretically i830 could also hit problems with vblank timestamps jumping around (since we skip the wait during modeset on i830). Additionally moving planes between the pipes etc. might not work correctly until both pipes are actually up and running. v2: Less pointless duplication in the code (Chris) Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129153732.3612-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f712418594ed..7678caa81727 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14718,6 +14718,7 @@ int intel_modeset_init(struct drm_device *dev) void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) { + struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); /* 640x480@60Hz, ~25175 kHz */ struct dpll clock = { .m1 = 18, @@ -14781,6 +14782,8 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) I915_WRITE(PIPECONF(pipe), PIPECONF_ENABLE | PIPECONF_PROGRESSIVE); POSTING_READ(PIPECONF(pipe)); + + intel_wait_for_pipe_scanline_moving(crtc); } void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) -- cgit From 4972f70a202eeb3c270e182c8b83fc271288076c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 17:37:32 +0200 Subject: drm/i915: Pass crtc state to intel_pipe_{enable,disable}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the crtc->config usages from within intel_pipe_{enable,disable}() by passing in the appropriate crtc state. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129153732.3612-3-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_display.c | 76 +++++++++++------------------------- 1 file changed, 23 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7678caa81727..47a2f6acee50 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1038,28 +1038,14 @@ static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) wait_for_pipe_scanline_moving(crtc, true); } -/* - * intel_wait_for_pipe_off - wait for pipe to turn off - * @crtc: crtc whose pipe to wait for - * - * After disabling a pipe, we can't wait for vblank in the usual way, - * spinning on the vblank interrupt status bit, since we won't actually - * see an interrupt when the pipe is disabled. - * - * On Gen4 and above: - * wait for the pipe register state bit to turn off - * - * Otherwise: - * wait for the display line value to settle (it usually - * ends up stopping at the start of the next frame). - * - */ -static void intel_wait_for_pipe_off(struct intel_crtc *crtc) +static void +intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; if (INTEL_GEN(dev_priv) >= 4) { + enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; i915_reg_t reg = PIPECONF(cpu_transcoder); /* Wait for the Pipe State to go off */ @@ -1828,19 +1814,12 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) return crtc->pipe; } -/** - * intel_enable_pipe - enable a pipe, asserting requirements - * @crtc: crtc responsible for the pipe - * - * Enable @crtc's pipe, making sure that various hardware specific requirements - * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. - */ -static void intel_enable_pipe(struct intel_crtc *crtc) +static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; - enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; i915_reg_t reg; u32 val; @@ -1854,12 +1833,12 @@ static void intel_enable_pipe(struct intel_crtc *crtc) * need the check. */ if (HAS_GMCH_DISPLAY(dev_priv)) { - if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI)) + if (intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI)) assert_dsi_pll_enabled(dev_priv); else assert_pll_enabled(dev_priv, pipe); } else { - if (crtc->config->has_pch_encoder) { + if (new_crtc_state->has_pch_encoder) { /* if driving the PCH, we need FDI enabled */ assert_fdi_rx_pll_enabled(dev_priv, intel_crtc_pch_transcoder(crtc)); @@ -1887,24 +1866,15 @@ static void intel_enable_pipe(struct intel_crtc *crtc) * when it's derived from the timestamps. So let's wait for the * pipe to start properly before we call drm_crtc_vblank_on() */ - if (dev->max_vblank_count == 0) + if (dev_priv->drm.max_vblank_count == 0) intel_wait_for_pipe_scanline_moving(crtc); } -/** - * intel_disable_pipe - disable a pipe, asserting requirements - * @crtc: crtc whose pipes is to be disabled - * - * Disable the pipe of @crtc, making sure that various hardware - * specific requirements are met, if applicable, e.g. plane - * disabled, panel fitter off, etc. - * - * Will wait until the pipe has shut down before returning. - */ -static void intel_disable_pipe(struct intel_crtc *crtc) +static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; + enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; enum pipe pipe = crtc->pipe; i915_reg_t reg; u32 val; @@ -1926,7 +1896,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc) * Double wide has implications for planes * so best keep it disabled when not needed. */ - if (crtc->config->double_wide) + if (old_crtc_state->double_wide) val &= ~PIPECONF_DOUBLE_WIDE; /* Don't disable pipe or pipe PLLs if needed */ @@ -1935,7 +1905,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc) I915_WRITE(reg, val); if ((val & PIPECONF_ENABLE) == 0) - intel_wait_for_pipe_off(crtc); + intel_wait_for_pipe_off(old_crtc_state); } static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv) @@ -5354,7 +5324,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(old_intel_state, intel_crtc->config); - intel_enable_pipe(intel_crtc); + intel_enable_pipe(pipe_config); if (intel_crtc->config->has_pch_encoder) ironlake_pch_enable(pipe_config); @@ -5473,7 +5443,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) - intel_enable_pipe(intel_crtc); + intel_enable_pipe(pipe_config); if (intel_crtc->config->has_pch_encoder) lpt_pch_enable(pipe_config); @@ -5539,7 +5509,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); - intel_disable_pipe(intel_crtc); + intel_disable_pipe(old_crtc_state); ironlake_pfit_disable(intel_crtc, false); @@ -5591,7 +5561,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) - intel_disable_pipe(intel_crtc); + intel_disable_pipe(old_crtc_state); if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST)) intel_ddi_set_vc_payload_alloc(intel_crtc->config, false); @@ -5769,7 +5739,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, dev_priv->display.initial_watermarks(old_intel_state, pipe_config); - intel_enable_pipe(intel_crtc); + intel_enable_pipe(pipe_config); assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); @@ -5828,7 +5798,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->config); else intel_update_watermarks(intel_crtc); - intel_enable_pipe(intel_crtc); + intel_enable_pipe(pipe_config); assert_vblank_disabled(crtc); drm_crtc_vblank_on(crtc); @@ -5872,7 +5842,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); - intel_disable_pipe(intel_crtc); + intel_disable_pipe(old_crtc_state); i9xx_pfit_disable(intel_crtc); -- cgit From 050213893307e661933a315a3c6e82658a68ffee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 29 Nov 2017 20:08:47 +0200 Subject: drm/i915: Interlaced DP output doesn't work on VLV/CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reject interlaced modes on VLV/CHV DP outputs. This simply does not work correctly in the hardware. We do get some output, but it's quite corrupted. The available documentation fails to mention this fact. I contacted some hardware people who eventually managed to locate the relevant HSD for VLV, which was resolved by declaring interlaced DP output as not supported. The HSD was never cloned for CHV even though it inherited most of the hardware and thus has the same problems with interlaced DP output. Cc: Dennis Vshivkov Reported-by: Dennis Vshivkov Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103922 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171129180847.30613-1-ville.syrjala@linux.intel.com Acked-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index bf93991c2fcc..90e8f35cc886 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1677,6 +1677,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, conn_state->scaling_mode); } + if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && + adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) + return false; + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) return false; @@ -6093,7 +6097,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, drm_connector_init(dev, connector, &intel_dp_connector_funcs, type); drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); - connector->interlace_allowed = true; + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) + connector->interlace_allowed = true; connector->doublescan_allowed = 0; intel_dp_init_connector_port_info(intel_dig_port); -- cgit From f7096d40eea84d32eb1e3b0f2b4407167aae9a83 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Dec 2017 12:20:11 +0000 Subject: drm/i915: Sleep and retry a GPU reset if at first we don't succeed As we declare the GPU wedged if the reset fails, such a failure is quite terminal. Before taking that drastic action, let's sleep first and try active, in the hope that the hardware has quietened down and is then able to reset. After a few such attempts, it is fair to say that the HW is truly wedged. v2: Always print the failure message now, we precheck whether resets are disabled. References: https://bugs.freedesktop.org/show_bug.cgi?id=104007 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171201122011.16841-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/i915_drv.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1c419893e3a9..43fbff48a133 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1877,7 +1877,9 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) { struct i915_gpu_error *error = &i915->gpu_error; int ret; + int i; + might_sleep(); lockdep_assert_held(&i915->drm.struct_mutex); GEM_BUG_ON(!test_bit(I915_RESET_BACKOFF, &error->flags)); @@ -1900,12 +1902,20 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) goto error; } - ret = intel_gpu_reset(i915, ALL_ENGINES); + if (!intel_has_gpu_reset(i915)) { + DRM_DEBUG_DRIVER("GPU reset disabled\n"); + goto error; + } + + for (i = 0; i < 3; i++) { + ret = intel_gpu_reset(i915, ALL_ENGINES); + if (ret == 0) + break; + + msleep(100); + } if (ret) { - if (ret != -ENODEV) - DRM_ERROR("Failed to reset chip: %i\n", ret); - else - DRM_DEBUG_DRIVER("GPU reset disabled\n"); + dev_err(i915->drm.dev, "Failed to reset chip\n"); goto error; } -- cgit From fb6db0f5bf1d4d3a4af6242e287fa795221ec5b8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 1 Dec 2017 11:30:30 +0000 Subject: drm/i915: Remove unsafe i915.enable_rc6 It has been many years since the last confirmed sighting (and fix) of an RC6 related bug (usually a system hang). Remove the parameter to stop users from setting dangerous values, as they often set it during triage and end up disabling the entire runtime pm instead (the option is not a fine scalpel!). Furthermore, it allows users to set known dangerous values which were intended for testing and not for production use. For testing, we can always patch in the required setting without having to expose ourselves to random abuse. v2: Fixup NEEDS_WaRsDisableCoarsePowerGating fumble, and document the lack of ilk support better. v3: Clear intel_info->rc6p if we don't support rc6 itself. Signed-off-by: Chris Wilson Cc: Rodrigo Vivi Cc: Joonas Lahtinen Cc: Jani Nikula Cc: Imre Deak Cc: Daniel Vetter Acked-by: Daniel Vetter Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20171201113030.18360-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_params.c | 7 -- drivers/gpu/drm/i915/i915_params.h | 1 - drivers/gpu/drm/i915/i915_pci.c | 2 + drivers/gpu/drm/i915/i915_pmu.c | 4 +- drivers/gpu/drm/i915/i915_sysfs.c | 13 +++- drivers/gpu/drm/i915/intel_drv.h | 5 -- drivers/gpu/drm/i915/intel_guc.c | 3 +- drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++------------------------- drivers/gpu/drm/i915/intel_uncore.c | 3 - 11 files changed, 64 insertions(+), 120 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 43fbff48a133..962d7c7c799c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2527,7 +2527,7 @@ static int intel_runtime_suspend(struct device *kdev) struct drm_i915_private *dev_priv = to_i915(dev); int ret; - if (WARN_ON_ONCE(!(dev_priv->gt_pm.rc6.enabled && intel_rc6_enabled()))) + if (WARN_ON_ONCE(!(dev_priv->gt_pm.rc6.enabled && HAS_RC6(dev_priv)))) return -ENODEV; if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bddd65839f60..e8dc7b77ac96 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3213,8 +3213,10 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi) #define HAS_FPGA_DBG_UNCLAIMED(dev_priv) ((dev_priv)->info.has_fpga_dbg) #define HAS_PSR(dev_priv) ((dev_priv)->info.has_psr) + #define HAS_RC6(dev_priv) ((dev_priv)->info.has_rc6) #define HAS_RC6p(dev_priv) ((dev_priv)->info.has_rc6p) +#define HAS_RC6pp(dev_priv) (false) /* HW was never validated */ #define HAS_CSR(dev_priv) ((dev_priv)->info.has_csr) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 3328147b4863..7bc538687871 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -46,13 +46,6 @@ i915_param_named_unsafe(panel_ignore_lid, int, 0600, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); -i915_param_named_unsafe(enable_rc6, int, 0400, - "Enable power-saving render C-state 6. " - "Different stages can be selected via bitmask values " - "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). " - "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " - "default: -1 (use per-chip default)"); - i915_param_named_unsafe(enable_dc, int, 0400, "Enable power-saving display C-states. " "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 8321bd86cba5..c48c88bb95e8 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -34,7 +34,6 @@ param(int, lvds_channel_mode, 0) \ param(int, panel_use_ssc, -1) \ param(int, vbt_sdvo_panel_type, -1) \ - param(int, enable_rc6, -1) \ param(int, enable_dc, -1) \ param(int, enable_fbc, -1) \ param(int, enable_ppgtt, -1) \ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 6458c309c039..fa67d3dde20e 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -209,6 +209,8 @@ static const struct intel_device_info intel_gm45_info __initconst = { .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ .has_snoop = true, \ + /* ilk does support rc6, but we do not implement [power] contexts */ \ + .has_rc6 = 0, \ GEN_DEFAULT_PIPEOFFSETS, \ GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index e8e2faf4982f..55a8a1e29424 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -413,12 +413,12 @@ static u64 __i915_pmu_event_read(struct perf_event *event) IS_VALLEYVIEW(i915) ? VLV_GT_RENDER_RC6 : GEN6_GT_GFX_RC6); - if (HAS_RC6p(i915)) { + if (HAS_RC6p(i915)) val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); + if (HAS_RC6pp(i915)) val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); - } intel_runtime_pm_put(i915); break; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index c290cb600eea..c74a20b80182 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -54,7 +54,18 @@ static u32 calc_residency(struct drm_i915_private *dev_priv, static ssize_t show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%x\n", intel_rc6_enabled()); + struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + unsigned int mask; + + mask = 0; + if (HAS_RC6(dev_priv)) + mask |= BIT(0); + if (HAS_RC6p(dev_priv)) + mask |= BIT(1); + if (HAS_RC6pp(dev_priv)) + mask |= BIT(2); + + return snprintf(buf, PAGE_SIZE, "%x\n", mask); } static ssize_t diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 82d637d20d5d..30f791f89d64 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1908,15 +1908,10 @@ bool skl_ddb_allocation_overlaps(struct drm_i915_private *dev_priv, const struct skl_ddb_entry *ddb, int ignore); bool ilk_disable_lp_wm(struct drm_device *dev); -int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, struct intel_crtc_state *cstate); void intel_init_ipc(struct drm_i915_private *dev_priv); void intel_enable_ipc(struct drm_i915_private *dev_priv); -static inline int intel_rc6_enabled(void) -{ - return i915_modparams.enable_rc6; -} /* intel_sdvo.c */ bool intel_sdvo_init(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c index 823d0c2e9ad2..d08e760252d4 100644 --- a/drivers/gpu/drm/i915/intel_guc.c +++ b/drivers/gpu/drm/i915/intel_guc.c @@ -231,8 +231,7 @@ int intel_guc_sample_forcewake(struct intel_guc *guc) action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE; /* WaRsDisableCoarsePowerGating:skl,bxt */ - if (!intel_rc6_enabled() || - NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) + if (!HAS_RC6(dev_priv) || NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) action[1] = 0; else /* bit 0 and 1 are for Render and Media domain separately */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a80c322c5b43..67f326230a7e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -52,9 +52,6 @@ * which brings the most power savings; deeper states save more power, but * require higher latency to switch to and wake up. */ -#define INTEL_RC6_ENABLE (1<<0) -#define INTEL_RC6p_ENABLE (1<<1) -#define INTEL_RC6pp_ENABLE (1<<2) static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) { @@ -6417,26 +6414,6 @@ static void valleyview_disable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_CONTROL, 0); } -static void intel_print_rc6_info(struct drm_i915_private *dev_priv, u32 mode) -{ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - if (mode & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1))) - mode = GEN6_RC_CTL_RC6_ENABLE; - else - mode = 0; - } - if (HAS_RC6p(dev_priv)) - DRM_DEBUG_DRIVER("Enabling RC6 states: " - "RC6 %s RC6p %s RC6pp %s\n", - onoff(mode & GEN6_RC_CTL_RC6_ENABLE), - onoff(mode & GEN6_RC_CTL_RC6p_ENABLE), - onoff(mode & GEN6_RC_CTL_RC6pp_ENABLE)); - - else - DRM_DEBUG_DRIVER("Enabling RC6 states: RC6 %s\n", - onoff(mode & GEN6_RC_CTL_RC6_ENABLE)); -} - static bool bxt_check_bios_rc6_setup(struct drm_i915_private *dev_priv) { struct i915_ggtt *ggtt = &dev_priv->ggtt; @@ -6499,42 +6476,30 @@ static bool bxt_check_bios_rc6_setup(struct drm_i915_private *dev_priv) return enable_rc6; } -int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6) +static bool sanitize_rc6(struct drm_i915_private *i915) { - /* No RC6 before Ironlake and code is gone for ilk. */ - if (INTEL_INFO(dev_priv)->gen < 6) - return 0; + struct intel_device_info *info = mkwrite_device_info(i915); - if (!enable_rc6) - return 0; + /* Powersaving is controlled by the host when inside a VM */ + if (intel_vgpu_active(i915)) + info->has_rc6 = 0; - if (IS_GEN9_LP(dev_priv) && !bxt_check_bios_rc6_setup(dev_priv)) { + if (info->has_rc6 && + IS_GEN9_LP(i915) && !bxt_check_bios_rc6_setup(i915)) { DRM_INFO("RC6 disabled by BIOS\n"); - return 0; + info->has_rc6 = 0; } - /* Respect the kernel parameter if it is set */ - if (enable_rc6 >= 0) { - int mask; - - if (HAS_RC6p(dev_priv)) - mask = INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE | - INTEL_RC6pp_ENABLE; - else - mask = INTEL_RC6_ENABLE; - - if ((enable_rc6 & mask) != enable_rc6) - DRM_DEBUG_DRIVER("Adjusting RC6 mask to %d " - "(requested %d, valid %d)\n", - enable_rc6 & mask, enable_rc6, mask); - - return enable_rc6 & mask; - } - - if (IS_IVYBRIDGE(dev_priv)) - return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); + /* + * We assume that we do not have any deep rc6 levels if we don't have + * have the previous rc6 level supported, i.e. we use HAS_RC6() + * as the initial coarse check for rc6 in general, moving on to + * progressively finer/deeper levels. + */ + if (!info->has_rc6 && info->has_rc6p) + info->has_rc6p = 0; - return INTEL_RC6_ENABLE; + return info->has_rc6; } static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) @@ -6627,7 +6592,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 rc6_mode, rc6_mask = 0; + u32 rc6_mode; /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -6668,9 +6633,6 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) I915_WRITE(GEN9_RENDER_PG_IDLE_HYSTERESIS, 25); /* 3a: Enable RC6 */ - if (intel_rc6_enabled() & INTEL_RC6_ENABLE) - rc6_mask = GEN6_RC_CTL_RC6_ENABLE; - DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */ /* WaRsUseTimeoutMode:cnl (pre-prod) */ @@ -6680,7 +6642,9 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) rc6_mode = GEN6_RC_CTL_EI_MODE(1); I915_WRITE(GEN6_RC_CONTROL, - GEN6_RC_CTL_HW_ENABLE | rc6_mode | rc6_mask); + GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_RC6_ENABLE | + rc6_mode); /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. @@ -6689,8 +6653,8 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) if (NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) I915_WRITE(GEN9_PG_ENABLE, 0); else - I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? - (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0); + I915_WRITE(GEN9_PG_ENABLE, + GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } @@ -6699,7 +6663,6 @@ static void gen8_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - uint32_t rc6_mask = 0; /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -6721,13 +6684,11 @@ static void gen8_enable_rc6(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ /* 3: Enable RC6 */ - if (intel_rc6_enabled() & INTEL_RC6_ENABLE) - rc6_mask = GEN6_RC_CTL_RC6_ENABLE; - intel_print_rc6_info(dev_priv, rc6_mask); - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN7_RC_CTL_TO_MODE | - rc6_mask); + I915_WRITE(GEN6_RC_CONTROL, + GEN6_RC_CTL_HW_ENABLE | + GEN7_RC_CTL_TO_MODE | + GEN6_RC_CTL_RC6_ENABLE); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } @@ -6776,9 +6737,8 @@ static void gen6_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 rc6vids, rc6_mask = 0; + u32 rc6vids, rc6_mask; u32 gtfifodbg; - int rc6_mode; int ret; I915_WRITE(GEN6_RC_STATE, 0); @@ -6813,22 +6773,12 @@ static void gen6_enable_rc6(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6p_THRESHOLD, 150000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ - /* Check if we are enabling RC6 */ - rc6_mode = intel_rc6_enabled(); - if (rc6_mode & INTEL_RC6_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; - /* We don't use those on Haswell */ - if (!IS_HASWELL(dev_priv)) { - if (rc6_mode & INTEL_RC6p_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; - - if (rc6_mode & INTEL_RC6pp_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; - } - - intel_print_rc6_info(dev_priv, rc6_mask); - + rc6_mask = GEN6_RC_CTL_RC6_ENABLE; + if (HAS_RC6p(dev_priv)) + rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; + if (HAS_RC6pp(dev_priv)) + rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; I915_WRITE(GEN6_RC_CONTROL, rc6_mask | GEN6_RC_CTL_EI_MODE(1) | @@ -7271,7 +7221,7 @@ static void cherryview_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 gtfifodbg, rc6_mode = 0, pcbr; + u32 gtfifodbg, rc6_mode, pcbr; gtfifodbg = I915_READ(GTFIFODBG) & ~(GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV | GT_FIFO_FREE_ENTRIES_CHV); @@ -7312,10 +7262,9 @@ static void cherryview_enable_rc6(struct drm_i915_private *dev_priv) pcbr = I915_READ(VLV_PCBR); /* 3: Enable RC6 */ - if ((intel_rc6_enabled() & INTEL_RC6_ENABLE) && - (pcbr >> VLV_PCBR_ADDR_SHIFT)) + rc6_mode = 0; + if (pcbr >> VLV_PCBR_ADDR_SHIFT) rc6_mode = GEN7_RC_CTL_TO_MODE; - I915_WRITE(GEN6_RC_CONTROL, rc6_mode); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); @@ -7367,7 +7316,7 @@ static void valleyview_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 gtfifodbg, rc6_mode = 0; + u32 gtfifodbg; valleyview_check_pctx(dev_priv); @@ -7400,12 +7349,8 @@ static void valleyview_enable_rc6(struct drm_i915_private *dev_priv) VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); - if (intel_rc6_enabled() & INTEL_RC6_ENABLE) - rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; - - intel_print_rc6_info(dev_priv, rc6_mode); - - I915_WRITE(GEN6_RC_CONTROL, rc6_mode); + I915_WRITE(GEN6_RC_CONTROL, + GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } @@ -7932,7 +7877,7 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) * RPM depends on RC6 to save restore the GT HW context, so make RC6 a * requirement. */ - if (!i915_modparams.enable_rc6) { + if (!sanitize_rc6(dev_priv)) { DRM_INFO("RC6 disabled, disabling runtime PM support\n"); intel_runtime_pm_get(dev_priv); } @@ -7985,7 +7930,7 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv)) valleyview_cleanup_gt_powersave(dev_priv); - if (!i915_modparams.enable_rc6) + if (!HAS_RC6(dev_priv)) intel_runtime_pm_put(dev_priv); } @@ -8152,7 +8097,8 @@ void intel_enable_gt_powersave(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->pcu_lock); - intel_enable_rc6(dev_priv); + if (HAS_RC6(dev_priv)) + intel_enable_rc6(dev_priv); intel_enable_rps(dev_priv); if (HAS_LLC(dev_priv)) intel_enable_llc_pstate(dev_priv); @@ -9444,7 +9390,7 @@ u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, u64 time_hw; u32 mul, div; - if (!intel_rc6_enabled()) + if (!HAS_RC6(dev_priv)) return 0; /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index b4621271e7a2..89547b614aa6 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -565,9 +565,6 @@ void intel_uncore_runtime_resume(struct drm_i915_private *dev_priv) void intel_uncore_sanitize(struct drm_i915_private *dev_priv) { - i915_modparams.enable_rc6 = - sanitize_rc6_option(dev_priv, i915_modparams.enable_rc6); - /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_sanitize_gt_powersave(dev_priv); } -- cgit From 23a7068ec581fcc6fb61039448632d25987b1fae Mon Sep 17 00:00:00 2001 From: James Ausmus Date: Thu, 30 Nov 2017 18:17:00 -0800 Subject: drm/i915/cnl: Mask previous DDI - PLL mapping Without masking out the old value, we can end up pointing the DDI to a disabled PLL, which makes the system fall over. Mask out the previous value before setting the PLL to DDI mapping. This can be observed by running igt/testdisplay with both an eDP and HDMI/DP output active. v2: Add the Bugzilla link Fixes: 555e38d273172 ("drm/i915/cnl: DDI - PLL mapping") Testcase: igt/testdisplay Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103997 Cc: Rodrigo Vivi Cc: Matt Atwood Signed-off-by: James Ausmus Reviewed-by: Rodrigo Vivi Tested-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20171201021700.13504-1-james.ausmus@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 48ba9b7fdc78..369f780588fb 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2098,6 +2098,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, if (IS_CANNONLAKE(dev_priv)) { /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ val = I915_READ(DPCLKA_CFGCR0); + val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->id, port); I915_WRITE(DPCLKA_CFGCR0, val); -- cgit From d65efe7c951371fbad2c426b59bbac8bf2e60662 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Fri, 1 Dec 2017 17:07:19 -0800 Subject: drm/i915: Update DRIVER_DATE to 20171201 Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e8dc7b77ac96..594fd14e66c5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20171117" -#define DRIVER_TIMESTAMP 1510958822 +#define DRIVER_DATE "20171201" +#define DRIVER_TIMESTAMP 1512176839 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit