From fd10e2ce9905030d922e179a8047a4d50daffd8e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 6 Feb 2018 09:46:33 +0000 Subject: [PATCH 001/113] drm/i915/breadcrumbs: Ignore unsubmitted signalers When a request is preempted, it is unsubmitted from the HW queue and removed from the active list of breadcrumbs. In the process, this however triggers the signaler and it may see the clear rbtree with the old, and still valid, seqno, or it may match the cleared seqno with the now zero rq->global_seqno. This confuses the signaler into action and signaling the fence. Fixes: d6a2289d9d6b ("drm/i915: Remove the preempted request from the execution queue") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: # v4.12+ Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180206094633.30181-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_breadcrumbs.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index efbc627a2a25..b955f7d7bd0f 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -588,29 +588,16 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine, spin_unlock_irq(&b->rb_lock); } -static bool signal_valid(const struct drm_i915_gem_request *request) -{ - return intel_wait_check_request(&request->signaling.wait, request); -} - static bool signal_complete(const struct drm_i915_gem_request *request) { if (!request) return false; - /* If another process served as the bottom-half it may have already - * signalled that this wait is already completed. - */ - if (intel_wait_complete(&request->signaling.wait)) - return signal_valid(request); - - /* Carefully check if the request is complete, giving time for the + /* + * Carefully check if the request is complete, giving time for the * seqno to be visible or if the GPU hung. */ - if (__i915_request_irq_complete(request)) - return true; - - return false; + return __i915_request_irq_complete(request); } static struct drm_i915_gem_request *to_signaler(struct rb_node *rb) @@ -712,6 +699,7 @@ static int intel_breadcrumbs_signaler(void *arg) &request->fence.flags)) { local_bh_disable(); dma_fence_signal(&request->fence); + GEM_BUG_ON(!i915_gem_request_completed(request)); local_bh_enable(); /* kick start the tasklets */ } From 31dade7df4605b4b40f2c026f15aa188916ea420 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 5 Feb 2018 11:58:41 +0100 Subject: [PATCH 002/113] drm/i915: Ignore minimum lines for level 0 in skl_compute_plane_wm, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to bspec, result_lines > 31 is only a maximum for latency level 1 through 7. For level 0 the number of lines is ignored, so always write 0 there to prevent overflowing the 5 bits value. This is required to make NV12 work. Changes since v1: - Rebase on top of GEN11 wm changes. It seems to use res_lines for level 0 limit calculations, but still doesn't appear to program it. Signed-off-by: Maarten Lankhorst Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20180205105841.31634-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index eb68abf6a8e9..41f26ab46501 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4596,7 +4596,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, min_disp_buf_needed = res_blocks; } - if (res_blocks >= ddb_allocation || res_lines > 31 || + if ((level > 0 && res_lines > 31) || + res_blocks >= ddb_allocation || min_disp_buf_needed >= ddb_allocation) { *enabled = false; @@ -4617,8 +4618,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, } } + /* The number of lines are ignored for the level 0 watermark. */ + *out_lines = level ? res_lines : 0; *out_blocks = res_blocks; - *out_lines = res_lines; *enabled = true; return 0; From 8ac71d1db1f8ebc68540cda131492927f46f334c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 08:43:50 +0000 Subject: [PATCH 003/113] drm/i915: Skip request serialisation if the timeline is already complete If the last request on the timeline is already complete, we do not need to emit the serialisation barriers. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180207084350.3929-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 8efa9e7a9e46..e5f87629e718 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -993,7 +993,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) lockdep_assert_held(&request->i915->drm.struct_mutex); trace_i915_gem_request_add(request); - /* Make sure that no request gazumped us - if it was allocated after + /* + * Make sure that no request gazumped us - if it was allocated after * our i915_gem_request_alloc() and called __i915_add_request() before * us, the timeline will hold its seqno which is later than ours. */ @@ -1020,7 +1021,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) WARN(err, "engine->emit_flush() failed: %d!\n", err); } - /* Record the position of the start of the breadcrumb so that + /* + * Record the position of the start of the breadcrumb so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the ring's HEAD. @@ -1029,7 +1031,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) GEM_BUG_ON(IS_ERR(cs)); request->postfix = intel_ring_offset(request, cs); - /* Seal the request and mark it as pending execution. Note that + /* + * Seal the request and mark it as pending execution. Note that * we may inspect this state, without holding any locks, during * hangcheck. Hence we apply the barrier to ensure that we do not * see a more recent value in the hws than we are tracking. @@ -1037,7 +1040,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) prev = i915_gem_active_raw(&timeline->last_request, &request->i915->drm.struct_mutex); - if (prev) { + if (prev && !i915_gem_request_completed(prev)) { i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, &request->submitq); if (engine->schedule) @@ -1057,7 +1060,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) list_add_tail(&request->ring_link, &ring->request_list); request->emitted_jiffies = jiffies; - /* Let the backend know a new request has arrived that may need + /* + * Let the backend know a new request has arrived that may need * to adjust the existing execution schedule due to a high priority * request - i.e. we may want to preempt the current request in order * to run a high priority dependency chain *before* we can execute this From c22b355ff7fd60378c55d1401530287fea4e3a96 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 08:43:49 +0000 Subject: [PATCH 004/113] drm/i915: Trim the retired request queue after submitting If we submit a request and see that the previous request on this timeline was already signaled, we first do not need to add the dependency tracker for that completed request and secondly we know that we there is then a large backlog in retiring requests affecting this timeline. Given that we just submitted more work to the HW, now would be a good time to catch up on those retirements. v2: Try to sum up the compromises involved in flushing the retirement queue after submission. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180207084350.3929-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index e5f87629e718..a8eb22a95b0f 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -1077,6 +1077,26 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) local_bh_disable(); i915_sw_fence_commit(&request->submit); local_bh_enable(); /* Kick the execlists tasklet if just scheduled */ + + /* + * In typical scenarios, we do not expect the previous request on + * the timeline to be still tracked by timeline->last_request if it + * has been completed. If the completed request is still here, that + * implies that request retirement is a long way behind submission, + * suggesting that we haven't been retiring frequently enough from + * the combination of retire-before-alloc, waiters and the background + * retirement worker. So if the last request on this timeline was + * already completed, do a catch up pass, flushing the retirement queue + * up to this client. Since we have now moved the heaviest operations + * during retirement onto secondary workers, such as freeing objects + * or contexts, retiring a bunch of requests is mostly list management + * (and cache misses), and so we should not be overly penalizing this + * client by performing excess work, though we may still performing + * work on behalf of others -- but instead we should benefit from + * improved resource management. (Well, that's the theory at least.) + */ + if (prev && i915_gem_request_completed(prev)) + i915_gem_request_retire_upto(prev); } static unsigned long local_clock_us(unsigned int *cpu) From 8177e1125235a40c1af110e37febf6bb1e7b3f81 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 11:15:45 +0000 Subject: [PATCH 005/113] drm/i915: Tidy up some error messages around reset failure On blb and pnv, we are seeing sporadic i915 0000:00:02.0: Resetting chip after gpu hang [drm:intel_gpu_reset [i915]] rcs0: timed out on STOP_RING [drm:i915_reset [i915]] *ERROR* Failed hw init on reset -5 which notably lack the actual root cause of the error. Ostensibly it should be the init_ring_common() that failed, but it's error paths are covered by DRM_ERROR. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180207111545.17078-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 6 ++++-- drivers/gpu/drm/i915/i915_gem.c | 11 ++++++++--- drivers/gpu/drm/i915/intel_ringbuffer.c | 18 +++++++++--------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9f1daf258fe..bb605e0b996c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1957,7 +1957,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) */ ret = i915_ggtt_enable_hw(i915); if (ret) { - DRM_ERROR("Failed to re-enable GGTT following reset %d\n", ret); + DRM_ERROR("Failed to re-enable GGTT following reset (%d)\n", + ret); goto error; } @@ -1974,7 +1975,8 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) */ ret = i915_gem_init_hw(i915); if (ret) { - DRM_ERROR("Failed hw init on reset %d\n", ret); + DRM_ERROR("Failed to initialise HW following reset (%d)\n", + ret); goto error; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1632f18e6a64..c1b80cd52f9e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5065,8 +5065,11 @@ static int __i915_gem_restart_engines(void *data) for_each_engine(engine, i915, id) { err = engine->init_hw(engine); - if (err) + if (err) { + DRM_ERROR("Failed to restart %s (%d)\n", + engine->name, err); return err; + } } return 0; @@ -5118,14 +5121,16 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) ret = i915_ppgtt_init_hw(dev_priv); if (ret) { - DRM_ERROR("PPGTT enable HW failed %d\n", ret); + DRM_ERROR("Enabling PPGTT failed (%d)\n", ret); goto out; } /* We can't enable contexts until all firmware is loaded */ ret = intel_uc_init_hw(dev_priv); - if (ret) + if (ret) { + DRM_ERROR("Enabling uc failed (%d)\n", ret); goto out; + } intel_mocs_init_l3cc_table(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e2085820b586..f93e4532371a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -453,13 +453,13 @@ static int init_ring_common(struct intel_engine_cs *engine) if (!stop_ring(engine)) { /* G45 ring initialization often fails to reset head to zero */ - DRM_DEBUG_KMS("%s head not reset to zero " - "ctl %08x head %08x tail %08x start %08x\n", - engine->name, - I915_READ_CTL(engine), - I915_READ_HEAD(engine), - I915_READ_TAIL(engine), - I915_READ_START(engine)); + DRM_DEBUG_DRIVER("%s head not reset to zero " + "ctl %08x head %08x tail %08x start %08x\n", + engine->name, + I915_READ_CTL(engine), + I915_READ_HEAD(engine), + I915_READ_TAIL(engine), + I915_READ_START(engine)); if (!stop_ring(engine)) { DRM_ERROR("failed to set %s head to zero " @@ -492,8 +492,8 @@ static int init_ring_common(struct intel_engine_cs *engine) /* WaClearRingBufHeadRegAtInit:ctg,elk */ if (I915_READ_HEAD(engine)) - DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", - engine->name, I915_READ_HEAD(engine)); + DRM_DEBUG_DRIVER("%s initialization failed [head=%08x], fudging\n", + engine->name, I915_READ_HEAD(engine)); intel_ring_update_space(ring); I915_WRITE_HEAD(engine, ring->head); From 1fe699e30113ed6f6e853ff44710d256072ea627 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 6 Feb 2018 18:33:11 +0000 Subject: [PATCH 006/113] drm/i915/pmu: Fix sleep under atomic in RC6 readout We are not allowed to call intel_runtime_pm_get from the PMU counter read callback since the former can sleep, and the latter is running under IRQ context. To workaround this, we record the last known RC6 and while runtime suspended estimate its increase by querying the runtime PM core timestamps. Downside of this approach is that we can temporarily lose a chunk of RC6 time, from the last PMU read-out to runtime suspend entry, but that will eventually catch up, once device comes back online and in the presence of PMU queries. Also, we have to be careful not to overshoot the RC6 estimate, so once resumed after a period of approximation, we only update the counter once it catches up. With the observation that RC6 is increasing while the device is suspended, this should not pose a problem and can only cause slight inaccuracies due clock base differences. v2: Simplify by estimating on top of PM core counters. (Imre) Signed-off-by: Tvrtko Ursulin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104943 Fixes: 6060b6aec03c ("drm/i915/pmu: Add RC6 residency metrics") Testcase: igt/perf_pmu/rc6-runtime-pm Cc: Tvrtko Ursulin Cc: Chris Wilson Cc: Imre Deak Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: David Airlie Cc: intel-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180206183311.17924-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_pmu.c | 93 +++++++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_pmu.h | 6 +++ 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 1c440460255d..bfc402d47609 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -415,7 +415,81 @@ static int i915_pmu_event_init(struct perf_event *event) return 0; } -static u64 __i915_pmu_event_read(struct perf_event *event) +static u64 get_rc6(struct drm_i915_private *i915, bool locked) +{ + unsigned long flags; + u64 val; + + if (intel_runtime_pm_get_if_in_use(i915)) { + val = intel_rc6_residency_ns(i915, IS_VALLEYVIEW(i915) ? + VLV_GT_RENDER_RC6 : + GEN6_GT_GFX_RC6); + + 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); + + /* + * If we are coming back from being runtime suspended we must + * be careful not to report a larger value than returned + * previously. + */ + + if (!locked) + spin_lock_irqsave(&i915->pmu.lock, flags); + + if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { + i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; + i915->pmu.sample[__I915_SAMPLE_RC6].cur = val; + } else { + val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur; + } + + if (!locked) + spin_unlock_irqrestore(&i915->pmu.lock, flags); + } else { + struct pci_dev *pdev = i915->drm.pdev; + struct device *kdev = &pdev->dev; + unsigned long flags2; + + /* + * We are runtime suspended. + * + * Report the delta from when the device was suspended to now, + * on top of the last known real value, as the approximated RC6 + * counter value. + */ + if (!locked) + spin_lock_irqsave(&i915->pmu.lock, flags); + + spin_lock_irqsave(&kdev->power.lock, flags2); + + if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) + i915->pmu.suspended_jiffies_last = + kdev->power.suspended_jiffies; + + val = kdev->power.suspended_jiffies - + i915->pmu.suspended_jiffies_last; + val += jiffies - kdev->power.accounting_timestamp; + + spin_unlock_irqrestore(&kdev->power.lock, flags2); + + val = jiffies_to_nsecs(val); + val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; + i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; + + if (!locked) + spin_unlock_irqrestore(&i915->pmu.lock, flags); + } + + return val; +} + +static u64 __i915_pmu_event_read(struct perf_event *event, bool locked) { struct drm_i915_private *i915 = container_of(event->pmu, typeof(*i915), pmu.base); @@ -453,18 +527,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event) 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); - 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); + val = get_rc6(i915, locked); break; } } @@ -479,7 +542,7 @@ static void i915_pmu_event_read(struct perf_event *event) again: prev = local64_read(&hwc->prev_count); - new = __i915_pmu_event_read(event); + new = __i915_pmu_event_read(event, false); if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) goto again; @@ -534,7 +597,7 @@ static void i915_pmu_enable(struct perf_event *event) * 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)); + local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, 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 5a2e013a56bb..aa1b1a987ea1 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -27,6 +27,8 @@ enum { __I915_SAMPLE_FREQ_ACT = 0, __I915_SAMPLE_FREQ_REQ, + __I915_SAMPLE_RC6, + __I915_SAMPLE_RC6_ESTIMATED, __I915_NUM_PMU_SAMPLERS }; @@ -94,6 +96,10 @@ struct i915_pmu { * struct intel_engine_cs. */ struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; + /** + * @suspended_jiffies_last: Cached suspend time from PM core. + */ + unsigned long suspended_jiffies_last; /** * @i915_attr: Memory block holding device attributes. */ From 05273c950a3c93c5f96be8807eaf24f2cc9f1c1e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 16:04:28 +0000 Subject: [PATCH 007/113] drm/i915/pmu: Fix building without CONFIG_PM As we peek inside struct device to query members guarded by CONFIG_PM, so must be the code. Reported-by: kbuild test robot Fixes: 1fe699e30113 ("drm/i915/pmu: Fix sleep under atomic in RC6 readout") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180207160428.17015-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pmu.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index bfc402d47609..964467b03e4d 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -415,22 +415,32 @@ static int i915_pmu_event_init(struct perf_event *event) return 0; } +static u64 __get_rc6(struct drm_i915_private *i915) +{ + u64 val; + + val = intel_rc6_residency_ns(i915, + IS_VALLEYVIEW(i915) ? + VLV_GT_RENDER_RC6 : + GEN6_GT_GFX_RC6); + + 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); + + return val; +} + static u64 get_rc6(struct drm_i915_private *i915, bool locked) { +#if IS_ENABLED(CONFIG_PM) unsigned long flags; u64 val; if (intel_runtime_pm_get_if_in_use(i915)) { - val = intel_rc6_residency_ns(i915, IS_VALLEYVIEW(i915) ? - VLV_GT_RENDER_RC6 : - GEN6_GT_GFX_RC6); - - 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); - + val = __get_rc6(i915); intel_runtime_pm_put(i915); /* @@ -487,6 +497,9 @@ static u64 get_rc6(struct drm_i915_private *i915, bool locked) } return val; +#else + return __get_rc6(i915); +#endif } static u64 __i915_pmu_event_read(struct perf_event *event, bool locked) From e78c91754d6cc6708db139822166b6708c0b172f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 21:05:42 +0000 Subject: [PATCH 008/113] drm/i915/guc: Allow preempt-client to be NULL In the next patch, we may only conditionally allocate the preempt-client if there is a global preempt context and so we need to be prepared in case the preempt-client itself is NULL. v2: Grep for more preempt_client. Signed-off-by: Chris Wilson Cc: Michal Winiarski Cc: Arkadiusz Hiler Cc: Daniele Ceraolo Spurio Cc: Michel Thierry Cc: Michal Wajdeczko Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180207210544.26351-1-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/i915_debugfs.c | 8 +++--- drivers/gpu/drm/i915/intel_guc_submission.c | 27 +++++++++++++-------- drivers/gpu/drm/i915/selftests/intel_guc.c | 20 ++++++++------- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3849ded354e3..9e44adef30f0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2338,7 +2338,6 @@ static int i915_guc_info(struct seq_file *m, void *data) return -ENODEV; GEM_BUG_ON(!guc->execbuf_client); - GEM_BUG_ON(!guc->preempt_client); seq_printf(m, "Doorbell map:\n"); seq_printf(m, "\t%*pb\n", GUC_NUM_DOORBELLS, guc->doorbell_bitmap); @@ -2346,8 +2345,11 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client); i915_guc_client_info(m, dev_priv, guc->execbuf_client); - seq_printf(m, "\nGuC preempt client @ %p:\n", guc->preempt_client); - i915_guc_client_info(m, dev_priv, guc->preempt_client); + if (guc->preempt_client) { + seq_printf(m, "\nGuC preempt client @ %p:\n", + guc->preempt_client); + i915_guc_client_info(m, dev_priv, guc->preempt_client); + } i915_guc_log_info(m, dev_priv); diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 1f3a8786bbdc..4ea65df05e02 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -832,10 +832,12 @@ static int guc_clients_doorbell_init(struct intel_guc *guc) if (ret) return ret; - ret = create_doorbell(guc->preempt_client); - if (ret) { - destroy_doorbell(guc->execbuf_client); - return ret; + if (guc->preempt_client) { + ret = create_doorbell(guc->preempt_client); + if (ret) { + destroy_doorbell(guc->execbuf_client); + return ret; + } } return 0; @@ -848,8 +850,11 @@ static void guc_clients_doorbell_fini(struct intel_guc *guc) * Instead of trying (in vain) to communicate with it, let's just * cleanup the doorbell HW and our internal state. */ - __destroy_doorbell(guc->preempt_client); - __update_doorbell_desc(guc->preempt_client, GUC_DOORBELL_INVALID); + if (guc->preempt_client) { + __destroy_doorbell(guc->preempt_client); + __update_doorbell_desc(guc->preempt_client, + GUC_DOORBELL_INVALID); + } __destroy_doorbell(guc->execbuf_client); __update_doorbell_desc(guc->execbuf_client, GUC_DOORBELL_INVALID); } @@ -998,10 +1003,11 @@ static void guc_clients_destroy(struct intel_guc *guc) { struct intel_guc_client *client; - client = fetch_and_zero(&guc->execbuf_client); - guc_client_free(client); - client = fetch_and_zero(&guc->preempt_client); + if (client) + guc_client_free(client); + + client = fetch_and_zero(&guc->execbuf_client); guc_client_free(client); } @@ -1160,7 +1166,8 @@ int intel_guc_submission_enable(struct intel_guc *guc) GEM_BUG_ON(!guc->execbuf_client); guc_reset_wq(guc->execbuf_client); - guc_reset_wq(guc->preempt_client); + if (guc->preempt_client) + guc_reset_wq(guc->preempt_client); err = intel_guc_sample_forcewake(guc); if (err) diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c index 3f9016466dea..fb74e2cf8a0a 100644 --- a/drivers/gpu/drm/i915/selftests/intel_guc.c +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c @@ -87,7 +87,7 @@ static int validate_client(struct intel_guc_client *client, static bool client_doorbell_in_sync(struct intel_guc_client *client) { - return doorbell_ok(client->guc, client->doorbell_id); + return !client || doorbell_ok(client->guc, client->doorbell_id); } /* @@ -137,7 +137,6 @@ static int igt_guc_clients(void *args) 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); @@ -146,16 +145,18 @@ static int igt_guc_clients(void *args) goto out; } - err = validate_client(guc->preempt_client, - GUC_CLIENT_PRIORITY_KMD_HIGH, true); - if (err) { - pr_err("preempt client validation failed\n"); - goto out; + if (guc->preempt_client) { + err = validate_client(guc->preempt_client, + GUC_CLIENT_PRIORITY_KMD_HIGH, true); + if (err) { + pr_err("preempt client validation failed\n"); + goto out; + } } /* each client should now have reserved a doorbell */ if (!has_doorbell(guc->execbuf_client) || - !has_doorbell(guc->preempt_client)) { + (guc->preempt_client && !has_doorbell(guc->preempt_client))) { pr_err("guc_clients_create didn't reserve doorbells\n"); err = -EINVAL; goto out; @@ -224,7 +225,8 @@ out: * clients during unload. */ destroy_doorbell(guc->execbuf_client); - destroy_doorbell(guc->preempt_client); + if (guc->preempt_client) + destroy_doorbell(guc->preempt_client); guc_clients_destroy(guc); guc_clients_create(guc); guc_clients_doorbell_init(guc); From 3fed180812edebac7d04b94a69da33b4f8532907 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 21:05:43 +0000 Subject: [PATCH 009/113] drm/i915: Move the scheduler feature bits into the purview of the engines Rather than having the high level ioctl interface guess the underlying implementation details, having the implementation declare what capabilities it exports. We define an intel_driver_caps, similar to the intel_device_info, which instead of trying to describe the HW gives details on what the driver itself supports. This is then populated by the engine backend for the new scheduler capability field for use elsewhere. v2: Use caps.scheduler for validating CONTEXT_PARAM_SET_PRIORITY (Mika) One less assumption of engine[RCS] \o/ Signed-off-by: Chris Wilson Cc: Tomasz Lis Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Cc: Michal Wajdeczko Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Reviewed-by: Tomasz Lis Link: https://patchwork.freedesktop.org/patch/msgid/20180207210544.26351-2-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_drv.c | 8 +------- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 3 +++ drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 7 +++++-- drivers/gpu/drm/i915/intel_device_info.c | 6 ++++++ drivers/gpu/drm/i915/intel_device_info.h | 7 +++++++ drivers/gpu/drm/i915/intel_lrc.c | 6 ++++++ 9 files changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9e44adef30f0..2bdce9fea671 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -49,6 +49,7 @@ static int i915_capabilities(struct seq_file *m, void *data) intel_device_info_dump_flags(info, &p); intel_device_info_dump_runtime(info, &p); + intel_driver_caps_print(&dev_priv->caps, &p); kernel_param_lock(THIS_MODULE); i915_params_dump(&i915_modparams, &p); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bb605e0b996c..143b9d5438d2 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -381,13 +381,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_gem_mmap_gtt_version(); break; case I915_PARAM_HAS_SCHEDULER: - value = 0; - 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)) - value |= I915_SCHEDULER_CAP_PREEMPTION; - } + value = dev_priv->caps.scheduler; break; case I915_PARAM_MMAP_VERSION: diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 60079a69c2f9..dd79d711c3dd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -472,6 +472,7 @@ struct i915_gpu_state { u32 reset_count; u32 suspend_count; struct intel_device_info device_info; + struct intel_driver_caps driver_caps; struct i915_params params; struct i915_error_uc { @@ -1815,6 +1816,7 @@ struct drm_i915_private { struct kmem_cache *priorities; const struct intel_device_info info; + struct intel_driver_caps caps; /** * Data Stolen Memory - aka "i915 stolen memory" gives us the start and diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c1b80cd52f9e..32883bb04747 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3229,8 +3229,11 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) * start to complete all requests. */ engine->submit_request = nop_complete_submit_request; + engine->schedule = NULL; } + i915->caps.scheduler = 0; + /* * Make sure no request can slip through without getting completed by * either this call here to intel_engine_init_global_seqno, or the one diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 648e7536ff51..8337d15bb0e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -807,7 +807,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, if (args->size) ret = -EINVAL; - else if (!to_i915(dev)->engine[RCS]->schedule) + else if (!(to_i915(dev)->caps.scheduler & I915_SCHEDULER_CAP_PRIORITY)) ret = -ENODEV; else if (priority > I915_CONTEXT_MAX_USER_PRIORITY || priority < I915_CONTEXT_MIN_USER_PRIORITY) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 67c902412193..7f82c6062c44 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -579,11 +579,13 @@ static void print_error_obj(struct drm_i915_error_state_buf *m, } static void err_print_capabilities(struct drm_i915_error_state_buf *m, - const struct intel_device_info *info) + const struct intel_device_info *info, + const struct intel_driver_caps *caps) { struct drm_printer p = i915_error_printer(m); intel_device_info_dump_flags(info, &p); + intel_driver_caps_print(caps, &p); } static void err_print_params(struct drm_i915_error_state_buf *m, @@ -808,7 +810,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (error->display) intel_display_print_error_state(m, error->display); - err_print_capabilities(m, &error->device_info); + err_print_capabilities(m, &error->device_info, &error->driver_caps); err_print_params(m, &error->params); err_print_uc(m, &error->uc); @@ -1740,6 +1742,7 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, memcpy(&error->device_info, INTEL_INFO(dev_priv), sizeof(error->device_info)); + error->driver_caps = dev_priv->caps; } static __always_inline void dup_param(const char *type, void *x) diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index a2c16140169f..298f8996cc54 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -586,3 +586,9 @@ void intel_device_info_runtime_init(struct intel_device_info *info) /* Initialize command stream timestamp frequency */ info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); } + +void intel_driver_caps_print(const struct intel_driver_caps *caps, + struct drm_printer *p) +{ + drm_printf(p, "scheduler: %x\n", caps->scheduler); +} diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 9542018d11d0..71fdfb0451ef 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -167,6 +167,10 @@ struct intel_device_info { } color; }; +struct intel_driver_caps { + unsigned int scheduler; +}; + static inline unsigned int sseu_subslice_total(const struct sseu_dev_info *sseu) { return hweight8(sseu->slice_mask) * hweight8(sseu->subslice_mask); @@ -182,4 +186,7 @@ void intel_device_info_dump_flags(const struct intel_device_info *info, void intel_device_info_dump_runtime(const struct intel_device_info *info, struct drm_printer *p); +void intel_driver_caps_print(const struct intel_driver_caps *caps, + struct drm_printer *p); + #endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 380c0838d8b3..449fd1e95f1f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1963,6 +1963,12 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) engine->unpark = NULL; engine->flags |= I915_ENGINE_SUPPORTS_STATS; + + engine->i915->caps.scheduler = + I915_SCHEDULER_CAP_ENABLED | + I915_SCHEDULER_CAP_PRIORITY; + if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; } static void From d63763749127b483ba042b2939ba39fd79792330 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 21:05:44 +0000 Subject: [PATCH 010/113] drm/i915: Only allocate preempt context when required If we remove some hardcoded assumptions about the preempt context having a fixed id, reserved from use by normal user contexts, we may only allocate the i915_gem_context when required. Then the subsequent decisions on using preemption reduce to having the preempt context available. v2: Include an assert that we don't allocate the preempt context twice. Signed-off-by: Chris Wilson Cc: Michal Winiarski Cc: Tvrtko Ursulin Cc: Arkadiusz Hiler Cc: Mika Kuoppala Cc: Daniele Ceraolo Spurio Acked-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20180207210544.26351-3-chris@chris-wilson.co.uk Reviewed-by: Michel Thierry --- drivers/gpu/drm/i915/i915_gem_context.c | 31 ++++++++++--------- drivers/gpu/drm/i915/intel_engine_cs.c | 6 ++-- drivers/gpu/drm/i915/intel_guc_submission.c | 24 +++++++------- drivers/gpu/drm/i915/intel_lrc.c | 17 ++++++---- drivers/gpu/drm/i915/intel_ringbuffer.h | 5 +++ .../gpu/drm/i915/selftests/mock_gem_device.c | 6 ---- 6 files changed, 48 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8337d15bb0e5..dd9efb9d0e0b 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -449,12 +449,18 @@ destroy_kernel_context(struct i915_gem_context **ctxp) i915_gem_context_free(ctx); } +static bool needs_preempt_context(struct drm_i915_private *i915) +{ + return HAS_LOGICAL_RING_PREEMPTION(i915); +} + int i915_gem_contexts_init(struct drm_i915_private *dev_priv) { struct i915_gem_context *ctx; - int err; + /* Reassure ourselves we are only called once */ GEM_BUG_ON(dev_priv->kernel_context); + GEM_BUG_ON(dev_priv->preempt_context); INIT_LIST_HEAD(&dev_priv->contexts.list); INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); @@ -468,8 +474,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN); if (IS_ERR(ctx)) { DRM_ERROR("Failed to create default global context\n"); - err = PTR_ERR(ctx); - goto err; + return PTR_ERR(ctx); } /* * For easy recognisablity, we want the kernel context to be 0 and then @@ -479,23 +484,18 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) dev_priv->kernel_context = ctx; /* highest priority; preempting task */ - ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); - if (IS_ERR(ctx)) { - DRM_ERROR("Failed to create default preempt context\n"); - err = PTR_ERR(ctx); - goto err_kernel_context; + if (needs_preempt_context(dev_priv)) { + ctx = i915_gem_context_create_kernel(dev_priv, INT_MAX); + if (!IS_ERR(ctx)) + dev_priv->preempt_context = ctx; + else + DRM_ERROR("Failed to create preempt context; disabling preemption\n"); } - dev_priv->preempt_context = ctx; DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->engine[RCS]->context_size ? "logical" : "fake"); return 0; - -err_kernel_context: - destroy_kernel_context(&dev_priv->kernel_context); -err: - return err; } void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) @@ -521,7 +521,8 @@ void i915_gem_contexts_fini(struct drm_i915_private *i915) { lockdep_assert_held(&i915->drm.struct_mutex); - destroy_kernel_context(&i915->preempt_context); + if (i915->preempt_context) + destroy_kernel_context(&i915->preempt_context); destroy_kernel_context(&i915->kernel_context); /* Must free all deferred contexts (via flush_workqueue) first */ diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 7eebfbb95e89..bf634432c9c6 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -631,7 +631,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) * Similarly the preempt context must always be available so that * we can interrupt the engine at any time. */ - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { + if (engine->i915->preempt_context) { ring = engine->context_pin(engine, engine->i915->preempt_context); if (IS_ERR(ring)) { @@ -656,7 +656,7 @@ int intel_engine_init_common(struct intel_engine_cs *engine) err_breadcrumbs: intel_engine_fini_breadcrumbs(engine); err_unpin_preempt: - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + if (engine->i915->preempt_context) engine->context_unpin(engine, engine->i915->preempt_context); err_unpin_kernel: engine->context_unpin(engine, engine->i915->kernel_context); @@ -686,7 +686,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) if (engine->default_state) i915_gem_object_put(engine->default_state); - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + if (engine->i915->preempt_context) engine->context_unpin(engine, engine->i915->preempt_context); engine->context_unpin(engine, engine->i915->kernel_context); } diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 4ea65df05e02..b43b58cc599b 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -688,7 +688,7 @@ static void guc_dequeue(struct intel_engine_cs *engine) goto unlock; if (port_isset(port)) { - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) { + if (engine->i915->preempt_context) { struct guc_preempt_work *preempt_work = &engine->i915->guc.preempt_work[engine->id]; @@ -984,17 +984,19 @@ static int guc_clients_create(struct intel_guc *guc) } guc->execbuf_client = client; - client = guc_client_alloc(dev_priv, - INTEL_INFO(dev_priv)->ring_mask, - GUC_CLIENT_PRIORITY_KMD_HIGH, - dev_priv->preempt_context); - if (IS_ERR(client)) { - DRM_ERROR("Failed to create GuC client for preemption!\n"); - guc_client_free(guc->execbuf_client); - guc->execbuf_client = NULL; - return PTR_ERR(client); + if (dev_priv->preempt_context) { + client = guc_client_alloc(dev_priv, + INTEL_INFO(dev_priv)->ring_mask, + GUC_CLIENT_PRIORITY_KMD_HIGH, + dev_priv->preempt_context); + if (IS_ERR(client)) { + DRM_ERROR("Failed to create GuC client for preemption!\n"); + guc_client_free(guc->execbuf_client); + guc->execbuf_client = NULL; + return PTR_ERR(client); + } + guc->preempt_client = client; } - guc->preempt_client = client; return 0; } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 449fd1e95f1f..c2c8380a0121 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -161,7 +161,6 @@ #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ #define WA_TAIL_DWORDS 2 #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) -#define PREEMPT_ID 0x1 static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, struct intel_engine_cs *engine); @@ -448,7 +447,8 @@ static void inject_preempt_context(struct intel_engine_cs *engine) &engine->i915->preempt_context->engine[engine->id]; unsigned int n; - GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); + GEM_BUG_ON(engine->execlists.preempt_complete_status != + upper_32_bits(ce->lrc_desc)); GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); @@ -528,7 +528,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_HWACK)) goto unlock; - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915) && + if (engine->i915->preempt_context && rb_entry(rb, struct i915_priolist, node)->priority > max(last->priotree.priority, 0)) { /* @@ -844,7 +844,7 @@ static void execlists_submission_tasklet(unsigned long data) GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE); if (status & GEN8_CTX_STATUS_COMPLETE && - buf[2*head + 1] == PREEMPT_ID) { + buf[2*head + 1] == execlists->preempt_complete_status) { GEM_TRACE("%s preempt-idle\n", engine->name); execlists_cancel_port_requests(execlists); @@ -1967,7 +1967,7 @@ static void execlists_set_default_submission(struct intel_engine_cs *engine) engine->i915->caps.scheduler = I915_SCHEDULER_CAP_ENABLED | I915_SCHEDULER_CAP_PRIORITY; - if (HAS_LOGICAL_RING_PREEMPTION(engine->i915)) + if (engine->i915->preempt_context) engine->i915->caps.scheduler |= I915_SCHEDULER_CAP_PREEMPTION; } @@ -2045,6 +2045,11 @@ static int logical_ring_init(struct intel_engine_cs *engine) engine->execlists.elsp = engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); + engine->execlists.preempt_complete_status = ~0u; + if (engine->i915->preempt_context) + engine->execlists.preempt_complete_status = + upper_32_bits(engine->i915->preempt_context->engine[engine->id].lrc_desc); + return 0; error: @@ -2307,7 +2312,7 @@ populate_lr_context(struct i915_gem_context *ctx, if (!engine->default_state) regs[CTX_CONTEXT_CONTROL + 1] |= _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); - if (ctx->hw_id == PREEMPT_ID) + if (ctx == ctx->i915->preempt_context) regs[CTX_CONTEXT_CONTROL + 1] |= _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a0e7a6c2a57c..8f1a4badf812 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -279,6 +279,11 @@ struct intel_engine_execlists { * @csb_use_mmio: access csb through mmio, instead of hwsp */ bool csb_use_mmio; + + /** + * @preempt_complete_status: expected CSB upon completing preemption + */ + u32 preempt_complete_status; }; #define INTEL_ENGINE_CS_MAX_NAME 8 diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 1bc61f3f76fc..3175db70cc6e 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -243,16 +243,10 @@ struct drm_i915_private *mock_gem_device(void) if (!i915->kernel_context) goto err_engine; - i915->preempt_context = mock_context(i915, NULL); - if (!i915->preempt_context) - goto err_kernel_context; - WARN_ON(i915_gemfs_init(i915)); return i915; -err_kernel_context: - i915_gem_context_put(i915->kernel_context); err_engine: for_each_engine(engine, i915, id) mock_engine_free(engine); From ce1599a40da20b0e5e4175fe3ef647d2862cbf41 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 7 Feb 2018 13:24:40 -0800 Subject: [PATCH 011/113] drm/i915: do not stop engines on sanitize if i915.reset=0 Since commit 5896a5c8c9c0 (drm/i915: Always stop the rings before a missing GPU reset) we attempt to stop the engines during gem_sanitize even if reset=0 and nothing bad happened on the gpu. The specs says that the STOP_RINGS bit needs to be cleared to resume normal operation, but for some reason the value of the bit seems to be changing without us writing to it (maybe rc6 entry/exit?), so normal operation resumes correctly. However, it still feels incorrect to stop the engines if there hasn't been any issue so skip the whole reset call in gem_sanitize if i915.reset=0 Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20180207212440.13438-1-daniele.ceraolospurio@intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 32883bb04747..021588950a52 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4885,10 +4885,8 @@ void i915_gem_sanitize(struct drm_i915_private *i915) * it may impact the display and we are uncertain about the stability * of the reset, so this could be applied to even earlier gen. */ - if (INTEL_GEN(i915) >= 5) { - int reset = intel_gpu_reset(i915, ALL_ENGINES); - WARN_ON(reset && reset != -ENODEV); - } + if (INTEL_GEN(i915) >= 5 && intel_has_gpu_reset(i915)) + WARN_ON(intel_gpu_reset(i915, ALL_ENGINES)); } int i915_gem_suspend(struct drm_i915_private *dev_priv) From 43df81d324cdd7056ad0ce3df709aff8dce856b7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 10:24:02 +0000 Subject: [PATCH 012/113] drm/i915/perf: Fix compiler warning for string truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/i915_oa_cflgt3.c: In function ‘i915_perf_load_test_config_cflgt3’: drivers/gpu/drm/i915/i915_oa_cflgt3.c:87:2: error: ‘strncpy’ output truncated before terminating nul copying 36 bytes from a string of the same length [-Werror=stringop-truncation] v2: strlcpy Fixes: 4407eaa9b0cc ("drm/i915/perf: add support for Coffeelake GT3") Signed-off-by: Chris Wilson Cc: Lionel Landwerlin Cc: Matthew Auld Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208102403.5587-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_oa_cflgt3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt3.c b/drivers/gpu/drm/i915/i915_oa_cflgt3.c index 42ff06fe54a3..792facdb6702 100644 --- a/drivers/gpu/drm/i915/i915_oa_cflgt3.c +++ b/drivers/gpu/drm/i915/i915_oa_cflgt3.c @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) void i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) { - strncpy(dev_priv->perf.oa.test_config.uuid, + strlcpy(dev_priv->perf.oa.test_config.uuid, "577e8e2c-3fa0-4875-8743-3538d585e3b0", - UUID_STRING_LEN); + sizeof(dev_priv->perf.oa.test_config.uuid)); dev_priv->perf.oa.test_config.id = 1; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; From 020580ff8edd50e64ae1bf47e560c61e5e2f29fc Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 10:24:03 +0000 Subject: [PATCH 013/113] drm/i915/perf: Fix compiler warning for string truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/i915_oa_cnl.c: In function ‘i915_perf_load_test_config_cnl’: drivers/gpu/drm/i915/i915_oa_cnl.c:99:2: error: ‘strncpy’ output truncated before terminating nul copying 36 bytes from a string of the same length [-Werror=stringop-truncation] v2: strlcpy Fixes: 95690a02fb5d ("drm/i915/perf: enable perf support on CNL") Signed-off-by: Chris Wilson Cc: Lionel Landwerlin Cc: Matthew Auld Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208102403.5587-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_oa_cnl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_oa_cnl.c b/drivers/gpu/drm/i915/i915_oa_cnl.c index ff0ac3627cc4..ba9140c87cc0 100644 --- a/drivers/gpu/drm/i915/i915_oa_cnl.c +++ b/drivers/gpu/drm/i915/i915_oa_cnl.c @@ -96,9 +96,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) void i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) { - strncpy(dev_priv->perf.oa.test_config.uuid, + strlcpy(dev_priv->perf.oa.test_config.uuid, "db41edd4-d8e7-4730-ad11-b9a2d6833503", - UUID_STRING_LEN); + sizeof(dev_priv->perf.oa.test_config.uuid)); dev_priv->perf.oa.test_config.id = 1; dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; From 253a281727d552200c4cddb0cc08cb2e95939603 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 6 Feb 2018 14:31:37 +0000 Subject: [PATCH 014/113] drm/i915: Remove superfluous worker wakeups when RPS is already boosted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only need to wake up the RPS worker once when initially enabling the client boost, it remains in effect then until the last client no longer requires the boost. References: https://bugs.freedesktop.org/show_bug.cgi?id=102250 References: 7b92c1bd0540 ("drm/i915: Avoid keeping waitboost active for signaling threads") Signed-off-by: Chris Wilson Cc: Michał Winiarski Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20180206143137.15509-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 6 ++++-- drivers/gpu/drm/i915/intel_pm.c | 9 ++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index a8eb22a95b0f..8a35b5591e0e 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -443,12 +443,14 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) engine->last_retired_context = request->ctx; spin_lock_irq(&request->lock); - if (request->waitboost) - atomic_dec(&request->i915->gt_pm.rps.num_waiters); if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags)) dma_fence_signal_locked(&request->fence); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) intel_engine_cancel_signaling(request); + if (request->waitboost) { + GEM_BUG_ON(!atomic_read(&request->i915->gt_pm.rps.num_waiters)); + atomic_dec(&request->i915->gt_pm.rps.num_waiters); + } spin_unlock_irq(&request->lock); i915_priotree_fini(request->i915, &request->priotree); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 41f26ab46501..b2f5e3b9ada8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6374,12 +6374,15 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq, if (!rps->enabled) return; + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) + return; + + /* Serializes with i915_gem_request_retire() */ boost = false; spin_lock_irqsave(&rq->lock, flags); - if (!rq->waitboost && !i915_gem_request_completed(rq)) { - atomic_inc(&rps->num_waiters); + if (!rq->waitboost && !dma_fence_is_signaled_locked(&rq->fence)) { + boost = !atomic_fetch_inc(&rps->num_waiters); rq->waitboost = true; - boost = true; } spin_unlock_irqrestore(&rq->lock, flags); if (!boost) From 11a18f631959fd1ca10856c836a827683536770c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 08:51:51 +0000 Subject: [PATCH 015/113] drm/i915: Avoid truncation before clamping userspace's priority value Userspace provides a 64b value for the priority, we need to be careful to preserve the full range before validation to prevent truncation (and letting an illegal value pass). Reported-by: Antonio Argenziano Fixes: ac14fbd460d0 ("drm/i915/scheduler: Support user-defined priorities") Signed-off-by: Chris Wilson Cc: Antonio Argenziano Cc: Michal Winiarski Cc: Mika Kuoppala Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180208085151.11480-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index dd9efb9d0e0b..7ccba6c786ae 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -804,7 +804,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, case I915_CONTEXT_PARAM_PRIORITY: { - int priority = args->value; + s64 priority = args->value; if (args->size) ret = -EINVAL; From 0d73e7a095f768fad5a002bf6732c675e2aee44b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 15:13:50 +0000 Subject: [PATCH 016/113] drm/i915: Mark the device as wedged from the beginning of set-wedged Reduce the window of opportunity for set-wedged being called concurrently with reset (after i915_reset() has performed the i915_gem_unset_wedged()) by moving the set_bit(I915_WEDGED) to before we complete the inflight requests. When i915_reset() is being blocked on a request, such completion may allow it to start and beginning resetting the GPU before i915_gem_set_wedged() has finished (and so before set-wedge will have marked the device as wedged). As such, i915_gem_init_hw() may see a wedged device even from inside i915_reset(). References: 36703e79a982 ("drm/i915: Break modeset deadlocks on reset") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180207151350.20883-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 021588950a52..349f127330c8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3205,6 +3205,9 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) intel_engine_dump(engine, &p, "%s\n", engine->name); } + set_bit(I915_WEDGED, &i915->gpu_error.flags); + smp_mb__after_atomic(); + /* * First, stop submission to hw, but do not yet complete requests by * rolling the global seqno forward (since this would complete requests @@ -3244,7 +3247,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { unsigned long flags; - /* Mark all pending requests as complete so that any concurrent + /* + * Mark all pending requests as complete so that any concurrent * (lockless) lookup doesn't try and wait upon the request as we * reset it. */ @@ -3254,7 +3258,6 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) spin_unlock_irqrestore(&engine->timeline->lock, flags); } - set_bit(I915_WEDGED, &i915->gpu_error.flags); wake_up_all(&i915->gpu_error.reset_queue); } From bc8f2f5db9d75e7f990fb8362c28a8d2a7f33c9c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 07:28:00 +0000 Subject: [PATCH 017/113] drm/i915: Be paranoid and post the writes to stop the rings Although the mmio are uncached and so should be flushed on every write, be paranoid and do a mmio read after setting the ring head/tail to be sure they have taken effect before moving on. v2: post tail to be pleasing to the eye Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180208072800.595-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_uncore.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 4075010ac088..db441bf3b9d5 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1522,9 +1522,11 @@ static void gen3_stop_engine(struct intel_engine_cs *engine) engine->name); I915_WRITE_FW(RING_HEAD(base), I915_READ_FW(RING_TAIL(base))); + POSTING_READ_FW(RING_HEAD(base)); /* paranoia */ I915_WRITE_FW(RING_HEAD(base), 0); I915_WRITE_FW(RING_TAIL(base), 0); + POSTING_READ_FW(RING_TAIL(base)); /* The ring must be empty before it is disabled */ I915_WRITE_FW(RING_CTL(base), 0); From a1ab7dcf634f9e5f8e8d25fec4cc4d46602c146c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 7 Feb 2018 22:28:24 +0000 Subject: [PATCH 018/113] drm/i915: Wait for gen3 reset status to be asserted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After we assert the reset request (and wait for 20us), when the device has been fully reset it asserts the reset-status bit. Before we stop requesting the reset and allow the device to return to normal, we should wait for the reset to be completed. (Similar to how we wait for the device to return to normal after deasserting the reset request.) v2: Rename i915_reset_completed() probe to not cause as much confusion. Signed-off-by: Chris Wilson Cc: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180207222824.29864-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala --- drivers/gpu/drm/i915/intel_uncore.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index db441bf3b9d5..c23af35c081e 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1550,24 +1550,31 @@ static void i915_stop_engines(struct drm_i915_private *dev_priv, gen3_stop_engine(engine); } -static bool i915_reset_complete(struct pci_dev *pdev) +static bool i915_in_reset(struct pci_dev *pdev) { u8 gdrst; pci_read_config_byte(pdev, I915_GDRST, &gdrst); - return (gdrst & GRDOM_RESET_STATUS) == 0; + return gdrst & GRDOM_RESET_STATUS; } static int i915_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) { struct pci_dev *pdev = dev_priv->drm.pdev; + int err; - /* assert reset for at least 20 usec */ + /* Assert reset for at least 20 usec, and wait for acknowledgement. */ pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); usleep_range(50, 200); - pci_write_config_byte(pdev, I915_GDRST, 0); + err = wait_for(i915_in_reset(pdev), 500); - return wait_for(i915_reset_complete(pdev), 500); + /* Clear the reset request. */ + pci_write_config_byte(pdev, I915_GDRST, 0); + usleep_range(50, 200); + if (!err) + err = wait_for(!i915_in_reset(pdev), 500); + + return err; } static bool g4x_reset_complete(struct pci_dev *pdev) From d03133a82dc2abd4aa3852ea35570ba82ea36201 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:11:05 +0000 Subject: [PATCH 019/113] drm/i915: Fix kerneldoc warnings for i915_gpu_error drivers/gpu/drm/i915/i915_gpu_error.c:1815: warning: No description found for parameter 'dev_priv' drivers/gpu/drm/i915/i915_gpu_error.c:1815: warning: No description found for parameter 'engine_mask' drivers/gpu/drm/i915/i915_gpu_error.c:1815: warning: No description found for parameter 'error_msg' drivers/gpu/drm/i915/i915_gpu_error.c:1815: warning: Excess function parameter 'dev' description in 'i915_capture_error_state' Signed-off-by: Chris Wilson Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208111105.32149-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 7f82c6062c44..161d9103a65e 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1805,14 +1805,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915) /** * i915_capture_error_state - capture an error record for later analysis - * @dev: drm device + * @i915: i915 device + * @engine_mask: the mask of engines triggering the hang + * @error_msg: a message to insert into the error capture header * * Should be called when an error is detected (either a hang or an error * interrupt) to capture error state from the time of the error. Fills * out a structure which becomes available in debugfs for user level tools * to pick up. */ -void i915_capture_error_state(struct drm_i915_private *dev_priv, +void i915_capture_error_state(struct drm_i915_private *i915, u32 engine_mask, const char *error_msg) { @@ -1823,25 +1825,25 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, if (!i915_modparams.error_capture) return; - if (READ_ONCE(dev_priv->gpu_error.first_error)) + if (READ_ONCE(i915->gpu_error.first_error)) return; - error = i915_capture_gpu_state(dev_priv); + error = i915_capture_gpu_state(i915); if (!error) { DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); return; } - i915_error_capture_msg(dev_priv, error, engine_mask, error_msg); + i915_error_capture_msg(i915, error, engine_mask, error_msg); DRM_INFO("%s\n", error->error_msg); if (!error->simulated) { - spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); - if (!dev_priv->gpu_error.first_error) { - dev_priv->gpu_error.first_error = error; + spin_lock_irqsave(&i915->gpu_error.lock, flags); + if (!i915->gpu_error.first_error) { + i915->gpu_error.first_error = error; error = NULL; } - spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags); + spin_unlock_irqrestore(&i915->gpu_error.lock, flags); } if (error) { @@ -1856,7 +1858,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); DRM_INFO("The gpu crash dump is required to analyze gpu hangs, so please always attach it.\n"); DRM_INFO("GPU crash dump saved to /sys/class/drm/card%d/error\n", - dev_priv->drm.primary->index); + i915->drm.primary->index); warned = true; } } From 179f402550cf0f5ba9338297469be56f823a2331 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:12:20 +0000 Subject: [PATCH 020/113] drm/i915: Fix kerneldoc warnings for intel_ringbuffer drivers/gpu/drm/i915/intel_ringbuffer.c:179: warning: No description found for parameter 'req' drivers/gpu/drm/i915/intel_ringbuffer.c:741: warning: No description found for parameter 'req' drivers/gpu/drm/i915/intel_ringbuffer.c:741: warning: No description found for parameter 'cs' Signed-off-by: Chris Wilson Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208111220.32293-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_ringbuffer.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f93e4532371a..c8f95456e430 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -137,7 +137,7 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) return 0; } -/** +/* * Emits a PIPE_CONTROL with a non-zero post-sync operation, for * implementing two workarounds on gen6. From section 1.4.7.1 * "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: @@ -729,14 +729,6 @@ static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) static const int i9xx_emit_breadcrumb_sz = 4; -/** - * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers - * - * @request - request to write to the ring - * - * Update the mailbox registers in the *other* rings with the current seqno. - * This acts like a signal in the canonical semaphore. - */ static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) { return i9xx_emit_breadcrumb(req, From a5a5ae2abe3ba776da8c384e362dc0d2b7dc93d7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:13:28 +0000 Subject: [PATCH 021/113] drm/i915: Fix kerneldoc warnings for i915_gem_userptr drivers/gpu/drm/i915/i915_gem_userptr.c:761: warning: No description found for parameter 'dev' drivers/gpu/drm/i915/i915_gem_userptr.c:761: warning: No description found for parameter 'data' drivers/gpu/drm/i915/i915_gem_userptr.c:761: warning: No description found for parameter 'file' Signed-off-by: Chris Wilson Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208111328.32422-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_userptr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 382a77a1097e..1f9d24021cbb 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -721,7 +721,7 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { .release = i915_gem_userptr_release, }; -/** +/* * Creates a new mm object that wraps some normal memory from the process * context - user memory. * @@ -757,7 +757,9 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = { * dma-buf instead. */ int -i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +i915_gem_userptr_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_userptr *args = data; From d8802126da6869c2fc3a51e7475846e9c54f3ffb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:14:53 +0000 Subject: [PATCH 022/113] drm/i915: Fix kerneldoc warnings for i915_gem_request drivers/gpu/drm/i915/i915_gem_request.c:941: warning: No description found for parameter 'write' Signed-off-by: Chris Wilson Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208111453.32567-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 8a35b5591e0e..8bc7c50b8418 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -918,9 +918,9 @@ i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req, /** * i915_gem_request_await_object - set this request to (async) wait upon a bo - * * @to: request we are wishing to use * @obj: object which may be in use on another ring. + * @write: whether the wait is on behalf of a writer * * This code is meant to abstract object synchronization with the GPU. * Conceptually we serialise writes between engines inside the GPU. From 3d4b7caf2ba2773e9beda85c5e031dfffc6644af Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:15:59 +0000 Subject: [PATCH 023/113] drm/i915: Remove lost comment from i915_gem_context The comment is very old and quite misleading now. drivers/gpu/drm/i915/i915_gem_context.c:349: warning: No description found for parameter 'dev_priv' drivers/gpu/drm/i915/i915_gem_context.c:349: warning: No description found for parameter 'file_priv' Signed-off-by: Chris Wilson Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20180208111559.32663-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 7ccba6c786ae..3d75f484f6e5 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -338,11 +338,6 @@ static void __destroy_hw_context(struct i915_gem_context *ctx, context_close(ctx); } -/** - * The default context needs to exist per ring that uses contexts. It stores the - * context state of the GPU for applications that don't utilize HW contexts, as - * well as an idle case. - */ static struct i915_gem_context * i915_gem_create_context(struct drm_i915_private *dev_priv, struct drm_i915_file_private *file_priv) From 34e07e42c55aeaa78e93b057a6664e2ecde3fadb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 10:54:48 +0000 Subject: [PATCH 024/113] drm/i915: Add missing kerneldoc for 'ent' in i915_driver_init_early drivers/gpu/drm/i915/i915_drv.c:891: warning: No description found for parameter 'ent' Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208105449.29880-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 143b9d5438d2..cd57f946cf45 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -873,6 +873,7 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) /** * i915_driver_init_early - setup state not requiring device access * @dev_priv: device private + * @ent: the matching pci_device_id * * Initialize everything that is a "SW-only" state, that is state not * requiring accessing the device or exposing the driver via kernel internal From eb8269b54d75e4742fbe3ae994fb2f69b7283b40 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 10:54:49 +0000 Subject: [PATCH 025/113] drm/i915: Fix kerneldoc parameter markup drivers/gpu/drm/i915/i915_syncmap.c:92: warning: No description found for parameter 'root' drivers/gpu/drm/i915/i915_syncmap.c:155: warning: No description found for parameter 'root' drivers/gpu/drm/i915/i915_syncmap.c:155: warning: No description found for parameter 'id' drivers/gpu/drm/i915/i915_syncmap.c:155: warning: No description found for parameter 'seqno' drivers/gpu/drm/i915/i915_syncmap.c:354: warning: No description found for parameter 'root' drivers/gpu/drm/i915/i915_syncmap.c:354: warning: No description found for parameter 'id' drivers/gpu/drm/i915/i915_syncmap.c:354: warning: No description found for parameter 'seqno' drivers/gpu/drm/i915/i915_syncmap.c:396: warning: No description found for parameter 'root' Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208105449.29880-2-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_syncmap.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_syncmap.c b/drivers/gpu/drm/i915/i915_syncmap.c index 0087acf731a8..58f8d0cc125c 100644 --- a/drivers/gpu/drm/i915/i915_syncmap.c +++ b/drivers/gpu/drm/i915/i915_syncmap.c @@ -86,7 +86,7 @@ struct i915_syncmap { /** * i915_syncmap_init -- initialise the #i915_syncmap - * @root - pointer to the #i915_syncmap + * @root: pointer to the #i915_syncmap */ void i915_syncmap_init(struct i915_syncmap **root) { @@ -139,9 +139,9 @@ static inline bool seqno_later(u32 a, u32 b) /** * i915_syncmap_is_later -- compare against the last know sync point - * @root - pointer to the #i915_syncmap - * @id - the context id (other timeline) we are synchronising to - * @seqno - the sequence number along the other timeline + * @root: pointer to the #i915_syncmap + * @id: the context id (other timeline) we are synchronising to + * @seqno: the sequence number along the other timeline * * If we have already synchronised this @root timeline with another (@id) then * we can omit any repeated or earlier synchronisation requests. If the two @@ -339,9 +339,9 @@ found: /** * i915_syncmap_set -- mark the most recent syncpoint between contexts - * @root - pointer to the #i915_syncmap - * @id - the context id (other timeline) we have synchronised to - * @seqno - the sequence number along the other timeline + * @root: pointer to the #i915_syncmap + * @id: the context id (other timeline) we have synchronised to + * @seqno: the sequence number along the other timeline * * When we synchronise this @root timeline with another (@id), we also know * that we have synchronized with all previous seqno along that timeline. If @@ -382,7 +382,7 @@ static void __sync_free(struct i915_syncmap *p) /** * i915_syncmap_free -- free all memory associated with the syncmap - * @root - pointer to the #i915_syncmap + * @root: pointer to the #i915_syncmap * * Either when the timeline is to be freed and we no longer need the sync * point tracking, or when the fences are all known to be signaled and the From 204bcfef60d082f88dcb12051f5740cc92ed4dc9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:39:17 +0000 Subject: [PATCH 026/113] drm/i915: Fix kerneldoc warnings in i915_gem_execbuffer drivers/gpu/drm/i915/i915_gem_execbuffer.c:1983: warning: No description found for parameter 'dev_priv' drivers/gpu/drm/i915/i915_gem_execbuffer.c:1983: warning: No description found for parameter 'file' Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180208113917.8439-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 4401068ff468..d6a1f2ce1fcd 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1973,7 +1973,7 @@ static int eb_submit(struct i915_execbuffer *eb) return 0; } -/** +/* * Find one BSD ring to dispatch the corresponding BSD command. * The engine index is returned. */ From 40f46095db0691bc39f5ce916eab9c3e6136c912 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 11:42:24 +0000 Subject: [PATCH 027/113] drm/i915: Fix kerneldoc warnings for i915_gem_internal drivers/gpu/drm/i915/i915_gem_internal.c:183: warning: No description found for parameter 'i915' drivers/gpu/drm/i915/i915_gem_internal.c:183: warning: No description found for parameter 'size' Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208114224.27271-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_internal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index a1d6956734f7..8301c06c952f 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -167,6 +167,10 @@ static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = { }; /** + * i915_gem_object_create_internal: create an object with volatile pages + * @i915: the i915 device + * @size: the size in bytes of backing storage to allocate for the object + * * Creates a new object that wraps some internal memory for private use. * This object is not backed by swappable storage, and as such its contents * are volatile and only valid whilst pinned. If the object is reaped by the From 6a05d290046447fca311022004a4725f3f627dc9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 16:16:39 +0000 Subject: [PATCH 028/113] drm/i915: Disable unused-but-set compiler warning The unused-but-set warning enabled by W=1 catches out a lot of the atomic helper iterator macros and drown us in their noise (or trip over Werror and die). Path of least resistance is to ignore the warning. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20180208161639.27511-1-chris@chris-wilson.co.uk Reviewed-by: Joonas Lahtinen Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/i915/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4d9e2f855e9d..838f9b48246b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -17,6 +17,7 @@ subdir-ccflags-y += $(call cc-disable-warning, unused-parameter) subdir-ccflags-y += $(call cc-disable-warning, type-limits) subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) +subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable) subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror # Fine grained warnings disable From f0fa739a3448e48b75e96c962853b73b1a11d6e1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 9 Dec 2017 22:21:33 +0000 Subject: [PATCH 029/113] drm/i915: Avoid leaking lpe audio platdev.data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct platform_device memdups the provided data pointer requiring us to free the template we construct during lpe_audio_platdev_create(): unreferenced object 0xffff88026eafe400 (size 512): comm "insmod", pid 6850, jiffies 4295060179 (age 22.300s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<000000008e4a834c>] intel_audio_init+0x9/0x30 [i915] [<000000001360e195>] i915_driver_load+0x802/0x14e0 [i915] [<00000000ab3f0e99>] i915_pci_probe+0x29/0x70 [i915] [<0000000016330ee5>] pci_device_probe+0x9c/0x120 [<000000000257d054>] driver_probe_device+0x307/0x470 [<000000009f0a6cb6>] __driver_attach+0x98/0xe0 [<0000000031b46e58>] bus_for_each_dev+0x57/0x80 [<000000000e28239d>] bus_add_driver+0x1bd/0x260 [<00000000abbe5161>] driver_register+0x52/0xc0 [<000000005c6e23d4>] do_one_initcall+0x36/0x150 [<00000000a55002f4>] do_init_module+0x56/0x1d7 [<00000000e48f2217>] load_module+0x23c8/0x2910 [<000000002b60bf61>] SyS_finit_module+0xb8/0xd0 [<0000000041cbad96>] entry_SYSCALL_64_fastpath+0x17/0x70 [<000000009f1d37ab>] 0xffffffffffffffff Signed-off-by: Chris Wilson Cc: Takashi Iwai Cc: Pierre-Louis Bossart Cc: Ville Syrjälä Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20171209222133.31880-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lpe_audio.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 5809b29044fc..6269750e2b54 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -74,7 +74,6 @@ static struct platform_device * lpe_audio_platdev_create(struct drm_i915_private *dev_priv) { - int ret; struct drm_device *dev = &dev_priv->drm; struct platform_device_info pinfo = {}; struct resource *rsc; @@ -119,24 +118,19 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv) spin_lock_init(&pdata->lpe_audio_slock); platdev = platform_device_register_full(&pinfo); - if (IS_ERR(platdev)) { - ret = PTR_ERR(platdev); - DRM_ERROR("Failed to allocate LPE audio platform device\n"); - goto err; - } - kfree(rsc); + kfree(pdata); + + if (IS_ERR(platdev)) { + DRM_ERROR("Failed to allocate LPE audio platform device\n"); + return platdev; + } pm_runtime_forbid(&platdev->dev); pm_runtime_set_active(&platdev->dev); pm_runtime_enable(&platdev->dev); return platdev; - -err: - kfree(rsc); - kfree(pdata); - return ERR_PTR(ret); } static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv) From 2927e4211f76893249cfa8e7ac5fe1c73ae791c1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 16:39:39 +0000 Subject: [PATCH 030/113] drm/i915/crt: Silence compiler warning for uninitialised status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang is confused by our if-else-chain that abruptly exits before a final else: drivers/gpu/drm/i915/intel_crt.c:821:11: warning: variable 'status' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] else if (ret < 0) ^~~~~~~ drivers/gpu/drm/i915/intel_crt.c:826:9: note: uninitialized use occurs here return status; ^~~~~~ drivers/gpu/drm/i915/intel_crt.c:821:7: note: remove the 'if' if its condition is always true else if (ret < 0) ^~~~~~~~~~~~ drivers/gpu/drm/i915/intel_crt.c:761:12: note: initialize the variable 'status' to silence this warning int status, ret; In this case, we can reduce the final else-if clause to an unconditional else. Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180208163939.27030-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_crt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 9f31aea51dff..ae55afcbdc2c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -810,10 +810,11 @@ intel_crt_detect(struct drm_connector *connector, else status = connector_status_unknown; intel_release_load_detect_pipe(connector, &tmp, ctx); - } else if (ret == 0) + } else if (ret == 0) { status = connector_status_unknown; - else if (ret < 0) + } else { status = ret; + } out: intel_display_power_put(dev_priv, intel_encoder->power_domain); From 8e47b4b65bbd646b4d8be28e1ffff7a684f60fe6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 8 Feb 2018 15:12:24 +0000 Subject: [PATCH 031/113] drm/i915: Remove redundant check on execlists interrupt Since commit 4a118ecbe99c ("drm/i915: Filter out spurious execlists context-switch interrupts") we probe execlists->active, and no longer have to peek at the execlist interrupt to determine if the tasklet still needs to be run to drain the ELSP. References: 4a118ecbe99c ("drm/i915: Filter out spurious execlists context-switch interrupts") Signed-off-by: Chris Wilson Cc: Michal Winiarski Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180208151224.16285-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index bf634432c9c6..0ad9184eba97 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1503,10 +1503,6 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) if (I915_SELFTEST_ONLY(engine->breadcrumbs.mock)) return true; - /* Interrupt/tasklet pending? */ - if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) - return false; - /* Waiting to drain ELSP? */ if (READ_ONCE(engine->execlists.active)) return false; From 928f0cd0eb0511e19b416e34a030ebff6785fa52 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 8 Feb 2018 13:23:31 +0200 Subject: [PATCH 032/113] drm/i915/snb+: Remove incorrect forcewake check in debugfs/i915_drpc_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FORCEWAKE_ACK is depricated by BSpec at least starting from BDW, referring to the multi-threaded version of it instead. Accessing FORCEWAKE_ACK triggers an unclaimed register access error - at least on GLK - see the Reference: below. The correct registers to use would be FORCEWAKE_MT_ACK on IVB+ and FORCEWAKE_ACK_RENDER_GEN9 on SKL+ like it's done elsewhere in the driver. The forcewake check itself is inconsistent and redundant, since there could be other forcewake requesters besides the kernel (being the multithreaded version of the register) and the kernel's per-domain forcewake counters are shown anyway at the end of the file. So let's just remove the check. Suggested-by: Chris Wilson Cc: Ville Syrjälä Cc: Chris Wilson Cc: Mika Kuoppala Reference: https://bugs.freedesktop.org/show_bug.cgi?id=103337 Signed-off-by: Imre Deak Tested-by: Lionel Landwerlin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208112331.12986-1-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2bdce9fea671..eff5548ec093 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1461,19 +1461,6 @@ static int gen6_drpc_info(struct seq_file *m) struct drm_i915_private *dev_priv = node_to_i915(m->private); u32 gt_core_status, rcctl1, rc6vids = 0; u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; - unsigned forcewake_count; - int count = 0; - - forcewake_count = READ_ONCE(dev_priv->uncore.fw_domain[FW_DOMAIN_ID_RENDER].wake_count); - if (forcewake_count) { - seq_puts(m, "RC information inaccurate because somebody " - "holds a forcewake reference \n"); - } else { - /* NB: we cannot use forcewake, else we read the wrong values */ - while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) - udelay(10); - seq_printf(m, "RC information accurate: %s\n", yesno(count < 51)); - } gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS); trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true); From 89746e790ae5840d23f244c98cab6f45625463b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 6 Feb 2018 22:43:33 +0200 Subject: [PATCH 033/113] drm/i915: Reject undefined colorkey flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check that userspace isn't passing in garbage in the colorkey ioctl flags. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180206204333.4399-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/intel_sprite.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 32f10621fac8..d8900d09bef7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1073,6 +1073,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, /* ignore the pointless "none" flag */ set->flags &= ~I915_SET_COLORKEY_NONE; + if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) + return -EINVAL; + /* Make sure we don't try to enable both src & dest simultaneously */ if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) return -EINVAL; From 6a20fe7b17cd7ecd4b75dd82cfa6664780d6f923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 7 Feb 2018 18:48:41 +0200 Subject: [PATCH 034/113] drm/i915: Give all ioctl functions an _ioctl suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of our ioctl functions have an _ioctl suffix in the name. I like that idea since it makes it easy to figure out how the function is going to get called. Rename the handful of exceptions to follow the same pattern. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180207164841.19431-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.c | 14 +++++++------- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++---- drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 8 ++++---- drivers/gpu/drm/i915/intel_sprite.c | 4 ++-- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index cd57f946cf45..daa9060bdfcb 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -286,8 +286,8 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) pci_dev_put(pch); } -static int i915_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_getparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; @@ -2792,7 +2792,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, drm_noop, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, drm_noop, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, drm_noop, DRM_AUTH), - DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_SETPARAM, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH), @@ -2804,8 +2804,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, drm_noop, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), - DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), @@ -2824,11 +2824,11 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0), + DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id_ioctl, 0), DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), - DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW), + DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dd79d711c3dd..5040f41e7792 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3083,10 +3083,10 @@ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv); -int i915_gem_execbuffer2(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +int i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a1f2ce1fcd..b15305f2fb76 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -2463,8 +2463,8 @@ static bool check_buffer_count(size_t count) * list array and passes it to the real function. */ int -i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file) +i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_gem_execbuffer *args = data; struct drm_i915_gem_execbuffer2 exec2; @@ -2554,8 +2554,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, } int -i915_gem_execbuffer2(struct drm_device *dev, void *data, - struct drm_file *file) +i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_gem_execbuffer2 *args = data; struct drm_i915_gem_exec_object2 *exec2_list; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e9bba2ab4904..d128277978d7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13479,8 +13479,8 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) return to_intel_crtc(connector->base.state->crtc)->pipe; } -int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file) +int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; struct drm_crtc *drmmode_crtc; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 71355fdec94a..f894e17f784f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1371,8 +1371,8 @@ struct drm_display_mode * intel_encoder_current_mode(struct intel_encoder *encoder); enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); -int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe); static inline bool @@ -1924,8 +1924,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, int usecs); struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe, int plane); -int intel_sprite_set_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); void skl_update_plane(struct intel_plane *plane, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d8900d09bef7..574bd02c5a2e 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1059,8 +1059,8 @@ intel_check_sprite_plane(struct intel_plane *plane, return 0; } -int intel_sprite_set_colorkey(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_intel_sprite_colorkey *set = data; From c56b89f16dd0e7d979399bfe94b4056103dd16a8 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 9 Feb 2018 21:58:46 +0000 Subject: [PATCH 035/113] drm/i915: Use INTEL_GEN everywhere Coccinelle patch: @@ identifier p; @@ -INTEL_INFO(p)->gen +INTEL_GEN(p) Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180208130606.15556-12-tvrtko.ursulin@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180209215847.6660-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_fence_reg.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/intel_audio.c | 2 +- drivers/gpu/drm/i915/intel_bios.c | 2 +- drivers/gpu/drm/i915/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ drivers/gpu/drm/i915/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_mocs.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- drivers/gpu/drm/i915/intel_psr.c | 4 ++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +- drivers/gpu/drm/i915/intel_uncore.c | 6 +++--- 18 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5040f41e7792..a3a02acfc345 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2801,7 +2801,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2) #define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc) -#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_INFO(dev_priv)->gen >= 7) +#define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 7) #define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 349f127330c8..fc68b35854df 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5424,10 +5424,10 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv) { int i; - if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) && + if (INTEL_GEN(dev_priv) >= 7 && !IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) dev_priv->num_fence_regs = 32; - else if (INTEL_INFO(dev_priv)->gen >= 4 || + else if (INTEL_GEN(dev_priv) >= 4 || IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) dev_priv->num_fence_regs = 16; diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c index b8338d75c6f3..d548ac05ccd7 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c +++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c @@ -64,7 +64,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence, int fence_pitch_shift; u64 val; - if (INTEL_INFO(fence->i915)->gen >= 6) { + if (INTEL_GEN(fence->i915) >= 6) { fence_reg_lo = FENCE_REG_GEN6_LO(fence->id); fence_reg_hi = FENCE_REG_GEN6_HI(fence->id); fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 955ce7bee448..0c0f1affddad 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2109,7 +2109,7 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt, ppgtt->base.i915 = dev_priv; ppgtt->base.dma = &dev_priv->drm.pdev->dev; - if (INTEL_INFO(dev_priv)->gen < 8) + if (INTEL_GEN(dev_priv) < 8) return gen6_ppgtt_init(ppgtt); else return gen8_ppgtt_init(ppgtt); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index d3f222fa6356..f18da9e2be8e 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -356,7 +356,7 @@ int i915_gem_init_stolen(struct drm_i915_private *dev_priv) reserved_base = 0; reserved_size = 0; - switch (INTEL_INFO(dev_priv)->gen) { + switch (INTEL_GEN(dev_priv)) { case 2: case 3: break; diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 522d54fecb53..ff455c724775 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -704,7 +704,7 @@ void intel_init_audio_hooks(struct drm_i915_private *dev_priv) } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; - } else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) { + } else if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8) { dev_priv->display.audio_codec_enable = hsw_audio_codec_enable; dev_priv->display.audio_codec_disable = hsw_audio_codec_disable; } else if (HAS_PCH_SPLIT(dev_priv)) { diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4e74aa2f16bc..aa4df6548771 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -391,7 +391,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, static int intel_bios_ssc_frequency(struct drm_i915_private *dev_priv, bool alternate) { - switch (INTEL_INFO(dev_priv)->gen) { + switch (INTEL_GEN(dev_priv)) { case 2: return alternate ? 66667 : 48000; case 3: diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index ee788d5be5e3..aab6d1538fff 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -2233,7 +2233,7 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) return max_cdclk_freq; else if (IS_CHERRYVIEW(dev_priv)) return max_cdclk_freq*95/100; - else if (INTEL_INFO(dev_priv)->gen < 4) + else if (INTEL_GEN(dev_priv) < 4) return 2*max_cdclk_freq*90/100; else return max_cdclk_freq*90/100; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d9b52fe82932..db92a2691206 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2123,7 +2123,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, I915_WRITE(DPLL_CTRL2, val); - } else if (INTEL_INFO(dev_priv)->gen < 9) { + } else if (INTEL_GEN(dev_priv) < 9) { I915_WRITE(PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll)); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d128277978d7..94d03e2cd498 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2029,12 +2029,12 @@ static unsigned int intel_cursor_alignment(const struct drm_i915_private *dev_pr static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return 256 * 1024; else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) || IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) return 128 * 1024; - else if (INTEL_INFO(dev_priv)->gen >= 4) + else if (INTEL_GEN(dev_priv) >= 4) return 4 * 1024; else return 0; @@ -6307,7 +6307,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* GDG double wide on either pipe, otherwise pipe A only */ - return INTEL_INFO(dev_priv)->gen < 4 && + return INTEL_GEN(dev_priv) < 4 && (crtc->pipe == PIPE_A || IS_I915G(dev_priv)); } @@ -8185,7 +8185,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *config = intel_crtc->config; - if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) { + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { u32 val = 0; switch (intel_crtc->config->pipe_bpp) { @@ -13928,7 +13928,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, * gen2/3 display engine uses the fence if present, * so the tiling mode must match the fb modifier exactly. */ - if (INTEL_INFO(dev_priv)->gen < 4 && + if (INTEL_GEN(dev_priv) < 4 && tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) { DRM_DEBUG_KMS("tiling_mode must match fb modifier exactly on gen2/3\n"); goto err; @@ -14116,7 +14116,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) { intel_init_cdclk_hooks(dev_priv); - if (INTEL_INFO(dev_priv)->gen >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = skylake_get_initial_plane_config; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8503d182921b..a2eeede525e0 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1443,7 +1443,7 @@ static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return skl_aux_ctl_reg(dev_priv, port); else if (HAS_PCH_SPLIT(dev_priv)) return ilk_aux_ctl_reg(dev_priv, port); @@ -1454,7 +1454,7 @@ static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, enum port port, int index) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return skl_aux_data_reg(dev_priv, port, index); else if (HAS_PCH_SPLIT(dev_priv)) return ilk_aux_data_reg(dev_priv, port, index); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index ef80499113ee..4677ac0b10d7 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -189,7 +189,7 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv, /* Convert from 100ms to 100us units */ pps->t4 = val * 1000; - if (INTEL_INFO(dev_priv)->gen <= 4 && + if (INTEL_GEN(dev_priv) <= 4 && pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) { DRM_DEBUG_KMS("Panel power timings uninitialized, " "setting defaults\n"); diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index f4c46b0b8f0a..abb7a8c1e340 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -187,7 +187,7 @@ static bool get_mocs_settings(struct drm_i915_private *dev_priv, table->table = broxton_mocs_table; result = true; } else { - WARN_ONCE(INTEL_INFO(dev_priv)->gen >= 9, + WARN_ONCE(INTEL_GEN(dev_priv) >= 9, "Platform that should have a MOCS table does not.\n"); } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e702a6487aa9..78a53c8b1789 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -497,7 +497,7 @@ static u32 i9xx_get_backlight(struct intel_connector *connector) u32 val; val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (INTEL_INFO(dev_priv)->gen < 4) + if (INTEL_GEN(dev_priv) < 4) val >>= 1; if (panel->backlight.combination_mode) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b2f5e3b9ada8..6f98d144924e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6943,7 +6943,7 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) * No floor required for ring frequency on SKL. */ ring_freq = gpu_freq; - } else if (INTEL_INFO(dev_priv)->gen >= 8) { + } else if (INTEL_GEN(dev_priv) >= 8) { /* max(2 * GT, DDR). NB: GT is 50MHz units */ ring_freq = max(min_ring_freq, gpu_freq); } else if (IS_HASWELL(dev_priv)) { @@ -7554,7 +7554,7 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_INFO(dev_priv)->gen != 5) + if (INTEL_GEN(dev_priv) != 5) return 0; spin_lock_irq(&mchdev_lock); @@ -7638,7 +7638,7 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) void i915_update_gfx_val(struct drm_i915_private *dev_priv) { - if (INTEL_INFO(dev_priv)->gen != 5) + if (INTEL_GEN(dev_priv) != 5) return; spin_lock_irq(&mchdev_lock); @@ -7689,7 +7689,7 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_INFO(dev_priv)->gen != 5) + if (INTEL_GEN(dev_priv) != 5) return 0; spin_lock_irq(&mchdev_lock); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index e9feffdea899..2ef374f936b9 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -126,7 +126,7 @@ static void vlv_psr_enable_sink(struct intel_dp *intel_dp) static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, enum port port) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return DP_AUX_CH_CTL(port); else return EDP_PSR_AUX_CTL; @@ -135,7 +135,7 @@ static i915_reg_t psr_aux_ctl_reg(struct drm_i915_private *dev_priv, static i915_reg_t psr_aux_data_reg(struct drm_i915_private *dev_priv, enum port port, int index) { - if (INTEL_INFO(dev_priv)->gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) return DP_AUX_CH_DATA(port, index); else return EDP_PSR_AUX_DATA(index); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c8f95456e430..5718f37160c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -655,7 +655,7 @@ static int init_render_ring(struct intel_engine_cs *engine) if (IS_GEN(dev_priv, 6, 7)) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); - if (INTEL_INFO(dev_priv)->gen >= 6) + if (INTEL_GEN(dev_priv) >= 6) I915_WRITE_IMR(engine, ~engine->irq_keep_mask); return init_workarounds_ring(engine); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index c23af35c081e..2cfac0b60500 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1874,9 +1874,9 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) if (!i915_modparams.reset) return NULL; - if (INTEL_INFO(dev_priv)->gen >= 8) + if (INTEL_GEN(dev_priv) >= 8) return gen8_reset_engines; - else if (INTEL_INFO(dev_priv)->gen >= 6) + else if (INTEL_GEN(dev_priv) >= 6) return gen6_reset_engines; else if (IS_GEN5(dev_priv)) return ironlake_do_reset; @@ -1884,7 +1884,7 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) return g4x_do_reset; else if (IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) return g33_do_reset; - else if (INTEL_INFO(dev_priv)->gen >= 3) + else if (INTEL_GEN(dev_priv) >= 3) return i915_do_reset; else return NULL; From 0f550a21247f6029bba036c06fef8de78dddaa69 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 9 Feb 2018 21:58:47 +0000 Subject: [PATCH 036/113] drm/i915: Replace some negative Gen checks Instead of INTEL_GEN != x use !IS_GENx for more optimisation opportunities. Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180208130606.15556-16-tvrtko.ursulin@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180209215847.6660-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6f98d144924e..b026b020d8b8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7554,7 +7554,7 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_GEN(dev_priv) != 5) + if (!IS_GEN5(dev_priv)) return 0; spin_lock_irq(&mchdev_lock); @@ -7638,7 +7638,7 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) void i915_update_gfx_val(struct drm_i915_private *dev_priv) { - if (INTEL_GEN(dev_priv) != 5) + if (!IS_GEN5(dev_priv)) return; spin_lock_irq(&mchdev_lock); @@ -7689,7 +7689,7 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) { unsigned long val; - if (INTEL_GEN(dev_priv) != 5) + if (!IS_GEN5(dev_priv)) return 0; spin_lock_irq(&mchdev_lock); From ad5169070713cee0be9f533a8f39b2903b7833d8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 9 Feb 2018 11:40:56 +0000 Subject: [PATCH 037/113] drm/i915: Move the final intel_gpu_reset() to after declaring wedged If we fail to reset the GPU (i915_reset()), we do one final intel_gpu_reset() attempt as we mark the device wedged. The idea here is even though the GPU has proven unreliable (and so we want to stop using it for the time being), we don't want it spinning away in the background whilst the driver idles so we try to reset it one more time. However, we want to dump the i915_gem_set_wedged() debugging info before we do, so that we can see the accurate state of the GPU when it failed. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180209114056.9957-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index daa9060bdfcb..7bfc74c1aeb8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1920,7 +1920,6 @@ void i915_reset(struct drm_i915_private *i915, unsigned int flags) ret = i915_gem_reset_prepare(i915); if (ret) { dev_err(i915->drm.dev, "GPU recovery failed\n"); - intel_gpu_reset(i915, ALL_ENGINES); goto taint; } @@ -2003,6 +2002,7 @@ taint: error: i915_gem_set_wedged(i915); i915_gem_retire_requests(i915); + intel_gpu_reset(i915, ALL_ENGINES); goto finish; } From 74d00d28a15c8452f65de0a9477b52d95639cc63 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 12 Feb 2018 09:39:28 +0000 Subject: [PATCH 038/113] drm/i915: Don't wake the device up to check if the engine is asleep If the entire device is powered off, we can safely assume that the engine is also asleep (and idle). Reported-by: Tvrtko Ursulin Fixes: a091d4ee931b ("drm/i915: Hold a wakeref for probing the ring registers") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180212093928.6005-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 0ad9184eba97..3efc589a7f37 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1464,7 +1464,9 @@ static bool ring_is_idle(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; bool idle = true; - intel_runtime_pm_get(dev_priv); + /* If the whole device is asleep, the engine must be idle */ + if (!intel_runtime_pm_get_if_in_use(dev_priv)) + return true; /* First check that no commands are left in the ring */ if ((I915_READ_HEAD(engine) & HEAD_ADDR) != From 3ceda3a4a856336c5c902a6cfbacff2c4effaa21 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 12 Feb 2018 10:24:15 +0000 Subject: [PATCH 039/113] drm/i915: Hold rpm wakeref for printing the engine's register state When dumping the engine, we print out the current register values. This requires the rpm wakeref. If the device is alseep, we can assume the engine is asleep (and the register state is uninteresting) so skip and only acquire the rpm wakeref if the device is already awake. Reported-by: Tvrtko Ursulin Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180212102415.24246-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 162 +++++++++++++----------- drivers/gpu/drm/i915/intel_ringbuffer.h | 6 +- 2 files changed, 94 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 3efc589a7f37..f3c5100d629e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -691,7 +691,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) engine->context_unpin(engine, engine->i915->kernel_context); } -u64 intel_engine_get_active_head(struct intel_engine_cs *engine) +u64 intel_engine_get_active_head(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; u64 acthd; @@ -707,7 +707,7 @@ u64 intel_engine_get_active_head(struct intel_engine_cs *engine) return acthd; } -u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) +u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; u64 bbaddr; @@ -1705,73 +1705,20 @@ static void hexdump(struct drm_printer *m, const void *buf, size_t len) } } -void intel_engine_dump(struct intel_engine_cs *engine, - struct drm_printer *m, - const char *header, ...) +static void intel_engine_print_registers(const struct intel_engine_cs *engine, + struct drm_printer *m) { - struct intel_breadcrumbs * const b = &engine->breadcrumbs; - const struct intel_engine_execlists * const execlists = &engine->execlists; - struct i915_gpu_error * const error = &engine->i915->gpu_error; struct drm_i915_private *dev_priv = engine->i915; - struct drm_i915_gem_request *rq; - struct rb_node *rb; - char hdr[80]; + const struct intel_engine_execlists * const execlists = + &engine->execlists; u64 addr; - if (header) { - va_list ap; - - va_start(ap, header); - drm_vprintf(m, header, &ap); - va_end(ap); - } - - if (i915_terminally_wedged(&engine->i915->gpu_error)) - drm_printf(m, "*** WEDGED ***\n"); - - drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", - intel_engine_get_seqno(engine), - intel_engine_last_submit(engine), - engine->hangcheck.seqno, - jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), - engine->timeline->inflight_seqnos); - drm_printf(m, "\tReset count: %d (global %d)\n", - i915_reset_engine_count(error, engine), - i915_reset_count(error)); - - rcu_read_lock(); - - drm_printf(m, "\tRequests:\n"); - - rq = list_first_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tfirst "); - - rq = list_last_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tlast "); - - rq = i915_gem_find_active_request(engine); - if (rq) { - print_request(m, rq, "\t\tactive "); - drm_printf(m, - "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", - rq->head, rq->postfix, rq->tail, - rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, - rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); - } - - drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", - I915_READ(RING_START(engine->mmio_base)), - rq ? i915_ggtt_offset(rq->ring->vma) : 0); - drm_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", - I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, - rq ? rq->ring->head : 0); - drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", - I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, - rq ? rq->ring->tail : 0); + drm_printf(m, "\tRING_START: 0x%08x\n", + I915_READ(RING_START(engine->mmio_base))); + drm_printf(m, "\tRING_HEAD: 0x%08x\n", + I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR); + drm_printf(m, "\tRING_TAIL: 0x%08x\n", + I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR); drm_printf(m, "\tRING_CTL: 0x%08x%s\n", I915_READ(RING_CTL(engine->mmio_base)), I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? " [waiting]" : ""); @@ -1780,6 +1727,11 @@ void intel_engine_dump(struct intel_engine_cs *engine, I915_READ(RING_MI_MODE(engine->mmio_base)), I915_READ(RING_MI_MODE(engine->mmio_base)) & (MODE_IDLE) ? " [idle]" : ""); } + + if (INTEL_GEN(dev_priv) >= 6) { + drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine)); + } + if (HAS_LEGACY_SEMAPHORES(dev_priv)) { drm_printf(m, "\tSYNC_0: 0x%08x\n", I915_READ(RING_SYNC_0(engine->mmio_base))); @@ -1790,8 +1742,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, I915_READ(RING_SYNC_2(engine->mmio_base))); } - rcu_read_unlock(); - addr = intel_engine_get_active_head(engine); drm_printf(m, "\tACTHD: 0x%08x_%08x\n", upper_32_bits(addr), lower_32_bits(addr)); @@ -1853,10 +1803,13 @@ void intel_engine_dump(struct intel_engine_cs *engine, rcu_read_lock(); for (idx = 0; idx < execlists_num_ports(execlists); idx++) { + struct drm_i915_gem_request *rq; unsigned int count; rq = port_unpack(&execlists->port[idx], &count); if (rq) { + char hdr[80]; + snprintf(hdr, sizeof(hdr), "\t\tELSP[%d] count=%d, rq: ", idx, count); @@ -1875,6 +1828,77 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(engine))); } +} + +void intel_engine_dump(struct intel_engine_cs *engine, + struct drm_printer *m, + const char *header, ...) +{ + struct intel_breadcrumbs * const b = &engine->breadcrumbs; + const struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_gpu_error * const error = &engine->i915->gpu_error; + struct drm_i915_gem_request *rq; + struct rb_node *rb; + + if (header) { + va_list ap; + + va_start(ap, header); + drm_vprintf(m, header, &ap); + va_end(ap); + } + + if (i915_terminally_wedged(&engine->i915->gpu_error)) + drm_printf(m, "*** WEDGED ***\n"); + + drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", + intel_engine_get_seqno(engine), + intel_engine_last_submit(engine), + engine->hangcheck.seqno, + jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), + engine->timeline->inflight_seqnos); + drm_printf(m, "\tReset count: %d (global %d)\n", + i915_reset_engine_count(error, engine), + i915_reset_count(error)); + + rcu_read_lock(); + + drm_printf(m, "\tRequests:\n"); + + rq = list_first_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tfirst "); + + rq = list_last_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tlast "); + + rq = i915_gem_find_active_request(engine); + if (rq) { + print_request(m, rq, "\t\tactive "); + drm_printf(m, + "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", + rq->head, rq->postfix, rq->tail, + rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, + rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); + drm_printf(m, "\t\tring->start: 0x%08x\n", + i915_ggtt_offset(rq->ring->vma)); + drm_printf(m, "\t\tring->head: 0x%08x\n", + rq->ring->head); + drm_printf(m, "\t\tring->tail: 0x%08x\n", + rq->ring->tail); + } + + rcu_read_unlock(); + + if (intel_runtime_pm_get_if_in_use(engine->i915)) { + intel_engine_print_registers(engine, m); + intel_runtime_pm_put(engine->i915); + } else { + drm_printf(m, "\tDevice is asleep; skipping register dump\n"); + } spin_lock_irq(&engine->timeline->lock); list_for_each_entry(rq, &engine->timeline->requests, link) @@ -1897,10 +1921,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, } spin_unlock_irq(&b->rb_lock); - if (INTEL_GEN(dev_priv) >= 6) { - drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine)); - } - drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s) (execlists? %s)\n", engine->irq_posted, yesno(test_bit(ENGINE_IRQ_BREADCRUMB, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 8f1a4badf812..51523ad049de 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -659,7 +659,7 @@ intel_engine_flag(const struct intel_engine_cs *engine) } static inline u32 -intel_read_status_page(struct intel_engine_cs *engine, int reg) +intel_read_status_page(const struct intel_engine_cs *engine, int reg) { /* Ensure that the compiler doesn't optimize away the load. */ return READ_ONCE(engine->status_page.page_addr[reg]); @@ -817,8 +817,8 @@ int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine); int intel_init_blt_ring_buffer(struct intel_engine_cs *engine); int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine); -u64 intel_engine_get_active_head(struct intel_engine_cs *engine); -u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine); +u64 intel_engine_get_active_head(const struct intel_engine_cs *engine); +u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine); static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) { From 51cc9adef064c8cf3df6d24e8662e9151529decf Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 8 Feb 2018 19:41:02 +0200 Subject: [PATCH 040/113] drm/i915: Don't query PCODE RC6VIDS on platforms not supporting it On BXT/GLK GEN6_PCODE_READ_RC6VIDS fails with MAILBOX_P24C_CC_ILLEGAL_CMD, so don't try to do the query on these platforms. Do it only on SNB, IVB and HSW, where we use this command anyway for RC6 enabling. Based on my tests the command also succeeds on all LLC platforms, but it's not clear if it's really supported on those (it returns 0 aka 245mv for all RC6 states everywhere except on SNB). BSpec lists the command as supported on SKL+ (see P24C_PCODE_MAILBOX_INTERFACE) but that's clearly incorrect, since on SKL/KBL the same command ID is used for SKL_PCODE_LOAD_HDCP_KEYS. Since the command fails on BXT/GLK, the BSpec command list is also incorrect for those platforms (see P_CR_P24C_PCODE_MAILBOX_INTERFACE_0_2_0_GTTMMADR). I filed a request to update that info in Bspec, but for now let's assume a minimal set of platforms where the command is supported. References: https://bugs.freedesktop.org/show_bug.cgi?id=103337 Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208174102.10240-1-imre.deak@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index eff5548ec093..960302668649 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1471,9 +1471,12 @@ static int gen6_drpc_info(struct seq_file *m) gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS); } - mutex_lock(&dev_priv->pcu_lock); - sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); - mutex_unlock(&dev_priv->pcu_lock); + if (INTEL_GEN(dev_priv) <= 7) { + mutex_lock(&dev_priv->pcu_lock); + sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, + &rc6vids); + mutex_unlock(&dev_priv->pcu_lock); + } seq_printf(m, "RC1e Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); @@ -1529,12 +1532,15 @@ static int gen6_drpc_info(struct seq_file *m) print_rc6_res(m, "RC6+ residency since boot:", GEN6_GT_GFX_RC6p); print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp); - seq_printf(m, "RC6 voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); - seq_printf(m, "RC6+ voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); - seq_printf(m, "RC6++ voltage: %dmV\n", - GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); + if (INTEL_GEN(dev_priv) <= 7) { + seq_printf(m, "RC6 voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 0) & 0xff))); + seq_printf(m, "RC6+ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 8) & 0xff))); + seq_printf(m, "RC6++ voltage: %dmV\n", + GEN6_DECODE_RC6_VID(((rc6vids >> 16) & 0xff))); + } + return i915_forcewake_domains(m, NULL); } From e53792f44d8bde64022093cfc3f39db0e7d39212 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 12 Feb 2018 13:31:18 +0000 Subject: [PATCH 041/113] drm/i915: Replace open-coded memset_p() When initialising the page directories, we set the GTT entries and the tree to the scratch page. We have already replaced the DMA fill with memset64(), but we can similarly use memset_p() to set the pointer array. References: 4dd504f7d98a ("drm/i915: Use memset64() to prefill the GTT page") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Matthew Auld Cc: Mika Kuoppala Reviewed-by: Matthew Auld Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180212133118.16443-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0c0f1affddad..a44eccda7d48 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -673,27 +673,22 @@ static void free_pd(struct i915_address_space *vm, static void gen8_initialize_pd(struct i915_address_space *vm, struct i915_page_directory *pd) { - unsigned int i; - fill_px(vm, pd, gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC)); - for (i = 0; i < I915_PDES; i++) - pd->page_table[i] = vm->scratch_pt; + memset_p((void **)pd->page_table, vm->scratch_pt, I915_PDES); } static int __pdp_init(struct i915_address_space *vm, struct i915_page_directory_pointer *pdp) { const unsigned int pdpes = i915_pdpes_per_pdp(vm); - unsigned int i; pdp->page_directory = kmalloc_array(pdpes, sizeof(*pdp->page_directory), GFP_KERNEL | __GFP_NOWARN); if (unlikely(!pdp->page_directory)) return -ENOMEM; - for (i = 0; i < pdpes; i++) - pdp->page_directory[i] = vm->scratch_pd; + memset_p((void **)pdp->page_directory, vm->scratch_pd, pdpes); return 0; } @@ -764,12 +759,9 @@ static void gen8_initialize_pdp(struct i915_address_space *vm, static void gen8_initialize_pml4(struct i915_address_space *vm, struct i915_pml4 *pml4) { - unsigned int i; - fill_px(vm, pml4, gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC)); - for (i = 0; i < GEN8_PML4ES_PER_PML4; i++) - pml4->pdps[i] = vm->scratch_pdp; + memset_p((void **)pml4->pdps, vm->scratch_pdp, GEN8_PML4ES_PER_PML4); } /* Broadwell Page Directory Pointer Descriptors */ From 3758d96808b9942de9272079d5a24c6c0d2b6c7a Mon Sep 17 00:00:00 2001 From: David Weinehall Date: Fri, 9 Feb 2018 15:07:55 +0200 Subject: [PATCH 042/113] drm/i915: Fix incorrect comment While the comment singles out Port A or B, the code says Port A or *D*. Looking at the history it seems that the comment was added after the code, so it seems likely that the code is correct, not the comment. CC: Jani Nikula CC: Rodrigo Vivi Signed-off-by: David Weinehall Reviewed-by: James Ausmus Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180209130755.11893-1-david.weinehall@linux.intel.com --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a2eeede525e0..1868f73f730c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -256,7 +256,7 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp) if (IS_CNL_WITH_PORT_F(dev_priv)) return 810000; - /* For other SKUs, max rate on ports A and B is 5.4G */ + /* For other SKUs, max rate on ports A and D is 5.4G */ if (port == PORT_A || port == PORT_D) return 540000; From 62d4a5e149552ef1f1757197652ae7be4fc9f3a3 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 5 Feb 2018 13:40:41 -0200 Subject: [PATCH 043/113] drm/i915/icl: add ICL support to cnl_set_procmon_ref_values On ICL we have two sets of registers: one for port A and another for port B. The set of port A registers is the same as the CNL registers. Since the procmon table on ICL is the same we want to reuse the CNL function. To do that we add a port argument and make CNL always call the function passing port A. This way, we'll be able to easily reuse the function on ICL when we add icl_display_core_init(). v2: Don't use _PICK() when you can use a ternary operator. v3: Don't use a ternary operation when you can use _MMIO_PORT (Ville). Add an extra comment about why we're passing PORT_A (James). Reviewed-by: James Ausmus Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180205154046.11485-2-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/intel_runtime_pm.c | 22 +++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1489dd3b3ec2..4551f1725771 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2104,6 +2104,28 @@ enum i915_power_well_id { #define CNL_PORT_COMP_DW9 _MMIO(0x162124) #define CNL_PORT_COMP_DW10 _MMIO(0x162128) +#define _ICL_PORT_COMP_DW0_A 0x162100 +#define _ICL_PORT_COMP_DW0_B 0x6C100 +#define ICL_PORT_COMP_DW0(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW0_A, \ + _ICL_PORT_COMP_DW0_B) +#define _ICL_PORT_COMP_DW1_A 0x162104 +#define _ICL_PORT_COMP_DW1_B 0x6C104 +#define ICL_PORT_COMP_DW1(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW1_A, \ + _ICL_PORT_COMP_DW1_B) +#define _ICL_PORT_COMP_DW3_A 0x16210C +#define _ICL_PORT_COMP_DW3_B 0x6C10C +#define ICL_PORT_COMP_DW3(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW3_A, \ + _ICL_PORT_COMP_DW3_B) +#define _ICL_PORT_COMP_DW9_A 0x162124 +#define _ICL_PORT_COMP_DW9_B 0x6C124 +#define ICL_PORT_COMP_DW9(port) _MMIO_PORT(port, _ICL_PORT_COMP_DW9_A, \ + _ICL_PORT_COMP_DW9_B) +#define _ICL_PORT_COMP_DW10_A 0x162128 +#define _ICL_PORT_COMP_DW10_B 0x6C128 +#define ICL_PORT_COMP_DW10(port) _MMIO_PORT(port, \ + _ICL_PORT_COMP_DW10_A, \ + _ICL_PORT_COMP_DW10_B) + /* BXT PHY Ref registers */ #define _PORT_REF_DW3_A 0x16218C #define _PORT_REF_DW3_BC 0x6C18C diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 70e659772a7a..b4ef7875f055 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2794,12 +2794,19 @@ static const struct cnl_procmon { { .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, }; -static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv) +/* + * CNL has just one set of registers, while ICL has two sets: one for port A and + * the other for port B. The CNL registers are equivalent to the ICL port A + * registers, that's why we call the ICL macros even though the function has CNL + * on its name. + */ +static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv, + enum port port) { const struct cnl_procmon *procmon; u32 val; - val = I915_READ(CNL_PORT_COMP_DW3); + val = I915_READ(ICL_PORT_COMP_DW3(port)); switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) { default: MISSING_CASE(val); @@ -2820,13 +2827,13 @@ static void cnl_set_procmon_ref_values(struct drm_i915_private *dev_priv) break; } - val = I915_READ(CNL_PORT_COMP_DW1); + val = I915_READ(ICL_PORT_COMP_DW1(port)); val &= ~((0xff << 16) | 0xff); val |= procmon->dw1; - I915_WRITE(CNL_PORT_COMP_DW1, val); + I915_WRITE(ICL_PORT_COMP_DW1(port), val); - I915_WRITE(CNL_PORT_COMP_DW9, procmon->dw9); - I915_WRITE(CNL_PORT_COMP_DW10, procmon->dw10); + I915_WRITE(ICL_PORT_COMP_DW9(port), procmon->dw9); + I915_WRITE(ICL_PORT_COMP_DW10(port), procmon->dw10); } static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume) @@ -2847,7 +2854,8 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume val &= ~CNL_COMP_PWR_DOWN; I915_WRITE(CHICKEN_MISC_2, val); - cnl_set_procmon_ref_values(dev_priv); + /* Dummy PORT_A to get the correct CNL register from the ICL macro */ + cnl_set_procmon_ref_values(dev_priv, PORT_A); val = I915_READ(CNL_PORT_COMP_DW0); val |= COMP_INIT; From 186a277e317a14dcba5a2d709f2fbd8c078dfa6f Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 6 Feb 2018 17:33:46 -0200 Subject: [PATCH 044/113] drm/i915/icl: add the main CDCLK functions This commit adds the basic CDCLK functions, but it's still missing pieces of the display initialization sequence. v2: - Implement the voltage levels. - Rebase. v3: - Adjust to the new "bypass" clock (Imre). - Call intel_dump_cdclk_state() too. - Rename a variable to avoid confusion. - Simplify the DVFS part. v4: - Remove wrong bit definition (James). - Also drive-by fix the coding style for the register definition we touched. v5: - Comment style (checkpatch). Cc: James Ausmus Cc: Imre Deak Reviewed-by: James Ausmus Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180206193346.18272-1-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 35 +++-- drivers/gpu/drm/i915/intel_cdclk.c | 237 ++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_drv.h | 2 + 3 files changed, 257 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4551f1725771..76542f7504a6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7181,8 +7181,12 @@ enum { #define SKL_DFSM_PIPE_B_DISABLE (1 << 21) #define SKL_DFSM_PIPE_C_DISABLE (1 << 28) -#define SKL_DSSM _MMIO(0x51004) -#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31) +#define SKL_DSSM _MMIO(0x51004) +#define CNL_DSSM_CDCLK_PLL_REFCLK_24MHz (1 << 31) +#define ICL_DSSM_CDCLK_PLL_REFCLK_MASK (7 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_24MHz (0 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29) +#define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29) #define GEN7_FF_SLICE_CS_CHICKEN1 _MMIO(0x20e0) #define GEN9_FFSC_PERCTX_PREEMPT_CTRL (1<<14) @@ -8731,20 +8735,21 @@ enum skl_power_gate { /* CDCLK_CTL */ #define CDCLK_CTL _MMIO(0x46000) -#define CDCLK_FREQ_SEL_MASK (3<<26) -#define CDCLK_FREQ_450_432 (0<<26) -#define CDCLK_FREQ_540 (1<<26) -#define CDCLK_FREQ_337_308 (2<<26) -#define CDCLK_FREQ_675_617 (3<<26) -#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_1 (0<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_2 (2<<22) -#define BXT_CDCLK_CD2X_DIV_SEL_4 (3<<22) -#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe)<<20) -#define CDCLK_DIVMUX_CD_OVERRIDE (1<<19) +#define CDCLK_FREQ_SEL_MASK (3 << 26) +#define CDCLK_FREQ_450_432 (0 << 26) +#define CDCLK_FREQ_540 (1 << 26) +#define CDCLK_FREQ_337_308 (2 << 26) +#define CDCLK_FREQ_675_617 (3 << 26) +#define BXT_CDCLK_CD2X_DIV_SEL_MASK (3 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_1 (0 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_1_5 (1 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_2 (2 << 22) +#define BXT_CDCLK_CD2X_DIV_SEL_4 (3 << 22) +#define BXT_CDCLK_CD2X_PIPE(pipe) ((pipe) << 20) +#define CDCLK_DIVMUX_CD_OVERRIDE (1 << 19) #define BXT_CDCLK_CD2X_PIPE_NONE BXT_CDCLK_CD2X_PIPE(3) -#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1<<16) +#define ICL_CDCLK_CD2X_PIPE_NONE (7 << 19) +#define BXT_CDCLK_SSA_PRECHARGE_ENABLE (1 << 16) #define CDCLK_FREQ_DECIMAL_MASK (0x7ff) /* LCPLL_CTL */ diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index aab6d1538fff..dc7db8a2caf8 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -1778,6 +1778,199 @@ sanitize: dev_priv->cdclk.hw.vco = -1; } +static int icl_calc_cdclk(int min_cdclk, unsigned int ref) +{ + int ranges_24[] = { 312000, 552000, 648000 }; + int ranges_19_38[] = { 307200, 556800, 652800 }; + int *ranges; + + switch (ref) { + default: + MISSING_CASE(ref); + case 24000: + ranges = ranges_24; + break; + case 19200: + case 38400: + ranges = ranges_19_38; + break; + } + + if (min_cdclk > ranges[1]) + return ranges[2]; + else if (min_cdclk > ranges[0]) + return ranges[1]; + else + return ranges[0]; +} + +static int icl_calc_cdclk_pll_vco(struct drm_i915_private *dev_priv, int cdclk) +{ + int ratio; + + if (cdclk == dev_priv->cdclk.hw.bypass) + return 0; + + switch (cdclk) { + default: + MISSING_CASE(cdclk); + case 307200: + case 556800: + case 652800: + WARN_ON(dev_priv->cdclk.hw.ref != 19200 && + dev_priv->cdclk.hw.ref != 38400); + break; + case 312000: + case 552000: + case 648000: + WARN_ON(dev_priv->cdclk.hw.ref != 24000); + } + + ratio = cdclk / (dev_priv->cdclk.hw.ref / 2); + + return dev_priv->cdclk.hw.ref * ratio; +} + +static void icl_set_cdclk(struct drm_i915_private *dev_priv, + const struct intel_cdclk_state *cdclk_state) +{ + unsigned int cdclk = cdclk_state->cdclk; + unsigned int vco = cdclk_state->vco; + int ret; + + mutex_lock(&dev_priv->pcu_lock); + ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL, + SKL_CDCLK_PREPARE_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, + SKL_CDCLK_READY_FOR_CHANGE, 3); + mutex_unlock(&dev_priv->pcu_lock); + if (ret) { + DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n", + ret); + return; + } + + if (dev_priv->cdclk.hw.vco != 0 && + dev_priv->cdclk.hw.vco != vco) + cnl_cdclk_pll_disable(dev_priv); + + if (dev_priv->cdclk.hw.vco != vco) + cnl_cdclk_pll_enable(dev_priv, vco); + + I915_WRITE(CDCLK_CTL, ICL_CDCLK_CD2X_PIPE_NONE | + skl_cdclk_decimal(cdclk)); + + mutex_lock(&dev_priv->pcu_lock); + /* TODO: add proper DVFS support. */ + sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, 2); + mutex_unlock(&dev_priv->pcu_lock); + + intel_update_cdclk(dev_priv); +} + +static void icl_get_cdclk(struct drm_i915_private *dev_priv, + struct intel_cdclk_state *cdclk_state) +{ + u32 val; + + cdclk_state->bypass = 50000; + + val = I915_READ(SKL_DSSM); + switch (val & ICL_DSSM_CDCLK_PLL_REFCLK_MASK) { + default: + MISSING_CASE(val); + case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz: + cdclk_state->ref = 24000; + break; + case ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz: + cdclk_state->ref = 19200; + break; + case ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz: + cdclk_state->ref = 38400; + break; + } + + val = I915_READ(BXT_DE_PLL_ENABLE); + if ((val & BXT_DE_PLL_PLL_ENABLE) == 0 || + (val & BXT_DE_PLL_LOCK) == 0) { + /* + * CDCLK PLL is disabled, the VCO/ratio doesn't matter, but + * setting it to zero is a way to signal that. + */ + cdclk_state->vco = 0; + cdclk_state->cdclk = cdclk_state->bypass; + return; + } + + cdclk_state->vco = (val & BXT_DE_PLL_RATIO_MASK) * cdclk_state->ref; + + val = I915_READ(CDCLK_CTL); + WARN_ON((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0); + + cdclk_state->cdclk = cdclk_state->vco / 2; +} + +/** + * icl_init_cdclk - Initialize CDCLK on ICL + * @dev_priv: i915 device + * + * Initialize CDCLK for ICL. This consists mainly of initializing + * dev_priv->cdclk.hw and sanitizing the state of the hardware if needed. This + * is generally done only during the display core initialization sequence, after + * which the DMC will take care of turning CDCLK off/on as needed. + */ +void icl_init_cdclk(struct drm_i915_private *dev_priv) +{ + struct intel_cdclk_state sanitized_state; + u32 val; + + /* This sets dev_priv->cdclk.hw. */ + intel_update_cdclk(dev_priv); + intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK"); + + /* This means CDCLK disabled. */ + if (dev_priv->cdclk.hw.cdclk == dev_priv->cdclk.hw.bypass) + goto sanitize; + + val = I915_READ(CDCLK_CTL); + + if ((val & BXT_CDCLK_CD2X_DIV_SEL_MASK) != 0) + goto sanitize; + + if ((val & CDCLK_FREQ_DECIMAL_MASK) != + skl_cdclk_decimal(dev_priv->cdclk.hw.cdclk)) + goto sanitize; + + return; + +sanitize: + DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n"); + + sanitized_state.ref = dev_priv->cdclk.hw.ref; + sanitized_state.cdclk = icl_calc_cdclk(0, sanitized_state.ref); + sanitized_state.vco = icl_calc_cdclk_pll_vco(dev_priv, + sanitized_state.cdclk); + + icl_set_cdclk(dev_priv, &sanitized_state); +} + +/** + * icl_uninit_cdclk - Uninitialize CDCLK on ICL + * @dev_priv: i915 device + * + * Uninitialize CDCLK for ICL. This is done only during the display core + * uninitialization sequence. + */ +void icl_uninit_cdclk(struct drm_i915_private *dev_priv) +{ + struct intel_cdclk_state cdclk_state = dev_priv->cdclk.hw; + + cdclk_state.cdclk = cdclk_state.bypass; + cdclk_state.vco = 0; + + icl_set_cdclk(dev_priv, &cdclk_state); +} + /** * cnl_init_cdclk - Initialize CDCLK on CNL * @dev_priv: i915 device @@ -2216,6 +2409,36 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state) return 0; } +static int icl_modeset_calc_cdclk(struct drm_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->dev); + struct intel_atomic_state *intel_state = to_intel_atomic_state(state); + unsigned int ref = intel_state->cdclk.logical.ref; + int min_cdclk, cdclk, vco; + + min_cdclk = intel_compute_min_cdclk(state); + if (min_cdclk < 0) + return min_cdclk; + + cdclk = icl_calc_cdclk(min_cdclk, ref); + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk); + + intel_state->cdclk.logical.vco = vco; + intel_state->cdclk.logical.cdclk = cdclk; + + if (!intel_state->active_crtcs) { + cdclk = icl_calc_cdclk(0, ref); + vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk); + + intel_state->cdclk.actual.vco = vco; + intel_state->cdclk.actual.cdclk = cdclk; + } else { + intel_state->cdclk.actual = intel_state->cdclk.logical; + } + + return 0; +} + static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) { int max_cdclk_freq = dev_priv->max_cdclk_freq; @@ -2249,7 +2472,12 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv) */ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) { - if (IS_CANNONLAKE(dev_priv)) { + if (IS_ICELAKE(dev_priv)) { + if (dev_priv->cdclk.hw.ref == 24000) + dev_priv->max_cdclk_freq = 648000; + else + dev_priv->max_cdclk_freq = 652800; + } else if (IS_CANNONLAKE(dev_priv)) { dev_priv->max_cdclk_freq = 528000; } else if (IS_GEN9_BC(dev_priv)) { u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; @@ -2473,9 +2701,14 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) dev_priv->display.set_cdclk = cnl_set_cdclk; dev_priv->display.modeset_calc_cdclk = cnl_modeset_calc_cdclk; + } else if (IS_ICELAKE(dev_priv)) { + dev_priv->display.set_cdclk = icl_set_cdclk; + dev_priv->display.modeset_calc_cdclk = icl_modeset_calc_cdclk; } - if (IS_CANNONLAKE(dev_priv)) + if (IS_ICELAKE(dev_priv)) + dev_priv->display.get_cdclk = icl_get_cdclk; + else if (IS_CANNONLAKE(dev_priv)) dev_priv->display.get_cdclk = cnl_get_cdclk; else if (IS_GEN9_BC(dev_priv)) dev_priv->display.get_cdclk = skl_get_cdclk; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f894e17f784f..5853d92a6512 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1323,6 +1323,8 @@ void cnl_init_cdclk(struct drm_i915_private *dev_priv); void cnl_uninit_cdclk(struct drm_i915_private *dev_priv); void bxt_init_cdclk(struct drm_i915_private *dev_priv); void bxt_uninit_cdclk(struct drm_i915_private *dev_priv); +void icl_init_cdclk(struct drm_i915_private *dev_priv); +void icl_uninit_cdclk(struct drm_i915_private *dev_priv); void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); void intel_update_max_cdclk(struct drm_i915_private *dev_priv); void intel_update_cdclk(struct drm_i915_private *dev_priv); From ad186f3fd98a958d38cd6cf642b21b603bee1b36 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 5 Feb 2018 13:40:43 -0200 Subject: [PATCH 045/113] drm/i915/icl: implement the display init/uninit sequences This code is similar enough to the CNL code that I considered just adding ICL support to the CNL function, but I think it's still different enough, and having a function specific to ICL allows us to more easily adapt code in case the spec changes more later. We're still missing the power wells and the mbus code, so leave those pieces with a FIXME comment while they're not here yet. v2: Don't use _PICK, don't WARN_ON(1), don't forget the chicken bits. v3: Use _MMIO_PORT() (Ville). Reviewed-by: James Ausmus (v2) Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180205154046.11485-4-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 16 ++++- drivers/gpu/drm/i915/intel_runtime_pm.c | 82 ++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 76542f7504a6..f50374308330 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1906,6 +1906,11 @@ enum i915_power_well_id { #define CL_POWER_DOWN_ENABLE (1 << 4) #define SUS_CLOCK_CONFIG (3 << 0) +#define _ICL_PORT_CL_DW5_A 0x162014 +#define _ICL_PORT_CL_DW5_B 0x6C014 +#define ICL_PORT_CL_DW5(port) _MMIO_PORT(port, _ICL_PORT_CL_DW5_A, \ + _ICL_PORT_CL_DW5_B) + #define _PORT_CL1CM_DW9_A 0x162024 #define _PORT_CL1CM_DW9_BC 0x6C024 #define IREF0RC_OFFSET_SHIFT 8 @@ -7168,8 +7173,9 @@ enum { #define RESET_PCH_HANDSHAKE_ENABLE (1<<4) #define GEN8_CHICKEN_DCPR_1 _MMIO(0x46430) -#define SKL_SELECT_ALTERNATE_DC_EXIT (1<<30) -#define MASK_WAKEMEM (1<<13) +#define SKL_SELECT_ALTERNATE_DC_EXIT (1 << 30) +#define MASK_WAKEMEM (1 << 13) +#define CNL_DDI_CLOCK_REG_ACCESS_ON (1 << 7) #define SKL_DFSM _MMIO(0x51000) #define SKL_DFSM_CDCLK_LIMIT_MASK (3 << 23) @@ -9658,4 +9664,10 @@ enum skl_power_gate { #define MMCD_PCLA (1 << 31) #define MMCD_HOTSPOT_EN (1 << 27) +#define _ICL_PHY_MISC_A 0x64C00 +#define _ICL_PHY_MISC_B 0x64C04 +#define ICL_PHY_MISC(port) _MMIO_PORT(port, _ICL_PHY_MISC_A, \ + _ICL_PHY_MISC_B) +#define ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN (1 << 23) + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index b4ef7875f055..c432a661bdd3 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2919,6 +2919,80 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) I915_WRITE(CHICKEN_MISC_2, val); } +static void icl_display_core_init(struct drm_i915_private *dev_priv, + bool resume) +{ + enum port port; + u32 val; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + /* 1. Enable PCH reset handshake. */ + val = I915_READ(HSW_NDE_RSTWRN_OPT); + val |= RESET_PCH_HANDSHAKE_ENABLE; + I915_WRITE(HSW_NDE_RSTWRN_OPT, val); + + for (port = PORT_A; port <= PORT_B; port++) { + /* 2. Enable DDI combo PHY comp. */ + val = I915_READ(ICL_PHY_MISC(port)); + val &= ~ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN; + I915_WRITE(ICL_PHY_MISC(port), val); + + cnl_set_procmon_ref_values(dev_priv, port); + + val = I915_READ(ICL_PORT_COMP_DW0(port)); + val |= COMP_INIT; + I915_WRITE(ICL_PORT_COMP_DW0(port), val); + + /* 3. Set power down enable. */ + val = I915_READ(ICL_PORT_CL_DW5(port)); + val |= CL_POWER_DOWN_ENABLE; + I915_WRITE(ICL_PORT_CL_DW5(port), val); + } + + /* 4. Enable power well 1 (PG1) and aux IO power. */ + /* FIXME: ICL power wells code not here yet. */ + + /* 5. Enable CDCLK. */ + icl_init_cdclk(dev_priv); + + /* 6. Enable DBUF. */ + gen9_dbuf_enable(dev_priv); + + /* 7. Setup MBUS. */ + /* FIXME: MBUS code not here yet. */ + + /* 8. CHICKEN_DCPR_1 */ + I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) | + CNL_DDI_CLOCK_REG_ACCESS_ON); +} + +static void icl_display_core_uninit(struct drm_i915_private *dev_priv) +{ + enum port port; + u32 val; + + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + + /* 1. Disable all display engine functions -> aready done */ + + /* 2. Disable DBUF */ + gen9_dbuf_disable(dev_priv); + + /* 3. Disable CD clock */ + icl_uninit_cdclk(dev_priv); + + /* 4. Disable Power Well 1 (PG1) and Aux IO Power */ + /* FIXME: ICL power wells code not here yet. */ + + /* 5. Disable Comp */ + for (port = PORT_A; port <= PORT_B; port++) { + val = I915_READ(ICL_PHY_MISC(port)); + val |= ICL_PHY_MISC_DE_IO_COMP_PWR_DOWN; + I915_WRITE(ICL_PHY_MISC(port), val); + } +} + static void chv_phy_control_init(struct drm_i915_private *dev_priv) { struct i915_power_well *cmn_bc = @@ -3051,7 +3125,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) power_domains->initializing = true; - if (IS_CANNONLAKE(dev_priv)) { + if (IS_ICELAKE(dev_priv)) { + icl_display_core_init(dev_priv, resume); + } else if (IS_CANNONLAKE(dev_priv)) { cnl_display_core_init(dev_priv, resume); } else if (IS_GEN9_BC(dev_priv)) { skl_display_core_init(dev_priv, resume); @@ -3092,7 +3168,9 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); - if (IS_CANNONLAKE(dev_priv)) + if (IS_ICELAKE(dev_priv)) + icl_display_core_uninit(dev_priv); + else if (IS_CANNONLAKE(dev_priv)) cnl_display_core_uninit(dev_priv); else if (IS_GEN9_BC(dev_priv)) skl_display_core_uninit(dev_priv); From 746edf8f66ed8aa6aeba90b301530a16461844e8 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Mon, 5 Feb 2018 13:40:44 -0200 Subject: [PATCH 046/113] drm/i915/icl: Enable both DBuf slices during init ICL has 2 slices of DBuf, enable both the slices during display init. Ideally we should only enable the second slice when needed in order to save power, but while we're not there yet, adopt the simpler solution to keep us bug-free. v2 (from Paulo): - Add the TODO comment. - Reorganize where things are defined. - Fix indentation. - Remove unnecessary POSTING_READ() calls. - Improve the commit message. Reviewed-by: Paulo Zanoni Signed-off-by: Mahesh Kumar Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180205154046.11485-5-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_runtime_pm.c | 34 +++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f50374308330..e84993dd9886 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7164,6 +7164,8 @@ enum { #define DISP_DATA_PARTITION_5_6 (1<<6) #define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) +#define DBUF_CTL_S1 _MMIO(0x45008) +#define DBUF_CTL_S2 _MMIO(0x44FE8) #define DBUF_POWER_REQUEST (1<<31) #define DBUF_POWER_STATE (1<<30) #define GEN7_MSG_CTL _MMIO(0x45010) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index c432a661bdd3..7e8694a70661 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2646,6 +2646,36 @@ static void gen9_dbuf_disable(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power disable timeout!\n"); } +/* + * TODO: we shouldn't always enable DBUF_CTL_S2, we should only enable it when + * needed and keep it disabled as much as possible. + */ +static void icl_dbuf_enable(struct drm_i915_private *dev_priv) +{ + I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) | DBUF_POWER_REQUEST); + I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) | DBUF_POWER_REQUEST); + POSTING_READ(DBUF_CTL_S2); + + udelay(10); + + if (!(I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || + !(I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) + DRM_ERROR("DBuf power enable timeout\n"); +} + +static void icl_dbuf_disable(struct drm_i915_private *dev_priv) +{ + I915_WRITE(DBUF_CTL_S1, I915_READ(DBUF_CTL_S1) & ~DBUF_POWER_REQUEST); + I915_WRITE(DBUF_CTL_S2, I915_READ(DBUF_CTL_S2) & ~DBUF_POWER_REQUEST); + POSTING_READ(DBUF_CTL_S2); + + udelay(10); + + if ((I915_READ(DBUF_CTL_S1) & DBUF_POWER_STATE) || + (I915_READ(DBUF_CTL_S2) & DBUF_POWER_STATE)) + DRM_ERROR("DBuf power disable timeout!\n"); +} + static void skl_display_core_init(struct drm_i915_private *dev_priv, bool resume) { @@ -2957,7 +2987,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, icl_init_cdclk(dev_priv); /* 6. Enable DBUF. */ - gen9_dbuf_enable(dev_priv); + icl_dbuf_enable(dev_priv); /* 7. Setup MBUS. */ /* FIXME: MBUS code not here yet. */ @@ -2977,7 +3007,7 @@ static void icl_display_core_uninit(struct drm_i915_private *dev_priv) /* 1. Disable all display engine functions -> aready done */ /* 2. Disable DBUF */ - gen9_dbuf_disable(dev_priv); + icl_dbuf_disable(dev_priv); /* 3. Disable CD clock */ icl_uninit_cdclk(dev_priv); From 4cb4585e5a7f780726ab18ab12b547d9331d4acd Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Mon, 5 Feb 2018 13:40:45 -0200 Subject: [PATCH 047/113] drm/i915/icl: initialize MBus during display init This patch initializes MBus during display initialization. Changes since V2 (from Paulo): - Don't forget to remove the WARN_ON(1) call. Changes since V1: - Rebase to use function like Macros Reviewed-by: Paulo Zanoni Reviewed-by: James Ausmus Signed-off-by: Mahesh Kumar Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180205154046.11485-6-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_runtime_pm.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 7e8694a70661..16790f2576ec 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2676,6 +2676,18 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv) DRM_ERROR("DBuf power disable timeout!\n"); } +static void icl_mbus_init(struct drm_i915_private *dev_priv) +{ + uint32_t val; + + val = MBUS_ABOX_BT_CREDIT_POOL1(16) | + MBUS_ABOX_BT_CREDIT_POOL2(16) | + MBUS_ABOX_B_CREDIT(1) | + MBUS_ABOX_BW_CREDIT(1); + + I915_WRITE(MBUS_ABOX_CTL, val); +} + static void skl_display_core_init(struct drm_i915_private *dev_priv, bool resume) { @@ -2990,7 +3002,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, icl_dbuf_enable(dev_priv); /* 7. Setup MBUS. */ - /* FIXME: MBUS code not here yet. */ + icl_mbus_init(dev_priv); /* 8. CHICKEN_DCPR_1 */ I915_WRITE(GEN8_CHICKEN_DCPR_1, I915_READ(GEN8_CHICKEN_DCPR_1) | From c3cc39c539d46be73ee032d2ff1b3f8fe44d4483 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Mon, 5 Feb 2018 15:21:31 -0200 Subject: [PATCH 048/113] drm/i915/icl: program mbus during pipe enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch program default values of MBus credit during pipe enable. Changes Since V1: - Add WARN_ON (Paulo) - Remove TODO comment - Program 0 during pipe disable - Rebase Changes since V2: - We don't need to do anything when disabling the pipe Changes since V3 (from Paulo): - Remove WARN() that we'll never be able to trigger (Ville). Cc: Ville Syrjälä Reviewed-by: Paulo Zanoni Reviewed-by: James Ausmus Signed-off-by: Mahesh Kumar Signed-off-by: Paulo Zanoni Link: https://patchwork.freedesktop.org/patch/msgid/20180205172131.20255-1-paulo.r.zanoni@intel.com --- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 94d03e2cd498..bedb40861360 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5418,6 +5418,20 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, I915_WRITE(CLKGATE_DIS_PSL(pipe), val); } +static void icl_pipe_mbus_enable(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; + uint32_t val; + + val = MBUS_DBOX_BW_CREDIT(1) | MBUS_DBOX_A_CREDIT(2); + + /* Program B credit equally to all pipes */ + val |= MBUS_DBOX_B_CREDIT(24 / INTEL_INFO(dev_priv)->num_pipes); + + I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val); +} + static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_atomic_state *old_state) { @@ -5495,6 +5509,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(old_intel_state, pipe_config); + if (INTEL_GEN(dev_priv) >= 11) + icl_pipe_mbus_enable(intel_crtc); + /* XXX: Do the pipe assertions at the right place for BXT DSI. */ if (!transcoder_is_dsi(cpu_transcoder)) intel_enable_pipe(pipe_config); From 015df4f54e2c3891859200bfc052895423bcce8b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 13 Feb 2018 12:09:40 +0000 Subject: [PATCH 049/113] drm/i915/selftests: Report setup errors for igt_partial_tiling igt_partial_tiling managed to fail with an -EBUSY. This usually means a pin leak, but that should be impossible given the test setup. Add a couple of error messages to help identify the path that failed. References: https://bugs.freedesktop.org/show_bug.cgi?id=105073 Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180213120940.21579-1-chris@chris-wilson.co.uk --- .../gpu/drm/i915/selftests/i915_gem_object.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index f32aa6bb79e2..3c64815e910b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -212,8 +212,11 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, return -EINTR; err = i915_gem_object_set_tiling(obj, tile->tiling, tile->stride); - if (err) + if (err) { + pr_err("Failed to set tiling mode=%u, stride=%u, err=%d\n", + tile->tiling, tile->stride, err); return err; + } GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); @@ -230,13 +233,16 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, GEM_BUG_ON(view.partial.size > nreal); err = i915_gem_object_set_to_gtt_domain(obj, true); - if (err) + if (err) { + pr_err("Failed to flush to GTT write domain; err=%d\n", + err); return err; + } vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); if (IS_ERR(vma)) { - pr_err("Failed to pin partial view: offset=%lu\n", - page); + pr_err("Failed to pin partial view: offset=%lu; err=%d\n", + page, (int)PTR_ERR(vma)); return PTR_ERR(vma); } @@ -246,8 +252,8 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, io = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); if (IS_ERR(io)) { - pr_err("Failed to iomap partial view: offset=%lu\n", - page); + pr_err("Failed to iomap partial view: offset=%lu; err=%d\n", + page, (int)PTR_ERR(io)); return PTR_ERR(io); } From da6c10c23a904d8ada1a9bf94ee26422f4cd4be0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 5 Feb 2018 19:31:36 +0200 Subject: [PATCH 050/113] drm/i915: abstract PCH type detection from PCH id Make the logic in intel_detect_pch() easier to follow, and make the PCH id to type mapping reusable. No functional changes. Reviewed-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/3bd4ffcd284cdbd4e8dc77ab02d97ded422e0c21.1517851783.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 148 ++++++++++++++++---------------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7bfc74c1aeb8..066c3406bbc9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -122,6 +122,75 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv) i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \ fmt, ##__VA_ARGS__) +/* Map PCH device id to PCH type, or PCH_NONE if unknown. */ +static enum intel_pch +intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) +{ + switch (id) { + case INTEL_PCH_IBX_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); + WARN_ON(!IS_GEN5(dev_priv)); + return PCH_IBX; + case INTEL_PCH_CPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found CougarPoint PCH\n"); + WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); + return PCH_CPT; + case INTEL_PCH_PPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found PantherPoint PCH\n"); + WARN_ON(!IS_GEN6(dev_priv) && !IS_IVYBRIDGE(dev_priv)); + /* PantherPoint is CPT compatible */ + return PCH_CPT; + case INTEL_PCH_LPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found LynxPoint PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + return PCH_LPT; + case INTEL_PCH_WPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found WildcatPoint PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); + /* WildcatPoint is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found WildcatPoint LP PCH\n"); + WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); + WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); + /* WildcatPoint is LPT compatible */ + return PCH_LPT; + case INTEL_PCH_SPT_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); + return PCH_SPT; + case INTEL_PCH_KBP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); + WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv) && + !IS_COFFEELAKE(dev_priv)); + return PCH_KBP; + case INTEL_PCH_CNP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); + WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n"); + WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); + return PCH_CNP; + case INTEL_PCH_ICP_DEVICE_ID_TYPE: + DRM_DEBUG_KMS("Found Ice Lake PCH\n"); + WARN_ON(!IS_ICELAKE(dev_priv)); + return PCH_ICP; + default: + return PCH_NONE; + } +} static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) { @@ -183,6 +252,7 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) */ while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { unsigned short id; + enum intel_pch pch_type; if (pch->vendor != PCI_VENDOR_ID_INTEL) continue; @@ -191,81 +261,9 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) dev_priv->pch_id = id; - if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_IBX; - DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); - WARN_ON(!IS_GEN5(dev_priv)); - } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_CPT; - DRM_DEBUG_KMS("Found CougarPoint PCH\n"); - WARN_ON(!IS_GEN6(dev_priv) && - !IS_IVYBRIDGE(dev_priv)); - } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { - /* PantherPoint is CPT compatible */ - dev_priv->pch_type = PCH_CPT; - DRM_DEBUG_KMS("Found PantherPoint PCH\n"); - WARN_ON(!IS_GEN6(dev_priv) && - !IS_IVYBRIDGE(dev_priv)); - } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found LynxPoint PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(IS_HSW_ULT(dev_priv) || - IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(!IS_HSW_ULT(dev_priv) && - !IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_WPT_DEVICE_ID_TYPE) { - /* WildcatPoint is LPT compatible */ - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found WildcatPoint PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(IS_HSW_ULT(dev_priv) || - IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) { - /* WildcatPoint is LPT compatible */ - dev_priv->pch_type = PCH_LPT; - DRM_DEBUG_KMS("Found WildcatPoint LP PCH\n"); - WARN_ON(!IS_HASWELL(dev_priv) && - !IS_BROADWELL(dev_priv)); - WARN_ON(!IS_HSW_ULT(dev_priv) && - !IS_BDW_ULT(dev_priv)); - } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_SPT; - DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); - WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv)); - } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_SPT; - DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); - WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv)); - } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_KBP; - DRM_DEBUG_KMS("Found Kaby Lake PCH (KBP)\n"); - WARN_ON(!IS_SKYLAKE(dev_priv) && - !IS_KABYLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_CNP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found Cannon Lake PCH (CNP)\n"); - WARN_ON(!IS_CANNONLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_CNP; - DRM_DEBUG_KMS("Found Cannon Lake LP PCH (CNP-LP)\n"); - WARN_ON(!IS_CANNONLAKE(dev_priv) && - !IS_COFFEELAKE(dev_priv)); - } else if (id == INTEL_PCH_ICP_DEVICE_ID_TYPE) { - dev_priv->pch_type = PCH_ICP; - DRM_DEBUG_KMS("Found Ice Lake PCH\n"); - WARN_ON(!IS_ICELAKE(dev_priv)); + pch_type = intel_pch_type(dev_priv, id); + if (pch_type != PCH_NONE) { + dev_priv->pch_type = pch_type; } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || id == INTEL_PCH_P3X_DEVICE_ID_TYPE || (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && From 435ad2c009429157cb65ce8a6221038235cc0501 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 5 Feb 2018 19:31:37 +0200 Subject: [PATCH 051/113] drm/i915: abstract virtual PCH id detection Make the code slightly more pleasant to look at. No functional changes. Reviewed-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/38ee1ac06c6724e888679eb287af36c221bd399b.1517851783.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 066c3406bbc9..786486a53dce 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -192,6 +192,16 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) } } +static bool intel_is_virt_pch(unsigned short id, + unsigned short svendor, unsigned short sdevice) +{ + return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || + id == INTEL_PCH_P3X_DEVICE_ID_TYPE || + (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && + svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && + sdevice == PCI_SUBDEVICE_ID_QEMU)); +} + static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) { enum intel_pch ret = PCH_NOP; @@ -264,13 +274,8 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) pch_type = intel_pch_type(dev_priv, id); if (pch_type != PCH_NONE) { dev_priv->pch_type = pch_type; - } else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || - id == INTEL_PCH_P3X_DEVICE_ID_TYPE || - (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && - pch->subsystem_vendor == - PCI_SUBVENDOR_ID_REDHAT_QUMRANET && - pch->subsystem_device == - PCI_SUBDEVICE_ID_QEMU)) { + } else if (intel_is_virt_pch(id, pch->subsystem_vendor, + pch->subsystem_device)) { dev_priv->pch_type = intel_virt_detect_pch(dev_priv); } else { continue; From 40ace64b1ece1b8a29f86e6e2bc6fb91f7f0e537 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 5 Feb 2018 19:31:38 +0200 Subject: [PATCH 052/113] drm/i915: have virtual PCH detection return a PCH id Simplify intel_virt_detect_pch() by making it return a PCH id rather than returning the PCH type and setting PCH id for some PCHs. Map the PCH id to PCH type using the shared routine. This gives us sanity check on the supported combinations also in the virtualized setting. Reviewed-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/197cf635261a1c628371ffaaee90e8647493af4d.1517851783.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 66 +++++++++++++++++---------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 786486a53dce..9380c9f69b0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -202,9 +202,10 @@ static bool intel_is_virt_pch(unsigned short id, sdevice == PCI_SUBDEVICE_ID_QEMU)); } -static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) +static unsigned short +intel_virt_detect_pch(const struct drm_i915_private *dev_priv) { - enum intel_pch ret = PCH_NOP; + unsigned short id = 0; /* * In a virtualized passthrough environment we can be in a @@ -213,28 +214,25 @@ static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) * make an educated guess as to which PCH is really there. */ - if (IS_GEN5(dev_priv)) { - ret = PCH_IBX; - DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); - } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { - ret = PCH_CPT; - DRM_DEBUG_KMS("Assuming CougarPoint PCH\n"); - } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { - ret = PCH_LPT; - if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) - dev_priv->pch_id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; - else - dev_priv->pch_id = INTEL_PCH_LPT_DEVICE_ID_TYPE; - DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); - } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { - ret = PCH_SPT; - DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); - } else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { - ret = PCH_CNP; - DRM_DEBUG_KMS("Assuming CannonPoint PCH\n"); - } + if (IS_GEN5(dev_priv)) + id = INTEL_PCH_IBX_DEVICE_ID_TYPE; + else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) + id = INTEL_PCH_CPT_DEVICE_ID_TYPE; + else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) + id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; + else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) + id = INTEL_PCH_LPT_DEVICE_ID_TYPE; + else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + id = INTEL_PCH_SPT_DEVICE_ID_TYPE; + else if (IS_COFFEELAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) + id = INTEL_PCH_CNP_DEVICE_ID_TYPE; - return ret; + if (id) + DRM_DEBUG_KMS("Assuming PCH ID %04x\n", id); + else + DRM_DEBUG_KMS("Assuming no PCH\n"); + + return id; } static void intel_detect_pch(struct drm_i915_private *dev_priv) @@ -269,19 +267,25 @@ static void intel_detect_pch(struct drm_i915_private *dev_priv) id = pch->device & INTEL_PCH_DEVICE_ID_MASK; - dev_priv->pch_id = id; - pch_type = intel_pch_type(dev_priv, id); if (pch_type != PCH_NONE) { dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; } else if (intel_is_virt_pch(id, pch->subsystem_vendor, - pch->subsystem_device)) { - dev_priv->pch_type = intel_virt_detect_pch(dev_priv); - } else { - continue; + pch->subsystem_device)) { + id = intel_virt_detect_pch(dev_priv); + if (id) { + pch_type = intel_pch_type(dev_priv, id); + if (WARN_ON(pch_type == PCH_NONE)) + pch_type = PCH_NOP; + } else { + pch_type = PCH_NOP; + } + dev_priv->pch_type = pch_type; + dev_priv->pch_id = id; + break; } - - break; } if (!pch) DRM_DEBUG_KMS("No PCH found.\n"); From 817175040e7f92daac22b1b537ae09148e24de28 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 5 Feb 2018 19:31:39 +0200 Subject: [PATCH 053/113] drm/i915: introduce INTEL_PCH_ID() and use it Cleanup similar to INTEL_PCH_TYPE(). No functional changes. Reviewed-by: Rodrigo Vivi Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/798893c24728a1c766cb21c57ae0943e5859c897.1517851783.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a3a02acfc345..0bb8ad23efa7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2864,19 +2864,20 @@ intel_info(const struct drm_i915_private *dev_priv) #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ #define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) +#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id) #define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP) #define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP) #define HAS_PCH_CNP_LP(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_CNP_LP_DEVICE_ID_TYPE) #define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP) #define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) #define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) #define HAS_PCH_LPT_LP(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ - (dev_priv)->pch_id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE) #define HAS_PCH_LPT_H(dev_priv) \ - ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ - (dev_priv)->pch_id == INTEL_PCH_WPT_DEVICE_ID_TYPE) + (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \ + INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_DEVICE_ID_TYPE) #define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) #define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) From 62b5ed1f35d7f6f140cc9de818991df4f11adc69 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 13 Feb 2018 14:18:33 +0000 Subject: [PATCH 054/113] drm/i915: Fix i915_gem_context.h header Header uses I915_NUM_ENGINES so needs to include i915.gem.h, and also it uses requests so we can forward declare struct drm_i915_gem_request. Signed-off-by: Tvrtko Ursulin Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180213141833.17012-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_gem_context.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 4bfb72f8e1cb..a681c5b891ff 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -29,6 +29,8 @@ #include #include +#include "i915_gem.h" + struct pid; struct drm_device; @@ -36,6 +38,7 @@ struct drm_file; struct drm_i915_private; struct drm_i915_file_private; +struct drm_i915_gem_request; struct i915_hw_ppgtt; struct i915_vma; struct intel_ring; From 817cc07918232e0c3b4cf2926c1a08c8d08edc33 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 8 Feb 2018 16:00:36 +0000 Subject: [PATCH 055/113] drm/i915: Handle RC6 counter wrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can implement limited RC6 counter wrap-around protection under the assumption that clients will be reading this value more frequently than the wrap period on a given platform. With the typical wrap-around period being ~90 minutes, even with the exception of Baytrail which wraps every 13 seconds, this sounds like a reasonable assumption. Implementation works by storing a 64-bit software copy of a hardware RC6 counter, along with the previous HW counter snapshot. This enables it to detect wrap is polled frequently enough and keep the software copy monotonically incrementing. v2: * Missed GEN6_GT_GFX_RC6_LOCKED when considering slot sizing and indexing. * Fixed off-by-one in wrap-around handling. (Chris Wilson) v3: * Simplify index checking by using unsigned int. (Chris Wilson) * Expand the comment to explain why indexing works. v4: * Use __int128 if supported. v5: * Use mul_u64_u32_div. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94852 Cc: Chris Wilson Reviewed-by: Chris Wilson # v3 Cc: Ville Syrjälä Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180208160036.29919-1-tvrtko.ursulin@linux.intel.com Acked-by: Ville Syrjälä --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 64 +++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0bb8ad23efa7..ffbe397c2ade 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -947,6 +947,8 @@ struct intel_rps { struct intel_rc6 { bool enabled; + u64 prev_hw_residency[4]; + u64 cur_residency[4]; }; struct intel_llc_pstate { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b026b020d8b8..7e15b261821d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9420,15 +9420,16 @@ 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 + /* + * The register accessed do not need forcewake. We borrow * uncore lock to prevent concurrent access to range reg. */ - spin_lock_irqsave(&dev_priv->uncore.lock, flags); + lockdep_assert_held(&dev_priv->uncore.lock); - /* vlv and chv residency counters are 40 bits in width. + /* + * vlv and chv residency counters are 40 bits in width. * With a control bit, we can choose between upper or lower * 32bit window into this counter. * @@ -9452,29 +9453,49 @@ static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, upper = I915_READ_FW(reg); } while (upper != tmp && --loop); - /* Everywhere else we always use VLV_COUNTER_CONTROL with the + /* + * Everywhere else we always use VLV_COUNTER_CONTROL with the * VLV_COUNT_RANGE_HIGH bit set - so it is safe to leave it set * now. */ - spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); - return lower | (u64)upper << 8; } u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, const i915_reg_t reg) { - u64 time_hw; + u64 time_hw, prev_hw, overflow_hw; + unsigned int fw_domains; + unsigned long flags; + unsigned int i; u32 mul, div; if (!HAS_RC6(dev_priv)) return 0; + /* + * Store previous hw counter values for counter wrap-around handling. + * + * There are only four interesting registers and they live next to each + * other so we can use the relative address, compared to the smallest + * one as the index into driver storage. + */ + i = (i915_mmio_reg_offset(reg) - + i915_mmio_reg_offset(GEN6_GT_GFX_RC6_LOCKED)) / sizeof(u32); + if (WARN_ON_ONCE(i >= ARRAY_SIZE(dev_priv->gt_pm.rc6.cur_residency))) + return 0; + + fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, FW_REG_READ); + + spin_lock_irqsave(&dev_priv->uncore.lock, flags); + intel_uncore_forcewake_get__locked(dev_priv, fw_domains); + /* On VLV and CHV, residency time is in CZ units rather than 1.28us */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { mul = 1000000; div = dev_priv->czclk_freq; + overflow_hw = BIT_ULL(40); time_hw = vlv_residency_raw(dev_priv, reg); } else { /* 833.33ns units on Gen9LP, 1.28us elsewhere. */ @@ -9486,10 +9507,33 @@ u64 intel_rc6_residency_ns(struct drm_i915_private *dev_priv, div = 1; } - time_hw = I915_READ(reg); + overflow_hw = BIT_ULL(32); + time_hw = I915_READ_FW(reg); } - return DIV_ROUND_UP_ULL(time_hw * mul, div); + /* + * Counter wrap handling. + * + * But relying on a sufficient frequency of queries otherwise counters + * can still wrap. + */ + prev_hw = dev_priv->gt_pm.rc6.prev_hw_residency[i]; + dev_priv->gt_pm.rc6.prev_hw_residency[i] = time_hw; + + /* RC6 delta from last sample. */ + if (time_hw >= prev_hw) + time_hw -= prev_hw; + else + time_hw += overflow_hw - prev_hw; + + /* Add delta to RC6 extended raw driver copy. */ + time_hw += dev_priv->gt_pm.rc6.cur_residency[i]; + dev_priv->gt_pm.rc6.cur_residency[i] = time_hw; + + intel_uncore_forcewake_put__locked(dev_priv, fw_domains); + spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); + + return mul_u64_u32_div(time_hw, mul, div); } u32 intel_get_cagf(struct drm_i915_private *dev_priv, u32 rpstat) From 5270d9c367a1a5673c5afb7ef77c6ec25ff2b958 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 14 Feb 2018 11:38:27 +0200 Subject: [PATCH 056/113] drm/i915: Update DRIVER_DATE to 20180214 Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ffbe397c2ade..8bd55b568c01 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -83,8 +83,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20180207" -#define DRIVER_TIMESTAMP 1517988364 +#define DRIVER_DATE "20180214" +#define DRIVER_TIMESTAMP 1518601107 /* 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 From 785f076b3ba781804f2b22b347b4431e3efb0ab3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 Feb 2018 09:21:49 +0100 Subject: [PATCH 057/113] drm/i915: Add intel_bios_cleanup() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an intel_bios_cleanup() function to act as counterpart of intel_bios_init() and move the cleanup of vbt related resources there, putting it in the same file as the allocation. Changed in v2: -While touching the code anyways, remove the unnecessary: if (dev_priv->vbt.child_dev) done before kfree(dev_priv->vbt.child_dev) Reviewed-by: Ville Syrjälä Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-1-hdegoede@redhat.com --- drivers/gpu/drm/i915/i915_drv.c | 14 +------------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 9380c9f69b0f..a9931b8ec0b3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1448,19 +1448,7 @@ void i915_driver_unload(struct drm_device *dev) intel_modeset_cleanup(dev); - /* - * free the memory space allocated for the child device - * config parsed from VBT - */ - if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) { - kfree(dev_priv->vbt.child_dev); - dev_priv->vbt.child_dev = NULL; - dev_priv->vbt.child_dev_num = 0; - } - kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); - dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; - kfree(dev_priv->vbt.lfp_lvds_vbt_mode); - dev_priv->vbt.lfp_lvds_vbt_mode = NULL; + intel_bios_cleanup(dev_priv); vga_switcheroo_unregister_client(pdev); vga_client_register(pdev, NULL, NULL, NULL); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8bd55b568c01..0c0a4024d457 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3679,6 +3679,7 @@ extern void intel_i2c_reset(struct drm_i915_private *dev_priv); /* intel_bios.c */ void intel_bios_init(struct drm_i915_private *dev_priv); +void intel_bios_cleanup(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index aa4df6548771..ea1ed84a1e7d 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1610,6 +1610,21 @@ out: pci_unmap_rom(pdev, bios); } +/** + * intel_bios_cleanup - Free any resources allocated by intel_bios_init() + * @dev_priv: i915 device instance + */ +void intel_bios_cleanup(struct drm_i915_private *dev_priv) +{ + kfree(dev_priv->vbt.child_dev); + dev_priv->vbt.child_dev = NULL; + dev_priv->vbt.child_dev_num = 0; + kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); + dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; + kfree(dev_priv->vbt.lfp_lvds_vbt_mode); + dev_priv->vbt.lfp_lvds_vbt_mode = NULL; +} + /** * intel_bios_is_tv_present - is integrated TV present in VBT * @dev_priv: i915 device instance From e1b86c85f6c2029c31dba99823b6f3d9e15eaacd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 Feb 2018 09:21:50 +0100 Subject: [PATCH 058/113] drm/i915: Free memdup-ed DSI VBT data structures on driver_unload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make intel_bios_cleanup function free the DSI VBT data structures which are memdup-ed by parse_mipi_config() and parse_mipi_sequence(). Reviewed-by: Ville Syrjälä Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-2-hdegoede@redhat.com --- drivers/gpu/drm/i915/intel_bios.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index ea1ed84a1e7d..92e52bb65c41 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1623,6 +1623,12 @@ void intel_bios_cleanup(struct drm_i915_private *dev_priv) dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; kfree(dev_priv->vbt.lfp_lvds_vbt_mode); dev_priv->vbt.lfp_lvds_vbt_mode = NULL; + kfree(dev_priv->vbt.dsi.data); + dev_priv->vbt.dsi.data = NULL; + kfree(dev_priv->vbt.dsi.pps); + dev_priv->vbt.dsi.pps = NULL; + kfree(dev_priv->vbt.dsi.config); + dev_priv->vbt.dsi.config = NULL; } /** From fb38e7ade9af4f3e96f5916c3f6f19bfc7d5f961 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 14 Feb 2018 09:21:51 +0100 Subject: [PATCH 059/113] drm/i915: Fix DSI panels with v1 MIPI sequences without a DEASSERT sequence v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far models of the Dell Venue 8 Pro, with a panel with MIPI panel index = 3, one of which has been kindly provided to me by Jan Brummer, where not working with the i915 driver, giving a black screen on the first modeset. The problem with at least these Dells is that their VBT defines a MIPI ASSERT sequence, but not a DEASSERT sequence. Instead they DEASSERT the reset in their INIT_OTP sequence, but the deassert must be done before calling intel_dsi_device_ready(), so that is too late. Simply doing the INIT_OTP sequence earlier is not enough to fix this, because the INIT_OTP sequence also sends various MIPI packets to the panel, which can only happen after calling intel_dsi_device_ready(). This commit fixes this by splitting the INIT_OTP sequence into everything before the first DSI packet and everything else, including the first DSI packet. The first part (everything before the first DSI packet) is then used as deassert sequence. Changed in v2: -Split the init OTP sequence into a deassert reset and the actual init OTP sequence, instead of calling it earlier and then having the first mipi_exec_send_packet() call call intel_dsi_device_ready(). Changes in v3: -Move the whole shebang to intel_bios.c Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=82880 References: https://bugs.freedesktop.org/show_bug.cgi?id=101205 Cc: Jan-Michael Brummer Reported-by: Jan-Michael Brummer Tested-by: Hans de Goede Reviewed-by: Ville Syrjälä Acked-by: Jani Nikula Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20180214082151.25015-3-hdegoede@redhat.com --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 84 +++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0c0a4024d457..822f50e472b6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1359,6 +1359,7 @@ struct intel_vbt_data { u32 size; u8 *data; const u8 *sequence[MIPI_SEQ_MAX]; + u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ } dsi; int crt_ddc_pin; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 92e52bb65c41..c5c7530ba157 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -947,6 +947,86 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) return 0; } +/* + * Get len of pre-fixed deassert fragment from a v1 init OTP sequence, + * skip all delay + gpio operands and stop at the first DSI packet op. + */ +static int get_init_otp_deassert_fragment_len(struct drm_i915_private *dev_priv) +{ + const u8 *data = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + int index, len; + + if (WARN_ON(!data || dev_priv->vbt.dsi.seq_version != 1)) + return 0; + + /* index = 1 to skip sequence byte */ + for (index = 1; data[index] != MIPI_SEQ_ELEM_END; index += len) { + switch (data[index]) { + case MIPI_SEQ_ELEM_SEND_PKT: + return index == 1 ? 0 : index; + case MIPI_SEQ_ELEM_DELAY: + len = 5; /* 1 byte for operand + uint32 */ + break; + case MIPI_SEQ_ELEM_GPIO: + len = 3; /* 1 byte for op, 1 for gpio_nr, 1 for value */ + break; + default: + return 0; + } + } + + return 0; +} + +/* + * Some v1 VBT MIPI sequences do the deassert in the init OTP sequence. + * The deassert must be done before calling intel_dsi_device_ready, so for + * these devices we split the init OTP sequence into a deassert sequence and + * the actual init OTP part. + */ +static void fixup_mipi_sequences(struct drm_i915_private *dev_priv) +{ + u8 *init_otp; + int len; + + /* Limit this to VLV for now. */ + if (!IS_VALLEYVIEW(dev_priv)) + return; + + /* Limit this to v1 vid-mode sequences */ + if (dev_priv->vbt.dsi.config->is_cmd_mode || + dev_priv->vbt.dsi.seq_version != 1) + return; + + /* Only do this if there are otp and assert seqs and no deassert seq */ + if (!dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] || + !dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] || + dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) + return; + + /* The deassert-sequence ends at the first DSI packet */ + len = get_init_otp_deassert_fragment_len(dev_priv); + if (!len) + return; + + DRM_DEBUG_KMS("Using init OTP fragment to deassert reset\n"); + + /* Copy the fragment, update seq byte and terminate it */ + init_otp = (u8 *)dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; + dev_priv->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL); + if (!dev_priv->vbt.dsi.deassert_seq) + return; + dev_priv->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET; + dev_priv->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END; + /* Use the copy for deassert */ + dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] = + dev_priv->vbt.dsi.deassert_seq; + /* Replace the last byte of the fragment with init OTP seq byte */ + init_otp[len - 1] = MIPI_SEQ_INIT_OTP; + /* And make MIPI_MIPI_SEQ_INIT_OTP point to it */ + dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1; +} + static void parse_mipi_sequence(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -1016,6 +1096,8 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, dev_priv->vbt.dsi.size = seq_size; dev_priv->vbt.dsi.seq_version = sequence->version; + fixup_mipi_sequences(dev_priv); + DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); return; @@ -1629,6 +1711,8 @@ void intel_bios_cleanup(struct drm_i915_private *dev_priv) dev_priv->vbt.dsi.pps = NULL; kfree(dev_priv->vbt.dsi.config); dev_priv->vbt.dsi.config = NULL; + kfree(dev_priv->vbt.dsi.deassert_seq); + dev_priv->vbt.dsi.deassert_seq = NULL; } /** From 3930f18a09c815066aaa6075106ad039eaac5043 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 08:58:14 +0000 Subject: [PATCH 060/113] drm/i915/tv: Cleanup up obsolete comments The ages old kerneldoc-esque comments still refer to the original stubs and not the more complete functions. As they were only describing the external entry points (or at least thought themselves to be, they had drifted!), they don't provide any commentary for the code flow. drivers/gpu/drm/i915/intel_tv.c:379: warning: cannot understand function prototype: 'const struct tv_mode tv_modes[] = ' drivers/gpu/drm/i915/intel_tv.c:1133: warning: bad line: drivers/gpu/drm/i915/intel_tv.c:1140: warning: Function parameter or member 'intel_tv' not described in 'intel_tv_detect_type' drivers/gpu/drm/i915/intel_tv.c:1140: warning: Function parameter or member 'connector' not described in 'intel_tv_detect_type' drivers/gpu/drm/i915/intel_tv.c:1272: warning: Function parameter or member 'connector' not described in 'intel_tv_detect' drivers/gpu/drm/i915/intel_tv.c:1272: warning: Function parameter or member 'ctx' not described in 'intel_tv_detect' drivers/gpu/drm/i915/intel_tv.c:1272: warning: Function parameter or member 'force' not described in 'intel_tv_detect' drivers/gpu/drm/i915/intel_tv.c:1351: warning: Function parameter or member 'connector' not described in 'intel_tv_get_modes' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214085814.2565-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_tv.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index b3dabc219e6a..885fc3809f7f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -43,7 +43,6 @@ enum tv_margin { TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM }; -/** Private structure for the integrated TV support */ struct intel_tv { struct intel_encoder base; @@ -370,12 +369,11 @@ struct tv_mode { * The constants below were all computed using a 107.520MHz clock */ -/** +/* * Register programming values for TV modes. * * These values account for -1s required. */ - static const struct tv_mode tv_modes[] = { { .name = "NTSC-M", @@ -1126,14 +1124,6 @@ static const struct drm_display_mode reported_modes[] = { }, }; -/** - * Detects TV presence by checking for load. - * - * Requires that the current pipe's DPLL is active. - - * \return true if TV is connected. - * \return false if TV is disconnected. - */ static int intel_tv_detect_type(struct intel_tv *intel_tv, struct drm_connector *connector) @@ -1259,12 +1249,6 @@ static void intel_tv_find_better_format(struct drm_connector *connector) connector->state->tv.mode = i; } -/** - * Detect the TV connection. - * - * Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure - * we have a pipe programmed in order to probe the TV. - */ static int intel_tv_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, @@ -1339,13 +1323,6 @@ intel_tv_choose_preferred_modes(const struct tv_mode *tv_mode, } } -/** - * Stub get_modes function. - * - * This should probably return a set of fixed modes, unless we can figure out - * how to probe modes off of TV connections. - */ - static int intel_tv_get_modes(struct drm_connector *connector) { @@ -1512,7 +1489,8 @@ intel_tv_init(struct drm_i915_private *dev_priv) connector = &intel_connector->base; state = connector->state; - /* The documentation, for the older chipsets at least, recommend + /* + * The documentation, for the older chipsets at least, recommend * using a polling method rather than hotplug detection for TVs. * This is because in order to perform the hotplug detection, the PLLs * for the TV must be kept alive increasing power drain and starving From c16336b95c615fa84560a2e9786df71c0c55677b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:09:05 +0000 Subject: [PATCH 061/113] drm/i915/sdvo: Tidy up commentary Drop the kerneldoc markup from the non-kerneldoc comments and convert the multi-line comments to the canonical format. drivers/gpu/drm/i915/intel_sdvo.c:223: warning: Function parameter or member 'intel_sdvo' not described in 'intel_sdvo_write_sdvox' drivers/gpu/drm/i915/intel_sdvo.c:223: warning: Function parameter or member 'val' not described in 'intel_sdvo_write_sdvox' drivers/gpu/drm/i915/intel_sdvo.c:653: warning: Function parameter or member 'intel_sdvo' not described in 'intel_sdvo_get_trained_inputs' drivers/gpu/drm/i915/intel_sdvo.c:653: warning: Function parameter or member 'input_1' not described in 'intel_sdvo_get_trained_inputs' drivers/gpu/drm/i915/intel_sdvo.c:653: warning: Function parameter or member 'input_2' not described in 'intel_sdvo_get_trained_inputs' drivers/gpu/drm/i915/intel_sdvo.c:2311: warning: Function parameter or member 'dev_priv' not described in 'intel_sdvo_select_ddc_bus' drivers/gpu/drm/i915/intel_sdvo.c:2311: warning: Function parameter or member 'sdvo' not described in 'intel_sdvo_select_ddc_bus' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214090905.4747-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_sdvo.c | 82 ++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 2b8764897d68..f4e49b24d18c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -214,7 +214,7 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector); -/** +/* * Writes the SDVOB or SDVOC with the given value, but always writes both * SDVOB and SDVOC to work around apparent hardware issues (according to * comments in the BIOS). @@ -250,10 +250,10 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) * writing them only once doesn't appear to 'stick'. * The BIOS does this too. Yay, magic */ - for (i = 0; i < 2; i++) - { + for (i = 0; i < 2; i++) { I915_WRITE(GEN3_SDVOB, bval); POSTING_READ(GEN3_SDVOB); + I915_WRITE(GEN3_SDVOC, cval); POSTING_READ(GEN3_SDVOC); } @@ -643,7 +643,7 @@ static bool intel_sdvo_set_target_input(struct intel_sdvo *intel_sdvo) &targets, sizeof(targets)); } -/** +/* * Return whether each input is trained. * * This function is making an assumption about the layout of the response, @@ -1061,8 +1061,10 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, return true; } -/* Asks the sdvo controller for the preferred input mode given the output mode. - * Unfortunately we have to set up the full output mode to do that. */ +/* + * Asks the sdvo controller for the preferred input mode given the output mode. + * Unfortunately we have to set up the full output mode to do that. + */ static bool intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, const struct drm_display_mode *mode, @@ -1095,8 +1097,10 @@ static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_state *pipe_config) unsigned dotclock = pipe_config->port_clock; struct dpll *clock = &pipe_config->dpll; - /* SDVO TV has fixed PLL values depend on its clock range, - this mirrors vbios setting. */ + /* + * SDVO TV has fixed PLL values depend on its clock range, + * this mirrors vbios setting. + */ if (dotclock >= 100000 && dotclock < 140500) { clock->p1 = 2; clock->p2 = 10; @@ -1132,7 +1136,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) pipe_config->has_pch_encoder = true; - /* We need to construct preferred input timings based on our + /* + * We need to construct preferred input timings based on our * output timings. To do that, we have to set the output * timings, even though this isn't really the right place in * the sequence to do it. Oh well. @@ -1155,7 +1160,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, adjusted_mode); } - /* Make the CRTC code factor in the SDVO pixel multiplier. The + /* + * Make the CRTC code factor in the SDVO pixel multiplier. The * SDVO device will factor out the multiplier during mode_set. */ pipe_config->pixel_multiplier = @@ -1169,9 +1175,12 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, pipe_config->has_audio = true; if (intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) { - /* See CEA-861-E - 5.1 Default Encoding Parameters */ - /* FIXME: This bit is only valid when using TMDS encoding and 8 - * bit per color mode. */ + /* + * See CEA-861-E - 5.1 Default Encoding Parameters + * + * FIXME: This bit is only valid when using TMDS encoding and 8 + * bit per color mode. + */ if (pipe_config->has_hdmi_sink && drm_match_cea_mode(adjusted_mode) > 1) pipe_config->limited_color_range = true; @@ -1272,7 +1281,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, intel_sdvo_update_props(intel_sdvo, sdvo_state); - /* First, set the input mapping for the first input to our controlled + /* + * First, set the input mapping for the first input to our controlled * output. This is only correct if we're a single-input device, in * which case the first input is the output from the appropriate SDVO * channel on the motherboard. In a two-input device, the first input @@ -1435,8 +1445,10 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); if (!ret) { - /* Some sdvo encoders are not spec compliant and don't - * implement the mandatory get_timings function. */ + /* + * Some sdvo encoders are not spec compliant and don't + * implement the mandatory get_timings function. + */ DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n"); pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS; } else { @@ -1585,7 +1597,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder, intel_wait_for_vblank(dev_priv, intel_crtc->pipe); success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2); - /* Warn if the device reported failure to sync. + /* + * Warn if the device reported failure to sync. + * * A lot of SDVO devices fail to notify of sync, but it's * a given it the status is a success, we succeeded. */ @@ -1675,8 +1689,10 @@ static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) if (!I915_HAS_HOTPLUG(dev_priv)) return 0; - /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise - * on the line. */ + /* + * HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise + * on the line. + */ if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) return 0; @@ -1960,7 +1976,8 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - /* Read the list of supported input resolutions for the selected TV + /* + * Read the list of supported input resolutions for the selected TV * format. */ format_map = 1 << conn_state->tv.mode; @@ -2271,7 +2288,8 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) uint16_t mask = 0; unsigned int num_bits; - /* Make a mask of outputs less than or equal to our own priority in the + /* + * Make a mask of outputs less than or equal to our own priority in the * list. */ switch (sdvo->controlled_output) { @@ -2301,7 +2319,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) sdvo->ddc_bus = 1 << num_bits; } -/** +/* * Choose the appropriate DDC bus for control bus switch command for this * SDVO output based on the controlled output. * @@ -2345,9 +2363,11 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin); - /* With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow + /* + * With gmbus we should be able to drive sdvo i2c at 2MHz, but somehow * our code totally fails once we start using gmbus. Hence fall back to - * bit banging for now. */ + * bit banging for now. + */ intel_gmbus_force_bit(sdvo->i2c, true); } @@ -2382,7 +2402,8 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv, if (my_mapping->slave_addr) return my_mapping->slave_addr; - /* If the BIOS only described a different SDVO device, use the + /* + * If the BIOS only described a different SDVO device, use the * address that it isn't using. */ if (other_mapping->slave_addr) { @@ -2392,7 +2413,8 @@ intel_sdvo_get_slave_addr(struct drm_i915_private *dev_priv, return 0x70; } - /* No SDVO device info is found for another DVO port, + /* + * No SDVO device info is found for another DVO port, * so use mapping assumption we had before BIOS parsing. */ if (sdvo->port == PORT_B) @@ -2493,7 +2515,8 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) if (intel_sdvo_get_hotplug_support(intel_sdvo) & intel_sdvo_connector->output_flag) { intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag; - /* Some SDVO devices have one-shot hotplug interrupts. + /* + * Some SDVO devices have one-shot hotplug interrupts. * Ensure that they get re-enabled when an interrupt happens. */ intel_encoder->hot_plug = intel_sdvo_enable_hotplug; @@ -2792,7 +2815,7 @@ intel_sdvo_create_enhance_property_tv(struct intel_sdvo *intel_sdvo, to_intel_sdvo_connector_state(conn_state); uint16_t response, data_value[2]; - /* when horizontal overscan is supported, Add the left/right property */ + /* when horizontal overscan is supported, Add the left/right property */ if (enhancements.overscan_h) { if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_MAX_OVERSCAN_H, @@ -3077,7 +3100,8 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv, goto err_output; } - /* Only enable the hotplug irq if we need it, to work around noisy + /* + * Only enable the hotplug irq if we need it, to work around noisy * hotplug lines. */ if (intel_sdvo->hotplug_active) { From e9a744fa60f7d87fc108012005ca6811686f9e17 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:17:46 +0000 Subject: [PATCH 062/113] drm/i915/panel: Add missing parameters to kerneldoc drivers/gpu/drm/i915/intel_panel.c:409: warning: Function parameter or member 'source_min' not described in 'scale' drivers/gpu/drm/i915/intel_panel.c:409: warning: Function parameter or member 'source_max' not described in 'scale' drivers/gpu/drm/i915/intel_panel.c:409: warning: Function parameter or member 'target_min' not described in 'scale' drivers/gpu/drm/i915/intel_panel.c:409: warning: Function parameter or member 'target_max' not described in 'scale' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214091747.12753-1-chris@chris-wilson.co.uk Link: https://patchwork.freedesktop.org/patch/msgid/20180214091747.12753-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_panel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 78a53c8b1789..41296935ef11 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -397,8 +397,11 @@ intel_panel_detect(struct drm_i915_private *dev_priv) /** * scale - scale values from one range to another - * * @source_val: value in range [@source_min..@source_max] + * @source_min: minimum legal value for @source_val + * @source_max: maximum legal value for @source_val + * @target_min: corresponding target value for @source_min + * @target_max: corresponding target value for @source_max * * Return @source_val in range [@source_min..@source_max] scaled to range * [@target_min..@target_max]. From 5af4ce7d81a5945ad11ca04a68e7f1febd67d59f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:17:47 +0000 Subject: [PATCH 063/113] drm/i915/panel: Split range scaling calculation for readiblity Split the 64b multiplication from the division so that it doesn't sprawl across a couple of lines and use mul_u32_u32() instead of open-coding the 64b conversion. Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214091747.12753-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_panel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 41296935ef11..41d00b1603e3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -419,8 +419,9 @@ static uint32_t scale(uint32_t source_val, source_val = clamp(source_val, source_min, source_max); /* avoid overflows */ - target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) * - (target_max - target_min), source_max - source_min); + target_val = mul_u32_u32(source_val - source_min, + target_max - target_min); + target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min); target_val += target_min; return target_val; From 537225299f20301e58c3f0831453f9d9d25d9091 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:29:06 +0000 Subject: [PATCH 064/113] drm/i915/crt: Remove obsolete kerneldoc-esque comment The code describes what it is doing quite well; and that is now much more complex than what the old comment would let you believe. drivers/gpu/drm/i915/intel_crt.c:486: warning: Function parameter or member 'connector' not described in 'intel_crt_detect_hotplug' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214092909.27040-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_crt.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index ae55afcbdc2c..644853307f24 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -477,14 +477,6 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) return ret; } -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. - * - * Not for i915G/i915GM - * - * \return true if CRT is connected. - * \return false if CRT is disconnected. - */ static bool intel_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; From 5a3ec1e6bf4b01b826a9de4136fbb9443ace9f0d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:29:07 +0000 Subject: [PATCH 065/113] drm/i915/dvo: Remove incorrect kerneldoc markups Regular comments where being marked up for kerneldoc, but were not formatted properly. Remove the markup to remove the warnings. drivers/gpu/drm/i915/dvo_ivch.c:192: warning: Function parameter or member 'dvo' not described in 'ivch_read' drivers/gpu/drm/i915/dvo_ivch.c:192: warning: Function parameter or member 'addr' not described in 'ivch_read' drivers/gpu/drm/i915/dvo_ivch.c:192: warning: Function parameter or member 'data' not described in 'ivch_read' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214092909.27040-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/dvo_ivch.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 4950b82f5b49..c73aff163908 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c @@ -59,28 +59,28 @@ * This must not be set while VR01_DVO_BYPASS_ENABLE is set. */ # define VR01_LCD_ENABLE (1 << 2) -/** Enables the DVO repeater. */ +/* Enables the DVO repeater. */ # define VR01_DVO_BYPASS_ENABLE (1 << 1) -/** Enables the DVO clock */ +/* Enables the DVO clock */ # define VR01_DVO_ENABLE (1 << 0) -/** Enable dithering for 18bpp panels. Not documented. */ +/* Enable dithering for 18bpp panels. Not documented. */ # define VR01_DITHER_ENABLE (1 << 4) /* * LCD Interface Format */ #define VR10 0x10 -/** Enables LVDS output instead of CMOS */ +/* Enables LVDS output instead of CMOS */ # define VR10_LVDS_ENABLE (1 << 4) -/** Enables 18-bit LVDS output. */ +/* Enables 18-bit LVDS output. */ # define VR10_INTERFACE_1X18 (0 << 2) -/** Enables 24-bit LVDS or CMOS output */ +/* Enables 24-bit LVDS or CMOS output */ # define VR10_INTERFACE_1X24 (1 << 2) -/** Enables 2x18-bit LVDS or CMOS output. */ +/* Enables 2x18-bit LVDS or CMOS output. */ # define VR10_INTERFACE_2X18 (2 << 2) -/** Enables 2x24-bit LVDS output */ +/* Enables 2x24-bit LVDS output */ # define VR10_INTERFACE_2X24 (3 << 2) -/** Mask that defines the depth of the pipeline */ +/* Mask that defines the depth of the pipeline */ # define VR10_INTERFACE_DEPTH_MASK (3 << 2) /* @@ -97,7 +97,7 @@ * Panel power down status */ #define VR30 0x30 -/** Read only bit indicating that the panel is not in a safe poweroff state. */ +/* Read only bit indicating that the panel is not in a safe poweroff state. */ # define VR30_PANEL_ON (1 << 15) #define VR40 0x40 @@ -183,7 +183,7 @@ struct ivch_priv { static void ivch_dump_regs(struct intel_dvo_device *dvo); -/** +/* * Reads a register on the ivch. * * Each of the 256 registers are 16 bits long. @@ -230,7 +230,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) return false; } -/** Writes a 16-bit register on the ivch */ +/* Writes a 16-bit register on the ivch */ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) { struct ivch_priv *priv = dvo->dev_priv; @@ -258,7 +258,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) return false; } -/** Probes the given bus and slave address for an ivch */ +/* Probes the given bus and slave address for an ivch */ static bool ivch_init(struct intel_dvo_device *dvo, struct i2c_adapter *adapter) { @@ -338,7 +338,7 @@ static void ivch_reset(struct intel_dvo_device *dvo) ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]); } -/** Sets the power state of the panel connected to the ivch */ +/* Sets the power state of the panel connected to the ivch */ static void ivch_dpms(struct intel_dvo_device *dvo, bool enable) { int i; From d5fdd43fb17d474454d968a75eb54b01203461f4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:29:08 +0000 Subject: [PATCH 066/113] drm/i915/dvo: Fixup commentary Remove the kerneldoc markup applied to non-kerneldoc comments and convert the multiline comments to the canonical style. drivers/gpu/drm/i915/intel_dvo.c:303: warning: Function parameter or member 'connector' not described in 'intel_dvo_detect' drivers/gpu/drm/i915/intel_dvo.c:303: warning: Function parameter or member 'force' not described in 'intel_dvo_detect' drivers/gpu/drm/i915/intel_dvo.c:382: warning: Function parameter or member 'encoder' not described in 'intel_dvo_get_current_mode' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214092909.27040-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_dvo.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 754baa00bea9..09056a73e1ef 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -248,7 +248,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, intel_dvo->attached_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - /* If we have timings from the BIOS for the panel, put them in + /* + * If we have timings from the BIOS for the panel, put them in * to the adjusted mode. The CRTC will be set up for this mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode. @@ -296,11 +297,6 @@ static void intel_dvo_pre_enable(struct intel_encoder *encoder, I915_WRITE(dvo_reg, dvo_val); } -/** - * Detect the output connection on our DVO device. - * - * Unimplemented. - */ static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector, bool force) { @@ -316,7 +312,8 @@ static int intel_dvo_get_modes(struct drm_connector *connector) const struct drm_display_mode *fixed_mode = to_intel_connector(connector)->panel.fixed_mode; - /* We should probably have an i2c driver get_modes function for those + /* + * We should probably have an i2c driver get_modes function for those * devices which will have a fixed set of modes determined by the chip * (TV-out, for example), but for now with just TMDS and LVDS, * that's not the case. @@ -374,7 +371,7 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { .destroy = intel_dvo_enc_destroy, }; -/** +/* * Attempts to get a fixed panel timing for LVDS (currently only the i830). * * Other chips with DVO LVDS will need to extend this to deal with the LVDS @@ -446,7 +443,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) uint32_t dpll[I915_MAX_PIPES]; enum port port; - /* Allow the I2C driver info to specify the GPIO to be used in + /* + * Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined * in the spec. */ @@ -457,7 +455,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) else gpio = GMBUS_PIN_DPB; - /* Set up the I2C bus necessary for the chip we're probing. + /* + * Set up the I2C bus necessary for the chip we're probing. * It appears that everything is on GPIOE except for panels * on i830 laptops, which are on GPIOB (DVOA). */ @@ -465,12 +464,14 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_dvo->dev = *dvo; - /* GMBUS NAK handling seems to be unstable, hence let the + /* + * GMBUS NAK handling seems to be unstable, hence let the * transmitter detection run in bit banging mode for now. */ intel_gmbus_force_bit(i2c, true); - /* ns2501 requires the DVO 2x clock before it will + /* + * ns2501 requires the DVO 2x clock before it will * respond to i2c accesses, so make sure we have * have the clock enabled before we attempt to * initialize the device. @@ -528,7 +529,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); if (dvo->type == INTEL_DVO_CHIP_LVDS) { - /* For our LVDS chipsets, we should hopefully be able + /* + * For our LVDS chipsets, we should hopefully be able * to dig the fixed panel mode out of the BIOS data. * However, it's in a different format from the BIOS * data on chipsets with integrated LVDS (stored in AIM From af4ef7dccfcaef5eafd6a0eee9a82867800a840d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 09:29:09 +0000 Subject: [PATCH 067/113] drm/i915/lvds: Fixup commentary Remove the kerneldoc markup applied to non-kerneldoc comments and convert the multiline comments to the canonical style. drivers/gpu/drm/i915/intel_lvds.c:313: warning: Function parameter or member 'encoder' not described in 'intel_enable_lvds' drivers/gpu/drm/i915/intel_lvds.c:313: warning: Function parameter or member 'pipe_config' not described in 'intel_enable_lvds' drivers/gpu/drm/i915/intel_lvds.c:313: warning: Function parameter or member 'conn_state' not described in 'intel_enable_lvds' drivers/gpu/drm/i915/intel_lvds.c:453: warning: Function parameter or member 'connector' not described in 'intel_lvds_detect' drivers/gpu/drm/i915/intel_lvds.c:453: warning: Function parameter or member 'force' not described in 'intel_lvds_detect' drivers/gpu/drm/i915/intel_lvds.c:471: warning: Function parameter or member 'connector' not described in 'intel_lvds_get_modes' drivers/gpu/drm/i915/intel_lvds.c:932: warning: Function parameter or member 'dev_priv' not described in 'intel_lvds_init' drivers/gpu/drm/i915/intel_lvds.c:932: warning: Excess function parameter 'dev' description in 'intel_lvds_init' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214092909.27040-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lvds.c | 42 ++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 4677ac0b10d7..d35d2d50f595 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -268,7 +268,9 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, /* set the corresponsding LVDS_BORDER bit */ temp &= ~LVDS_BORDER_ENABLE; temp |= pipe_config->gmch_pfit.lvds_border_bits; - /* Set the B0-B3 data pairs corresponding to whether we're going to + + /* + * Set the B0-B3 data pairs corresponding to whether we're going to * set the DPLLs for dual-channel mode or not. */ if (lvds_encoder->is_dual_link) @@ -276,7 +278,8 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, else temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) + /* + * It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. For now, let's just maintain the * value we got from the BIOS. @@ -284,12 +287,16 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, temp &= ~LVDS_A3_POWER_MASK; temp |= lvds_encoder->a3_power; - /* Set the dithering flag on LVDS as needed, note that there is no + /* + * Set the dithering flag on LVDS as needed, note that there is no * special lvds dither control bit on pch-split platforms, dithering is - * only controlled through the PIPECONF reg. */ + * only controlled through the PIPECONF reg. + */ if (IS_GEN4(dev_priv)) { - /* Bspec wording suggests that LVDS port dithering only exists - * for 18bpp panels. */ + /* + * Bspec wording suggests that LVDS port dithering only exists + * for 18bpp panels. + */ if (pipe_config->dither && pipe_config->pipe_bpp == 18) temp |= LVDS_ENABLE_DITHER; else @@ -304,7 +311,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder, I915_WRITE(lvds_encoder->reg, temp); } -/** +/* * Sets the power state for the panel. */ static void intel_enable_lvds(struct intel_encoder *encoder, @@ -441,7 +448,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, return true; } -/** +/* * Detect the LVDS connection. * * Since LVDS doesn't have hotlug, we use the lid as a proxy. Open means @@ -464,7 +471,7 @@ intel_lvds_detect(struct drm_connector *connector, bool force) return connector_status_connected; } -/** +/* * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ static int intel_lvds_get_modes(struct drm_connector *connector) @@ -893,7 +900,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) if (dmi_check_system(intel_dual_link_lvds)) return true; - /* BIOS should set the proper LVDS register value at boot, but + /* + * BIOS should set the proper LVDS register value at boot, but * in reality, it doesn't set the value when the lid is closed; * we need to check "the value to be set" in VBT when LVDS * register is uninitialized. @@ -907,13 +915,17 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) static bool intel_lvds_supported(struct drm_i915_private *dev_priv) { - /* With the introduction of the PCH we gained a dedicated - * LVDS presence pin, use it. */ + /* + * With the introduction of the PCH we gained a dedicated + * LVDS presence pin, use it. + */ if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) return true; - /* Otherwise LVDS was only attached to mobile products, - * except for the inglorious 830gm */ + /* + * Otherwise LVDS was only attached to mobile products, + * except for the inglorious 830gm + */ if (INTEL_GEN(dev_priv) <= 4 && IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) return true; @@ -923,7 +935,7 @@ static bool intel_lvds_supported(struct drm_i915_private *dev_priv) /** * intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device + * @dev_priv: i915 device * * Create the connector, register the LVDS DDC bus, and try to figure out what * modes we can display on the LVDS panel (if present). From 847c51e030acc7edbf207beaf4435aea241d64d5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 10:40:40 +0000 Subject: [PATCH 068/113] drm/i915: Add missing kerneldoc parameters for huc_ucode_xfer During the recent upheaval to uc, the parameters to huc_ucode_xfer were changed, but the kerneldoc left behind. drivers/gpu/drm/i915/intel_huc.c:128: warning: Function parameter or member 'huc_fw' not described in 'huc_ucode_xfer' drivers/gpu/drm/i915/intel_huc.c:128: warning: Function parameter or member 'vma' not described in 'huc_ucode_xfer' drivers/gpu/drm/i915/intel_huc.c:128: warning: Excess function parameter 'dev_priv' description in 'huc_ucode_xfer' Signed-off-by: Chris Wilson Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20180214104040.4532-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_huc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 8ed05182f944..ef9a05d8e5a9 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -118,7 +118,8 @@ void intel_huc_init_early(struct intel_huc *huc) /** * huc_ucode_xfer() - DMA's the firmware - * @dev_priv: the drm_i915_private device + * @huc_fw: the firmware descriptor + * @vma: the firmware image (bound into the GGTT) * * Transfer the firmware image to RAM for execution by the microcontroller. * From b8aad15e2cdc52434bde2752690e5ab63f7211e9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 10:53:32 +0000 Subject: [PATCH 069/113] drm/i915: Fixup kerneldoc for intel_uc_fw_upload() Just a parameter name change that was lost to kerneldoc. drivers/gpu/drm/i915/intel_uc_fw.c:209: warning: Function parameter or member 'xfer' not described in 'intel_uc_fw_upload' drivers/gpu/drm/i915/intel_uc_fw.c:209: warning: Excess function parameter 'loader' description in 'intel_uc_fw_upload' v2: Add the Returns: Signed-off-by: Chris Wilson Reviewed-by: Michal Wajdeczko Link: https://patchwork.freedesktop.org/patch/msgid/20180214105332.30230-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_uc_fw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c index 784eff9cdfc8..3ec0ce505b76 100644 --- a/drivers/gpu/drm/i915/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/intel_uc_fw.c @@ -197,11 +197,12 @@ fail: /** * intel_uc_fw_upload - load uC firmware using custom loader - * * @uc_fw: uC firmware - * @loader: custom uC firmware loader function + * @xfer: custom uC firmware loader function * * Loads uC firmware using custom loader and updates internal flags. + * + * Return: 0 on success, non-zero on failure. */ int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, int (*xfer)(struct intel_uc_fw *uc_fw, From eac95c4e2f8c73e0ab8ff32ba15a77433c787a70 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 13:49:21 +0000 Subject: [PATCH 070/113] drm/i915/atomic: Fixup kerneldoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_atomic.c:198: warning: Function parameter or member 'state' not described in 'intel_crtc_destroy_state' drivers/gpu/drm/i915/intel_atomic.c:222: warning: Function parameter or member 'intel_crtc' not described in 'intel_atomic_setup_scalers' drivers/gpu/drm/i915/intel_atomic.c:222: warning: Excess function parameter 'crtc' description in 'intel_atomic_setup_scalers' Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180214134922.28761-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_atomic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 36d4e635e4ce..bb5df2b4e349 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -186,13 +186,14 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) /** * intel_crtc_destroy_state - destroy crtc state * @crtc: drm crtc + * @state: the state to destroy * * Destroys the crtc state (both common and Intel-specific) for the * specified crtc. */ void intel_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) + struct drm_crtc_state *state) { drm_atomic_helper_crtc_destroy_state(crtc, state); } @@ -200,7 +201,7 @@ intel_crtc_destroy_state(struct drm_crtc *crtc, /** * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests * @dev_priv: i915 device - * @crtc: intel crtc + * @intel_crtc: intel crtc * @crtc_state: incoming crtc_state to validate and setup scalers * * This function sets up scalers based on staged scaling requests for From c38c1455595295488109126b0e0d0fe6a4547355 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 13:49:22 +0000 Subject: [PATCH 071/113] drm/i915: Fixup kerneldoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_display.c:569: warning: Function parameter or member 'dev_priv' not described in 'intel_PLL_is_valid' drivers/gpu/drm/i915/intel_display.c:569: warning: Function parameter or member 'limit' not described in 'intel_PLL_is_valid' drivers/gpu/drm/i915/intel_display.c:569: warning: Function parameter or member 'clock' not described in 'intel_PLL_is_valid' drivers/gpu/drm/i915/intel_display.c:4769: warning: Function parameter or member 'crtc_state' not described in 'skl_update_scaler_plane' drivers/gpu/drm/i915/intel_display.c:4769: warning: Excess function parameter 'state' description in 'skl_update_scaler_plane' drivers/gpu/drm/i915/intel_display.c:4967: warning: Function parameter or member 'new_crtc_state' not described in 'intel_post_enable_primary' drivers/gpu/drm/i915/intel_display.c:12650: warning: Function parameter or member 'new_state' not described in 'intel_prepare_plane_fb' drivers/gpu/drm/i915/intel_display.c:12650: warning: Excess function parameter 'fb' description in 'intel_prepare_plane_fb' drivers/gpu/drm/i915/intel_display.c:12763: warning: Function parameter or member 'old_state' not described in 'intel_cleanup_plane_fb' drivers/gpu/drm/i915/intel_display.c:12763: warning: Excess function parameter 'fb' description in 'intel_cleanup_plane_fb' Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180214134922.28761-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bedb40861360..95d0e7a64773 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -558,11 +558,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock) } #define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0) -/** + +/* * Returns whether the given set of divisors are valid for a given refclk with * the given connectors. */ - static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv, const struct intel_limit *limit, const struct dpll *clock) @@ -4756,8 +4756,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state) /** * skl_update_scaler_plane - Stages update to scaler state for a given plane. - * - * @state: crtc's scaler state + * @crtc_state: crtc's scaler state * @plane_state: atomic plane state to update * * Return @@ -4954,6 +4953,7 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) /** * intel_post_enable_primary - Perform operations after enabling primary plane * @crtc: the CRTC whose primary plane was just enabled + * @new_crtc_state: the enabling state * * Performs potentially sleeping operations that must be done after the primary * plane is enabled, such as updating FBC and IPS. Note that this may be @@ -12619,7 +12619,7 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc, /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for - * @fb: framebuffer to prepare for presentation + * @new_state: the plane state being prepared * * Prepares a framebuffer for usage on a display plane. Generally this * involves pinning the underlying object and updating the frontbuffer tracking @@ -12737,7 +12737,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, /** * intel_cleanup_plane_fb - Cleans up an fb after plane use * @plane: drm plane to clean up for - * @fb: old framebuffer that was on plane + * @old_state: the state from the previous modeset * * Cleans up a framebuffer that has just been removed from a plane. * From 31383410f5327ceb6dc95c72296d0c4bf44bc616 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 14:03:03 +0000 Subject: [PATCH 072/113] drm/i915: Fixup kerneldoc for intel_pm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_pm.c:750: warning: Function parameter or member 'fifo_size' not described in 'intel_calculate_wm' drivers/gpu/drm/i915/intel_pm.c:5900: warning: Function parameter or member 'crtc' not described in 'intel_update_watermarks' Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180214140303.1561-1-chris@chris-wilson.co.uk Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/i915/intel_pm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7e15b261821d..158d00fdf549 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -729,6 +729,7 @@ static unsigned int intel_wm_method2(unsigned int pixel_rate, * intel_calculate_wm - calculate watermark level * @pixel_rate: pixel clock * @wm: chip FIFO params + * @fifo_size: size of the FIFO buffer * @cpp: bytes per pixel * @latency_ns: memory latency for the platform * @@ -5866,6 +5867,7 @@ void ilk_wm_get_hw_state(struct drm_device *dev) /** * intel_update_watermarks - update FIFO watermark values based on current modes + * @crtc: the #intel_crtc on which to compute the WM * * Calculate watermark values for the various WM regs based on current mode * and plane configuration. From b6a88e4a804cf5a71159906e16df2c1fc7196f92 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 14 Feb 2018 11:18:25 -0800 Subject: [PATCH 073/113] drm/i915: Fix rsvd2 mask when out-fence is returned GENMASK_ULL wants the high bit of the mask first. The current value cancels the in-fence when an out-fence is returned. Fixes: fec0445caa273 ("drm/i915: Support explicit fencing for execbuf") Testcase: igt/gem_exec_fence/keep-in-fence* Cc: Chris Wilson Signed-off-by: Daniele Ceraolo Spurio Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180214191827.8465-1-daniele.ceraolospurio@intel.com Cc: # v4.12+ --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b15305f2fb76..ed6e9db51e67 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -2410,7 +2410,7 @@ err_request: if (out_fence) { if (err == 0) { fd_install(out_fence_fd, out_fence->file); - args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */ + args->rsvd2 &= GENMASK_ULL(31, 0); /* keep in-fence */ args->rsvd2 |= (u64)out_fence_fd << 32; out_fence_fd = -1; } else { From e3890d05b34266f5981876c65a6a97fc0d0d0ccb Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 7 Feb 2018 23:32:19 -0800 Subject: [PATCH 074/113] drm/i915/cnl: Sync PCI ID with Spec. Add one missing PCI ID and sort them in a way that gets easier to review and compare against spec's table. When trying to sync libdrm and mesa id list with kernel and spec I noticed something was wrong and we were missing a pci id. So to make our lives easier when checking against spec let's simplify and sort like spec does. BSpec: 13621 Cc: Lucas De Marchi Cc: James Ausmus Signed-off-by: Rodrigo Vivi Reviewed-by: James Ausmus Link: https://patchwork.freedesktop.org/patch/msgid/20180208073219.27860-1-rodrigo.vivi@intel.com --- include/drm/i915_pciids.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 9e1fe6634424..0b2ba46fa00b 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -416,18 +416,19 @@ /* CNL */ #define INTEL_CNL_IDS(info) \ - INTEL_VGA_DEVICE(0x5A52, info), \ - INTEL_VGA_DEVICE(0x5A5A, info), \ - INTEL_VGA_DEVICE(0x5A42, info), \ - INTEL_VGA_DEVICE(0x5A4A, info), \ INTEL_VGA_DEVICE(0x5A51, info), \ INTEL_VGA_DEVICE(0x5A59, info), \ INTEL_VGA_DEVICE(0x5A41, info), \ INTEL_VGA_DEVICE(0x5A49, info), \ - INTEL_VGA_DEVICE(0x5A71, info), \ - INTEL_VGA_DEVICE(0x5A79, info), \ + INTEL_VGA_DEVICE(0x5A52, info), \ + INTEL_VGA_DEVICE(0x5A5A, info), \ + INTEL_VGA_DEVICE(0x5A42, info), \ + INTEL_VGA_DEVICE(0x5A4A, info), \ + INTEL_VGA_DEVICE(0x5A50, info), \ + INTEL_VGA_DEVICE(0x5A40, info), \ INTEL_VGA_DEVICE(0x5A54, info), \ INTEL_VGA_DEVICE(0x5A5C, info), \ - INTEL_VGA_DEVICE(0x5A44, info) + INTEL_VGA_DEVICE(0x5A44, info), \ + INTEL_VGA_DEVICE(0x5A4C, info) #endif /* _I915_PCIIDS_H */ From ccf74400da4d7c94307ac24e7398337d9c4312d9 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 14 Feb 2018 12:42:05 -0800 Subject: [PATCH 075/113] drm/i915/cnl: Remove alpha_support protection We now have a stable cnl on our CI and it seems mostly green without big risks of blank screen or anything blowing up on linux installations in the future. As a reminder i915.alpha_support was created to protect future linux installation's iso images that might contain a kernel from the enabling time of the new platform. Without this protection most of linux installation was recommending nomodeset option during installation that was getting stick there after installation. Specifically, alpha support says nothing about the development state of the hardware, and everything about the state of the driver in a kernel release. This is semantically no different from the old preliminary_hw_support flag, but the old one was all too often interpreted as (preliminary hw) support instead of the intended (preliminary) hw support, and it was misleading for everyone. Hence the rename. v2: Fix the typos and include more history about the parameter rename on commit message. (Jani) Reference: https://intel-gfx-ci.01.org/tree/drm-tip/fi-cnl-y3.html Cc: James Ausmus Cc: Lucas De Marchi Cc: Jani Saarinen Cc: Jani Nikula Cc: Joonas Lahtinen Signed-off-by: Rodrigo Vivi Acked-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214204205.4446-1-rodrigo.vivi@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 4e7a10c89782..49cef20594b3 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -573,7 +573,6 @@ static const struct intel_device_info intel_coffeelake_gt3_info = { static const struct intel_device_info intel_cannonlake_info = { GEN10_FEATURES, - .is_alpha_support = 1, .platform = INTEL_CANNONLAKE, .gen = 10, .gt = 2, From cdb3db8542d854bd678d60cd28861b042e191672 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 14 Feb 2018 19:38:40 +0200 Subject: [PATCH 076/113] drm/i915/audio: fix check for av_enc_map overflow Turns out -1 >= ARRAY_SIZE() is always true. Move the bounds check where we know pipe >= 0 and next to the array indexing where it makes most sense. Fixes: 9965db26ac05 ("drm/i915: Check for fused or unused pipes") Fixes: 0b7029b7e43f ("drm/i915: Check for fused or unused pipes") Cc: # v4.10+ Cc: Mika Kahola Cc: Rodrigo Vivi Cc: Jani Nikula Cc: Joonas Lahtinen Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Dhinakaran Pandiyan Reviewed-by: Mika Kahola Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214173840.25360-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index ff455c724775..709d6ca68074 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -779,11 +779,11 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, { struct intel_encoder *encoder; - if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) - return NULL; - /* MST */ if (pipe >= 0) { + if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) + return NULL; + encoder = dev_priv->av_enc_map[pipe]; /* * when bootup, audio driver may not know it is From cc3290955255ce61d16ceeab87685e99dc27bbc4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 14 Feb 2018 16:07:20 +0000 Subject: [PATCH 077/113] drm/i915: Clean up ancient doc comments for i915_ioc32.c As befitting a file dedicated to the mistakes of the past, drivers/gpu/drm/i915/i915_ioc32.c:2: warning: Cannot understand * \file i915_ioc32.c on line 2 - I thought it was a doc line drivers/gpu/drm/i915/i915_ioc32.c:82: warning: Function parameter or member 'filp' not described in 'i915_compat_ioctl' drivers/gpu/drm/i915/i915_ioc32.c:82: warning: Function parameter or member 'cmd' not described in 'i915_compat_ioctl' drivers/gpu/drm/i915/i915_ioc32.c:82: warning: Function parameter or member 'arg' not described in 'i915_compat_ioctl' Signed-off-by: Chris Wilson Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20180214160720.19673-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_ioc32.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 97f3a5640289..0e5c580d117c 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -1,11 +1,6 @@ -/** - * \file i915_ioc32.c - * +/* * 32-bit ioctl compatibility routines for the i915 DRM. * - * \author Alan Hourihane - * - * * Copyright (C) Paul Mackerras 2005 * Copyright (C) Alan Hourihane 2005 * All Rights Reserved. @@ -28,6 +23,8 @@ * 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. + * + * Author: Alan Hourihane */ #include @@ -55,10 +52,10 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); - if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) - || __put_user(req32.param, &request->param) - || __put_user((void __user *)(unsigned long)req32.value, - &request->value)) + if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || + __put_user(req32.param, &request->param) || + __put_user((void __user *)(unsigned long)req32.value, + &request->value)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM, @@ -70,13 +67,13 @@ static drm_ioctl_compat_t *i915_compat_ioctls[] = { }; /** + * i915_compat_ioctl - handle the mistakes of the past + * @filp: the file pointer + * @cmd: the ioctl command (and encoded flags) + * @arg: the ioctl argument (from userspace) + * * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/dri/card. - * - * \param filp file pointer. - * \param cmd command. - * \param arg user argument. - * \return zero on success or negative number on failure. */ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { From 62d4028fb0b9ce6250d66c39ebe887522d77eb3c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 11:07:59 +0000 Subject: [PATCH 078/113] drm/i915/gtt: Convert WARN_ON to GEM debugging As we presume that we have sufficient coverage of CI for new machines and new code paths, we do not need to have user impacting WARN_ON for programming errors inside i915_gem_gtt.c, so convert those over to GEM_BUG_ON. This leaves the memory debugging WARN_ON in place as they are not so easy to exercise with CI. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20180215110759.28603-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_gtt.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a44eccda7d48..cd5984246bc3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -710,7 +710,7 @@ alloc_pdp(struct i915_address_space *vm) struct i915_page_directory_pointer *pdp; int ret = -ENOMEM; - WARN_ON(!use_4lvl(vm)); + GEM_BUG_ON(!use_4lvl(vm)); pdp = kzalloc(sizeof(*pdp), GFP_KERNEL); if (!pdp) @@ -2249,9 +2249,9 @@ void i915_ppgtt_release(struct kref *kref) trace_i915_ppgtt_release(&ppgtt->base); /* vmas should already be unbound and destroyed */ - WARN_ON(!list_empty(&ppgtt->base.active_list)); - WARN_ON(!list_empty(&ppgtt->base.inactive_list)); - WARN_ON(!list_empty(&ppgtt->base.unbound_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.active_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.inactive_list)); + GEM_BUG_ON(!list_empty(&ppgtt->base.unbound_list)); ppgtt->base.cleanup(&ppgtt->base); i915_address_space_fini(&ppgtt->base); @@ -2814,10 +2814,10 @@ int i915_gem_init_aliasing_ppgtt(struct drm_i915_private *i915) i915->mm.aliasing_ppgtt = ppgtt; - WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); + GEM_BUG_ON(ggtt->base.bind_vma != ggtt_bind_vma); ggtt->base.bind_vma = aliasing_gtt_bind_vma; - WARN_ON(ggtt->base.unbind_vma != ggtt_unbind_vma); + GEM_BUG_ON(ggtt->base.unbind_vma != ggtt_unbind_vma); ggtt->base.unbind_vma = aliasing_gtt_unbind_vma; return 0; @@ -2908,7 +2908,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) ggtt->base.closed = true; mutex_lock(&dev_priv->drm.struct_mutex); - WARN_ON(!list_empty(&ggtt->base.active_list)); + GEM_BUG_ON(!list_empty(&ggtt->base.active_list)); list_for_each_entry_safe(vma, vn, &ggtt->base.inactive_list, vm_link) WARN_ON(i915_vma_unbind(vma)); mutex_unlock(&dev_priv->drm.struct_mutex); @@ -3801,6 +3801,9 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj)); switch (vma->ggtt_view.type) { + default: + GEM_BUG_ON(vma->ggtt_view.type); + /* fall through */ case I915_GGTT_VIEW_NORMAL: vma->pages = vma->obj->mm.pages; return 0; @@ -3813,11 +3816,6 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) case I915_GGTT_VIEW_PARTIAL: vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj); break; - - default: - WARN_ONCE(1, "GGTT view %u not implemented!\n", - vma->ggtt_view.type); - return -EINVAL; } ret = 0; From bc76298e68e791f878d76f9b7a911713c85b2843 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 08:19:28 +0000 Subject: [PATCH 079/113] drm/i915: Store gen_mask inside the static device info Rather than deriving the gen_mask from the static intel_device_info->gen at runtime, pre-fill it in the static data. v2: Undefine local macros at end of their scope. Signed-off-by: Chris Wilson Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180215081930.11477-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 -- drivers/gpu/drm/i915/i915_pci.c | 41 +++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a9931b8ec0b3..046c073aa4aa 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -909,8 +909,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, device_info->platform_mask = BIT(device_info->platform); BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); - device_info->gen_mask = BIT(device_info->gen - 1); - spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); mutex_init(&dev_priv->backlight_lock); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 49cef20594b3..37257f8d9aa9 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -29,6 +29,8 @@ #include "i915_drv.h" #include "i915_selftest.h" +#define GEN(x) .gen = (x), .gen_mask = BIT((x) - 1) + #define GEN_DEFAULT_PIPEOFFSETS \ .pipe_offsets = { PIPE_A_OFFSET, PIPE_B_OFFSET, \ PIPE_C_OFFSET, PIPE_EDP_OFFSET }, \ @@ -63,7 +65,8 @@ .page_sizes = I915_GTT_PAGE_SIZE_4K #define GEN2_FEATURES \ - .gen = 2, .num_pipes = 1, \ + GEN(2), \ + .num_pipes = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \ .has_gmch_display = 1, \ .hws_needs_physical = 1, \ @@ -100,7 +103,8 @@ static const struct intel_device_info intel_i865g_info = { }; #define GEN3_FEATURES \ - .gen = 3, .num_pipes = 2, \ + GEN(3), \ + .num_pipes = 2, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ .has_snoop = true, \ @@ -163,7 +167,8 @@ static const struct intel_device_info intel_pineview_info = { }; #define GEN4_FEATURES \ - .gen = 4, .num_pipes = 2, \ + GEN(4), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .has_gmch_display = 1, \ .ring_mask = RENDER_RING, \ @@ -205,7 +210,8 @@ static const struct intel_device_info intel_gm45_info = { }; #define GEN5_FEATURES \ - .gen = 5, .num_pipes = 2, \ + GEN(5), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ .has_snoop = true, \ @@ -227,7 +233,8 @@ static const struct intel_device_info intel_ironlake_m_info = { }; #define GEN6_FEATURES \ - .gen = 6, .num_pipes = 2, \ + GEN(6), \ + .num_pipes = 2, \ .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ @@ -270,7 +277,8 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = { }; #define GEN7_FEATURES \ - .gen = 7, .num_pipes = 3, \ + GEN(7), \ + .num_pipes = 3, \ .has_hotplug = 1, \ .has_fbc = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ @@ -324,7 +332,7 @@ static const struct intel_device_info intel_ivybridge_q_info = { static const struct intel_device_info intel_valleyview_info = { .platform = INTEL_VALLEYVIEW, - .gen = 7, + GEN(7), .is_lp = 1, .num_pipes = 2, .has_psr = 1, @@ -385,7 +393,7 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define BDW_PLATFORM \ GEN8_FEATURES, \ - .gen = 8, \ + GEN(8), \ .platform = INTEL_BROADWELL static const struct intel_device_info intel_broadwell_gt1_info = { @@ -413,7 +421,8 @@ static const struct intel_device_info intel_broadwell_gt3_info = { }; static const struct intel_device_info intel_cherryview_info = { - .gen = 8, .num_pipes = 3, + GEN(8), + .num_pipes = 3, .has_hotplug = 1, .is_lp = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, @@ -452,7 +461,7 @@ static const struct intel_device_info intel_cherryview_info = { #define SKL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ + GEN(9), \ .platform = INTEL_SKYLAKE static const struct intel_device_info intel_skylake_gt1_info = { @@ -481,7 +490,7 @@ static const struct intel_device_info intel_skylake_gt4_info = { }; #define GEN9_LP_FEATURES \ - .gen = 9, \ + GEN(9), \ .is_lp = 1, \ .has_hotplug = 1, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ @@ -526,7 +535,7 @@ static const struct intel_device_info intel_geminilake_info = { #define KBL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ + GEN(9), \ .platform = INTEL_KABYLAKE static const struct intel_device_info intel_kabylake_gt1_info = { @@ -547,7 +556,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = { #define CFL_PLATFORM \ GEN9_FEATURES, \ - .gen = 9, \ + GEN(9), \ .platform = INTEL_COFFEELAKE static const struct intel_device_info intel_coffeelake_gt1_info = { @@ -573,14 +582,14 @@ static const struct intel_device_info intel_coffeelake_gt3_info = { static const struct intel_device_info intel_cannonlake_info = { GEN10_FEATURES, + GEN(10), .platform = INTEL_CANNONLAKE, - .gen = 10, .gt = 2, }; #define GEN11_FEATURES \ GEN10_FEATURES, \ - .gen = 11, \ + GEN(11), \ .ddb_size = 2048, \ .has_csr = 0 @@ -591,6 +600,8 @@ static const struct intel_device_info intel_icelake_11_info = { .has_resource_streamer = 0, }; +#undef GEN + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem From a6e1c5ace4810342b708f3fbbd203013d4b9d22c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 08:19:29 +0000 Subject: [PATCH 080/113] drm/i915: Always define GEN as part of GENx_FEATURES Be consistent and define the device's GEN as part of the GENx_FEATURE. It will be overridden by the next gen upon inheriting, as per usual. Signed-off-by: Chris Wilson Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180215081930.11477-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_pci.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 37257f8d9aa9..0ed99966c7a7 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -383,6 +383,7 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define GEN8_FEATURES \ G75_FEATURES, \ + GEN(8), \ BDW_COLORS, \ .page_sizes = I915_GTT_PAGE_SIZE_4K | \ I915_GTT_PAGE_SIZE_2M, \ @@ -393,7 +394,6 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define BDW_PLATFORM \ GEN8_FEATURES, \ - GEN(8), \ .platform = INTEL_BROADWELL static const struct intel_device_info intel_broadwell_gt1_info = { @@ -452,6 +452,7 @@ static const struct intel_device_info intel_cherryview_info = { #define GEN9_FEATURES \ GEN8_FEATURES, \ + GEN(9), \ GEN9_DEFAULT_PAGE_SIZES, \ .has_logical_ring_preemption = 1, \ .has_csr = 1, \ @@ -461,7 +462,6 @@ static const struct intel_device_info intel_cherryview_info = { #define SKL_PLATFORM \ GEN9_FEATURES, \ - GEN(9), \ .platform = INTEL_SKYLAKE static const struct intel_device_info intel_skylake_gt1_info = { @@ -535,7 +535,6 @@ static const struct intel_device_info intel_geminilake_info = { #define KBL_PLATFORM \ GEN9_FEATURES, \ - GEN(9), \ .platform = INTEL_KABYLAKE static const struct intel_device_info intel_kabylake_gt1_info = { @@ -556,7 +555,6 @@ static const struct intel_device_info intel_kabylake_gt3_info = { #define CFL_PLATFORM \ GEN9_FEATURES, \ - GEN(9), \ .platform = INTEL_COFFEELAKE static const struct intel_device_info intel_coffeelake_gt1_info = { @@ -577,12 +575,12 @@ static const struct intel_device_info intel_coffeelake_gt3_info = { #define GEN10_FEATURES \ GEN9_FEATURES, \ + GEN(10), \ .ddb_size = 1024, \ GLK_COLORS static const struct intel_device_info intel_cannonlake_info = { GEN10_FEATURES, - GEN(10), .platform = INTEL_CANNONLAKE, .gt = 2, }; From c5cb21c17a169eee5d45f2706ba3b6c3a7288786 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 08:19:30 +0000 Subject: [PATCH 081/113] drm/i915: Store platform_mask inside the static device info Rather than deriving the platform_mask from the intel_device_static_info->platform at runtime, pre-fill it in the static data. v2: Undefine macros at end of their scope Signed-off-by: Chris Wilson Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180215081930.11477-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.c | 2 - drivers/gpu/drm/i915/i915_pci.c | 70 ++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 046c073aa4aa..d09f8e661fbd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -906,8 +906,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, BUILD_BUG_ON(INTEL_MAX_PLATFORMS > sizeof(device_info->platform_mask) * BITS_PER_BYTE); - device_info->platform_mask = BIT(device_info->platform); - BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 0ed99966c7a7..1eaabf28d7b7 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_selftest.h" +#define PLATFORM(x) .platform = (x), .platform_mask = BIT(x) #define GEN(x) .gen = (x), .gen_mask = BIT((x) - 1) #define GEN_DEFAULT_PIPEOFFSETS \ @@ -79,19 +80,20 @@ static const struct intel_device_info intel_i830_info = { GEN2_FEATURES, - .platform = INTEL_I830, + PLATFORM(INTEL_I830), .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, /* legal, last one wins */ }; static const struct intel_device_info intel_i845g_info = { GEN2_FEATURES, - .platform = INTEL_I845G, + PLATFORM(INTEL_I845G), }; static const struct intel_device_info intel_i85x_info = { GEN2_FEATURES, - .platform = INTEL_I85X, .is_mobile = 1, + PLATFORM(INTEL_I85X), + .is_mobile = 1, .num_pipes = 2, /* legal, last one wins */ .cursor_needs_physical = 1, .has_fbc = 1, @@ -99,7 +101,7 @@ static const struct intel_device_info intel_i85x_info = { static const struct intel_device_info intel_i865g_info = { GEN2_FEATURES, - .platform = INTEL_I865G, + PLATFORM(INTEL_I865G), }; #define GEN3_FEATURES \ @@ -114,7 +116,8 @@ static const struct intel_device_info intel_i865g_info = { static const struct intel_device_info intel_i915g_info = { GEN3_FEATURES, - .platform = INTEL_I915G, .cursor_needs_physical = 1, + PLATFORM(INTEL_I915G), + .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .hws_needs_physical = 1, .unfenced_needs_alignment = 1, @@ -122,7 +125,7 @@ static const struct intel_device_info intel_i915g_info = { static const struct intel_device_info intel_i915gm_info = { GEN3_FEATURES, - .platform = INTEL_I915GM, + PLATFORM(INTEL_I915GM), .is_mobile = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, @@ -134,7 +137,7 @@ static const struct intel_device_info intel_i915gm_info = { static const struct intel_device_info intel_i945g_info = { GEN3_FEATURES, - .platform = INTEL_I945G, + PLATFORM(INTEL_I945G), .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .hws_needs_physical = 1, @@ -143,7 +146,8 @@ static const struct intel_device_info intel_i945g_info = { static const struct intel_device_info intel_i945gm_info = { GEN3_FEATURES, - .platform = INTEL_I945GM, .is_mobile = 1, + PLATFORM(INTEL_I945GM), + .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, @@ -154,14 +158,15 @@ static const struct intel_device_info intel_i945gm_info = { static const struct intel_device_info intel_g33_info = { GEN3_FEATURES, - .platform = INTEL_G33, + PLATFORM(INTEL_G33), .has_hotplug = 1, .has_overlay = 1, }; static const struct intel_device_info intel_pineview_info = { GEN3_FEATURES, - .platform = INTEL_PINEVIEW, .is_mobile = 1, + PLATFORM(INTEL_PINEVIEW), + .is_mobile = 1, .has_hotplug = 1, .has_overlay = 1, }; @@ -179,7 +184,7 @@ static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_i965g_info = { GEN4_FEATURES, - .platform = INTEL_I965G, + PLATFORM(INTEL_I965G), .has_overlay = 1, .hws_needs_physical = 1, .has_snoop = false, @@ -187,7 +192,7 @@ static const struct intel_device_info intel_i965g_info = { static const struct intel_device_info intel_i965gm_info = { GEN4_FEATURES, - .platform = INTEL_I965GM, + PLATFORM(INTEL_I965GM), .is_mobile = 1, .has_fbc = 1, .has_overlay = 1, .supports_tv = 1, @@ -197,13 +202,13 @@ static const struct intel_device_info intel_i965gm_info = { static const struct intel_device_info intel_g45_info = { GEN4_FEATURES, - .platform = INTEL_G45, + PLATFORM(INTEL_G45), .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_gm45_info = { GEN4_FEATURES, - .platform = INTEL_GM45, + PLATFORM(INTEL_GM45), .is_mobile = 1, .has_fbc = 1, .supports_tv = 1, .ring_mask = RENDER_RING | BSD_RING, @@ -223,12 +228,12 @@ static const struct intel_device_info intel_gm45_info = { static const struct intel_device_info intel_ironlake_d_info = { GEN5_FEATURES, - .platform = INTEL_IRONLAKE, + PLATFORM(INTEL_IRONLAKE), }; static const struct intel_device_info intel_ironlake_m_info = { GEN5_FEATURES, - .platform = INTEL_IRONLAKE, + PLATFORM(INTEL_IRONLAKE), .is_mobile = 1, .has_fbc = 1, }; @@ -248,7 +253,7 @@ static const struct intel_device_info intel_ironlake_m_info = { #define SNB_D_PLATFORM \ GEN6_FEATURES, \ - .platform = INTEL_SANDYBRIDGE + PLATFORM(INTEL_SANDYBRIDGE) static const struct intel_device_info intel_sandybridge_d_gt1_info = { SNB_D_PLATFORM, @@ -262,7 +267,7 @@ static const struct intel_device_info intel_sandybridge_d_gt2_info = { #define SNB_M_PLATFORM \ GEN6_FEATURES, \ - .platform = INTEL_SANDYBRIDGE, \ + PLATFORM(INTEL_SANDYBRIDGE), \ .is_mobile = 1 @@ -293,7 +298,7 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = { #define IVB_D_PLATFORM \ GEN7_FEATURES, \ - .platform = INTEL_IVYBRIDGE, \ + PLATFORM(INTEL_IVYBRIDGE), \ .has_l3_dpf = 1 static const struct intel_device_info intel_ivybridge_d_gt1_info = { @@ -308,7 +313,7 @@ static const struct intel_device_info intel_ivybridge_d_gt2_info = { #define IVB_M_PLATFORM \ GEN7_FEATURES, \ - .platform = INTEL_IVYBRIDGE, \ + PLATFORM(INTEL_IVYBRIDGE), \ .is_mobile = 1, \ .has_l3_dpf = 1 @@ -324,14 +329,14 @@ static const struct intel_device_info intel_ivybridge_m_gt2_info = { static const struct intel_device_info intel_ivybridge_q_info = { GEN7_FEATURES, - .platform = INTEL_IVYBRIDGE, + PLATFORM(INTEL_IVYBRIDGE), .gt = 2, .num_pipes = 0, /* legal, last one wins */ .has_l3_dpf = 1, }; static const struct intel_device_info intel_valleyview_info = { - .platform = INTEL_VALLEYVIEW, + PLATFORM(INTEL_VALLEYVIEW), GEN(7), .is_lp = 1, .num_pipes = 2, @@ -363,7 +368,7 @@ static const struct intel_device_info intel_valleyview_info = { #define HSW_PLATFORM \ G75_FEATURES, \ - .platform = INTEL_HASWELL, \ + PLATFORM(INTEL_HASWELL), \ .has_l3_dpf = 1 static const struct intel_device_info intel_haswell_gt1_info = { @@ -394,7 +399,7 @@ static const struct intel_device_info intel_haswell_gt3_info = { #define BDW_PLATFORM \ GEN8_FEATURES, \ - .platform = INTEL_BROADWELL + PLATFORM(INTEL_BROADWELL) static const struct intel_device_info intel_broadwell_gt1_info = { BDW_PLATFORM, @@ -421,12 +426,12 @@ static const struct intel_device_info intel_broadwell_gt3_info = { }; static const struct intel_device_info intel_cherryview_info = { + PLATFORM(INTEL_CHERRYVIEW), GEN(8), .num_pipes = 3, .has_hotplug = 1, .is_lp = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, - .platform = INTEL_CHERRYVIEW, .has_64bit_reloc = 1, .has_psr = 1, .has_runtime_pm = 1, @@ -462,7 +467,7 @@ static const struct intel_device_info intel_cherryview_info = { #define SKL_PLATFORM \ GEN9_FEATURES, \ - .platform = INTEL_SKYLAKE + PLATFORM(INTEL_SKYLAKE) static const struct intel_device_info intel_skylake_gt1_info = { SKL_PLATFORM, @@ -522,20 +527,20 @@ static const struct intel_device_info intel_skylake_gt4_info = { static const struct intel_device_info intel_broxton_info = { GEN9_LP_FEATURES, - .platform = INTEL_BROXTON, + PLATFORM(INTEL_BROXTON), .ddb_size = 512, }; static const struct intel_device_info intel_geminilake_info = { GEN9_LP_FEATURES, - .platform = INTEL_GEMINILAKE, + PLATFORM(INTEL_GEMINILAKE), .ddb_size = 1024, GLK_COLORS, }; #define KBL_PLATFORM \ GEN9_FEATURES, \ - .platform = INTEL_KABYLAKE + PLATFORM(INTEL_KABYLAKE) static const struct intel_device_info intel_kabylake_gt1_info = { KBL_PLATFORM, @@ -555,7 +560,7 @@ static const struct intel_device_info intel_kabylake_gt3_info = { #define CFL_PLATFORM \ GEN9_FEATURES, \ - .platform = INTEL_COFFEELAKE + PLATFORM(INTEL_COFFEELAKE) static const struct intel_device_info intel_coffeelake_gt1_info = { CFL_PLATFORM, @@ -581,7 +586,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info = { static const struct intel_device_info intel_cannonlake_info = { GEN10_FEATURES, - .platform = INTEL_CANNONLAKE, + PLATFORM(INTEL_CANNONLAKE), .gt = 2, }; @@ -593,12 +598,13 @@ static const struct intel_device_info intel_cannonlake_info = { static const struct intel_device_info intel_icelake_11_info = { GEN11_FEATURES, - .platform = INTEL_ICELAKE, + PLATFORM(INTEL_ICELAKE), .is_alpha_support = 1, .has_resource_streamer = 0, }; #undef GEN +#undef PLATFORM /* * Make sure any device matches here are from most specific to most From 6e8c06d291f339d6586777e4c6184fb1102c2d97 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 14 Feb 2018 15:12:34 -0600 Subject: [PATCH 082/113] drm/i915/selftests: fix inconsistent IS_ERR and PTR_ERR Fix inconsistent IS_ERR and PTR_ERR in shrink_boom. The proper pointer to use is _explode_ instead of _purge_. This issue was detected with the help of Coccinelle. Fixes: fe215c8bc426 ("drm/i915/selftests: add missing gtt shrinker test") Signed-off-by: Gustavo A. R. Silva Link: https://patchwork.freedesktop.org/patch/msgid/20180214211234.GA22341@embeddedgus Reviewed-by: Jani Nikula Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index d8064276431c..89b6ca9b14a7 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -927,7 +927,7 @@ static int shrink_boom(struct drm_i915_private *i915, explode = fake_dma_object(i915, size); if (IS_ERR(explode)) { - err = PTR_ERR(purge); + err = PTR_ERR(explode); goto err_purge; } From 3b765c0b765d2cc03ef02276f1af2658a03b3ced Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:53 -0800 Subject: [PATCH 083/113] drm/vblank: Data type fixes for 64-bit vblank sequences. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_vblank_count() has an u32 type returning what is a 64-bit vblank count. The effect of this is when drm_wait_vblank_ioctl() tries to widen the user space requested vblank sequence using this clipped 32-bit count(when the value is >= 2^32) as reference, the requested sequence remains a 32-bit value and gets queued like that. However, the code that checks if the requested sequence has passed compares this against the 64-bit vblank count. With drm_vblank_count() returning all bits of the vblank count, update drm_crtc_accurate_vblank_count() so that drm_crtc_arm_vblank_event() queues the correct sequence. Otherwise, this leads to prolonged waits for a vblank sequence when the current count is >=2^32. Finally, fix drm_wait_one_vblank() too. v2: Commit message fix (Keith) Squash commits (Rodrigo) Fixes: 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") Cc: Keith Packard Cc: Michel Dänzer Cc: Daniel Vetter Cc: Rodrigo Vivi Signed-off-by: Dhinakaran Pandiyan Acked-by: Daniel Vetter Reviewed-by: Keith Packard Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-1-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/drm_vblank.c | 8 ++++---- include/drm/drm_vblank.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 32d9bcf5be7f..f0d3ed5f2528 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -271,7 +271,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, store_vblank(dev, pipe, diff, t_vblank, cur_vblank); } -static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) +static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -292,11 +292,11 @@ static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) * This is mostly useful for hardware that can obtain the scanout position, but * doesn't have a hardware frame counter. */ -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - u32 vblank; + u64 vblank; unsigned long flags; WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, @@ -1055,7 +1055,7 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; int ret; - u32 last; + u64 last; if (WARN_ON(pipe >= dev->num_crtcs)) return; diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 848b463a0af5..a4c3b0a0a197 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -179,7 +179,7 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); -u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, From 734cbbf3e9234b9d6c1a71e1f3f85ed9c7f0e16b Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:54 -0800 Subject: [PATCH 084/113] drm/i915/vblank: Make the vblank counter u64 -> u32 typecast explicit Core returns a u64 vblank count and intel_crtc_get_vblank_counter() expects a 32-bit value. Make the typecast explicit to add clarity. Cc: Keith Packard Cc: Rodrigo Vivi Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-2-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 95d0e7a64773..cafb72716e14 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12078,7 +12078,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; if (!dev->max_vblank_count) - return drm_crtc_accurate_vblank_count(&crtc->base); + return (u32)drm_crtc_accurate_vblank_count(&crtc->base); return dev->driver->get_vblank_counter(dev, crtc->pipe); } From 1b29b7ca7d43be309d399c996910c04a8ba0c195 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:55 -0800 Subject: [PATCH 085/113] drm/i915: Handle 64-bit return from drm_crtc_vblank_count() 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64, store all the bits without truncating. There is no need to type cast this value down to 32-bits. Cc: Keith Packard Cc: Paulo Zanoni Cc: Rodrigo Vivi Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-3-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 960302668649..3560eb567ca7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1593,7 +1593,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused) seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); if (fbc->work.scheduled) - seq_printf(m, "FBC worker scheduled on vblank %u, now %llu\n", + seq_printf(m, "FBC worker scheduled on vblank %llu, now %llu\n", fbc->work.scheduled_vblank, drm_crtc_vblank_count(&fbc->crtc->base)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 822f50e472b6..3a222f1165af 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -723,7 +723,7 @@ struct intel_fbc { struct intel_fbc_work { bool scheduled; - u32 scheduled_vblank; + u64 scheduled_vblank; struct work_struct work; } work; From 23effc1100975a36953255c1db737f18adf8dd0d Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:56 -0800 Subject: [PATCH 086/113] drm/amdgpu: Handle 64-bit return from drm_crtc_vblank_count() 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the typecasting was implicitly done. Cc: Keith Packard Cc: Alex Deucher Cc: Harry Wentland Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Reviewed-by: Harry Wentland Acked-by: Alex Deucher for both this patch Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-4-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 38d47559f098..c2fa5d55f04e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -207,7 +207,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, amdgpu_bo_unreserve(new_abo); work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(dev, work->crtc_id); /* we borrow the event spin lock for protecting flip_wrok */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1ce4c98385e3..b7254a29b34a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3836,7 +3836,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, /* Prepare wait for target vblank early - before the fence-waits */ - target_vblank = target - drm_crtc_vblank_count(crtc) + + target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id); /* TODO This might fail and hence better not used, wait @@ -3982,7 +3982,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank, + (uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank, dm_state->context); } From 9038aa480d34c1f87dccd4afb944bb3c7cce8ec7 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:57 -0800 Subject: [PATCH 087/113] drm/radeon: Handle 64-bit return from drm_crtc_vblank_count() 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the implicit typecasting was already correct. Cc: Keith Packard Cc: Alex Deucher Cc: Harry Wentland Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Acked-by: Alex Deucher Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-5-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index dfda5e0ed166..26129b2b082d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -570,7 +570,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, base &= ~7; } work->base = base; - work->target_vblank = target - drm_crtc_vblank_count(crtc) + + work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + dev->driver->get_vblank_counter(dev, work->crtc_id); /* We borrow the event spin lock for protecting flip_work */ From 3abe241337993a1e358a67427518af0162c4b769 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:58 -0800 Subject: [PATCH 088/113] drm/tegra: Handle 64-bit return from drm_crtc_vblank_count() 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. This could cause potential problems if the return value is used in arithmetic operations with a 32-bit reference HW vblank count. Explicitly typecasting this down to u32 either fixes a potential problem or serves to add clarity in case the implicit typecasting was already correct. Cc: Keith Packard Cc: Thierry Reding Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Acked-by: Thierry Reding Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-6-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/tegra/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b8403ed48285..49df2db2ad46 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1359,7 +1359,7 @@ static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc) return host1x_syncpt_read(dc->syncpt); /* fallback to software emulated VBLANK counter */ - return drm_crtc_vblank_count(&dc->base); + return (u32)drm_crtc_vblank_count(&dc->base); } static int tegra_dc_enable_vblank(struct drm_crtc *crtc) From f4c0468e4bd64b7cd00e2db309925728fc72bf8b Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:12:59 -0800 Subject: [PATCH 089/113] drm/atomic: Handle 64-bit return from drm_crtc_vblank_count() 570e86963a51 ("drm: Widen vblank count to 64-bits [v3]") changed the return type for drm_crtc_vblank_count() to u64. The flip ioctl receives a 32-bit target sequence from user space and is compared against the current sequence from drm_crtc_vblank_count(). So, typecast return from drm_crtc_vblank_count() explicitly to add clarity. __drm_crtcs_state.last_vblank_count however only ever stores the value from drm_crtc_vblank_count() and can be upgraded to u64. Cc: Keith Packard Cc: Rodrigo Vivi Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Keith Packard Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-7-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/drm_plane.c | 2 +- include/drm/drm_atomic.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 2c90519576a3..c3419ee09ff0 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -944,7 +944,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (r) return r; - current_vblank = drm_crtc_vblank_count(crtc); + current_vblank = (u32)drm_crtc_vblank_count(crtc); switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) { case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE: diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 1c27526c499e..6649baa19b65 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -145,7 +145,7 @@ struct __drm_crtcs_state { struct drm_crtc *ptr; struct drm_crtc_state *state, *old_state, *new_state; s32 __user *out_fence_ptr; - unsigned last_vblank_count; + u64 last_vblank_count; }; struct __drm_connnectors_state { From 68036b08b91bc491ccc308f902616a570a49227c Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:13:00 -0800 Subject: [PATCH 090/113] drm/vblank: Do not update vblank count if interrupts are already disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updating vblank counts requires register reads and these reads may not return meaningful values if the device was in a low power state after vblank interrupts were last disabled. So, update the count only if vblank interrupts are enabled. Secondly, this means the registers should be read before disabling vblank interrupts. v2: Don't check vblank->enabled outside it's lock (Chris) Cc: Chris Wilson Cc: Daniel Vetter Cc: Michel Dänzer Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Acked-by: Daniel Vetter Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-8-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/drm_vblank.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index f0d3ed5f2528..913954765d9e 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -347,23 +347,25 @@ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) spin_lock_irqsave(&dev->vblank_time_lock, irqflags); /* - * Only disable vblank interrupts if they're enabled. This avoids - * calling the ->disable_vblank() operation in atomic context with the - * hardware potentially runtime suspended. + * Update vblank count and disable vblank interrupts only if the + * interrupts were enabled. This avoids calling the ->disable_vblank() + * operation in atomic context with the hardware potentially runtime + * suspended. */ - if (vblank->enabled) { - __disable_vblank(dev, pipe); - vblank->enabled = false; - } + if (!vblank->enabled) + goto out; /* - * Always update the count and timestamp to maintain the + * Update the count and timestamp to maintain the * appearance that the counter has been ticking all along until * this time. This makes the count account for the entire time * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). */ drm_update_vblank_count(dev, pipe, false); + __disable_vblank(dev, pipe); + vblank->enabled = false; +out: spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } From d0bb96b4be69feea97f16de5306c35e280658931 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:13:01 -0800 Subject: [PATCH 091/113] drm/vblank: Restoring vblank counts after device PM events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HW frame counter can get reset if device enters a low power state after vblank interrupts were disabled. This messes up any following vblank count update as a negative diff (huge unsigned diff) is calculated from the HW frame counter change. We cannot ignore negative diffs altogther as there could be legitimate wrap arounds. So, allow drivers to update vblank->count with missed vblanks for the time interrupts were disabled. This is similar to _crtc_vblank_on() except that vblanks interrupts are not enabled at the end as this function is expected to be called from the driver _enable_vblank() vfunc. v2: drm_crtc_vblank_restore should take crtc as arg. (Chris) Add docs and sprinkle some asserts. Cc: Daniel Vetter Cc: Chris Wilson Cc: Michel Dänzer Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Acked-by: Daniel Vetter Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-9-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/drm_vblank.c | 59 ++++++++++++++++++++++++++++++++++++ include/drm/drm_vblank.h | 2 ++ 2 files changed, 61 insertions(+) diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 913954765d9e..c781cb426bf1 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -1237,6 +1237,65 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_crtc_vblank_on); +/** + * drm_vblank_restore - estimated vblanks using timestamps and update it. + * + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last &drm_crtc_funcs.disable_vblank. + * + * This function is the legacy version of drm_crtc_vblank_restore(). + */ +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) +{ + ktime_t t_vblank; + struct drm_vblank_crtc *vblank; + int framedur_ns; + u64 diff_ns; + u32 cur_vblank, diff = 1; + int count = DRM_TIMESTAMP_MAXRETRIES; + + if (WARN_ON(pipe >= dev->num_crtcs)) + return; + + assert_spin_locked(&dev->vbl_lock); + assert_spin_locked(&dev->vblank_time_lock); + + vblank = &dev->vblank[pipe]; + WARN_ONCE((drm_debug & DRM_UT_VBL) && !vblank->framedur_ns, + "Cannot compute missed vblanks without frame duration\n"); + framedur_ns = vblank->framedur_ns; + + do { + cur_vblank = __get_vblank_counter(dev, pipe); + drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false); + } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); + + diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); + if (framedur_ns) + diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); + + + DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n", + diff, diff_ns, framedur_ns, cur_vblank - vblank->last); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); +} +EXPORT_SYMBOL(drm_vblank_restore); + +/** + * drm_crtc_vblank_restore - estimate vblanks using timestamps and update it. + * Power manamement features can cause frame counter resets between vblank + * disable and enable. Drivers can then use this function in their + * &drm_crtc_funcs.enable_vblank implementation to estimate the vblanks since + * the last &drm_crtc_funcs.disable_vblank. + */ +void drm_crtc_vblank_restore(struct drm_crtc *crtc) +{ + drm_vblank_restore(crtc->dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_restore); + static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) { diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index a4c3b0a0a197..16d46e2a6854 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -180,6 +180,8 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc); void drm_crtc_vblank_reset(struct drm_crtc *crtc); void drm_crtc_vblank_on(struct drm_crtc *crtc); u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc); +void drm_vblank_restore(struct drm_device *dev, unsigned int pipe); +void drm_crtc_vblank_restore(struct drm_crtc *crtc); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, From 2e8bf223d8f51ffe98f7bc11522939e62ab79a55 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Fri, 2 Feb 2018 21:13:02 -0800 Subject: [PATCH 092/113] drm/i915: Estimate and update missed vblanks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The frame counter may have got reset between disabling and enabling vblank interrupts due to DMC putting the hardware to DC5/6 states if PSR was active. The frame counter could also have stalled if PSR was active in case there was no DMC. The frame counter resetting has a user visible impact of screen freezes. Make use of drm_vblank_restore() to compute missed vblanks for the duration in which vblank interrupts were disabled and update the vblank counter with this value as diff. There's no need to check if PSR was actually active in the interrupt disabled duration, so simplify the check to a feature check. Enabling vblank interrupts wakes up the hardware from DC5/6 and prevents it from going back again as long as the there are pending interrupts. So, we don't have to explicity disallow DC5/6 after enabling vblank interrupts to keep the counter running. This change is not applicable to CHV, as enabling interrupts does not prevent the hardware from activating PSR. v2: Added comments(Rodrigo) and rewrote commit message. Cc: Ville Syrjälä Cc: Rodrigo Vivi Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Rodrigo Vivi Acked-by: Daniel Vetter Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180203051302.9974-10-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/i915_irq.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b886bd459acc..7617826b7705 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2951,6 +2951,12 @@ static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) ilk_enable_display_irq(dev_priv, bit); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + /* Even though there is no DMC, frame counter can get stuck when + * PSR is active as no frames are generated. + */ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } @@ -2963,6 +2969,12 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + /* Even if there is no DMC, frame counter can get stuck when + * PSR is active as no frames are generated, so check only for PSR. + */ + if (HAS_PSR(dev_priv)) + drm_vblank_restore(dev, pipe); + return 0; } From e103962611b2d464be6ab596d7b3495fe7b4c132 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Thu, 15 Feb 2018 15:26:41 +0530 Subject: [PATCH 093/113] drm/i915/cnl: Fix PORT_TX_DW5/7 register address Register Address for CNL_PORT_DW5_LN0_D is 0x162E54, but current code is defining it as 0x162ED4. Similarly for CNL_PORT_DW7_LN0_D register address is defined 0x162EDC instead of 0x162E5C, fix it. Signed-off-by: Mahesh Kumar Fixes: 04416108ccea ("drm/i915/cnl: Add registers related to voltage swing sequences.") Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180215095643.3844-2-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e84993dd9886..0fc24ab3a8ca 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2034,7 +2034,7 @@ enum i915_power_well_id { #define _CNL_PORT_TX_DW5_LN0_AE 0x162454 #define _CNL_PORT_TX_DW5_LN0_B 0x162654 #define _CNL_PORT_TX_DW5_LN0_C 0x162C54 -#define _CNL_PORT_TX_DW5_LN0_D 0x162ED4 +#define _CNL_PORT_TX_DW5_LN0_D 0x162E54 #define _CNL_PORT_TX_DW5_LN0_F 0x162854 #define CNL_PORT_TX_DW5_GRP(port) _MMIO_PORT6(port, \ _CNL_PORT_TX_DW5_GRP_AE, \ @@ -2065,7 +2065,7 @@ enum i915_power_well_id { #define _CNL_PORT_TX_DW7_LN0_AE 0x16245C #define _CNL_PORT_TX_DW7_LN0_B 0x16265C #define _CNL_PORT_TX_DW7_LN0_C 0x162C5C -#define _CNL_PORT_TX_DW7_LN0_D 0x162EDC +#define _CNL_PORT_TX_DW7_LN0_D 0x162E5C #define _CNL_PORT_TX_DW7_LN0_F 0x16285C #define CNL_PORT_TX_DW7_GRP(port) _MMIO_PORT6(port, \ _CNL_PORT_TX_DW7_GRP_AE, \ From c0a51fd07b1dd50f31a413f0e7bb5e4499de2042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 16 Feb 2018 13:43:38 +0100 Subject: [PATCH 094/113] drm: move read_domains and write_domain into i915 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i915 is the only driver using those fields in the drm_gem_object structure, so they only waste memory for all other drivers. Move the fields into drm_i915_gem_object instead and patch the i915 code with the following sed commands: sed -i "s/obj->base.read_domains/obj->read_domains/g" drivers/gpu/drm/i915/*.c drivers/gpu/drm/i915/*/*.c sed -i "s/obj->base.write_domain/obj->write_domain/g" drivers/gpu/drm/i915/*.c drivers/gpu/drm/i915/*/*.c Change is only compile tested. v2: move fields around as suggested by Chris. Signed-off-by: Christian König Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180216124338.9087-1-christian.koenig@amd.com Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/gvt/dmabuf.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_gem.c | 60 +++++++++---------- drivers/gpu/drm/i915/i915_gem_clflush.c | 2 +- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 4 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 10 ++-- drivers/gpu/drm/i915/i915_gem_internal.c | 4 +- drivers/gpu/drm/i915/i915_gem_object.h | 15 +++++ drivers/gpu/drm/i915/i915_gem_stolen.c | 2 +- drivers/gpu/drm/i915/i915_gem_userptr.c | 4 +- drivers/gpu/drm/i915/i915_gpu_error.c | 4 +- .../gpu/drm/i915/selftests/huge_gem_object.c | 4 +- drivers/gpu/drm/i915/selftests/huge_pages.c | 8 +-- .../gpu/drm/i915/selftests/i915_gem_context.c | 4 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 4 +- include/drm/drm_gem.h | 15 ----- 16 files changed, 74 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 2ab584f97dfb..de3e076dcb31 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -162,8 +162,8 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev, info->size << PAGE_SHIFT); i915_gem_object_init(obj, &intel_vgpu_gem_ops); - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = 0; if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { unsigned int tiling_mode = 0; unsigned int stride = 0; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3560eb567ca7..0cbe154e517d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -150,8 +150,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) get_global_flag(obj), get_pin_mapped_flag(obj), obj->base.size / 1024, - obj->base.read_domains, - obj->base.write_domain, + obj->read_domains, + obj->write_domain, i915_cache_level_str(dev_priv, obj->cache_level), obj->mm.dirty ? " dirty" : "", obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fc68b35854df..f530cd247724 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -240,8 +240,8 @@ err_phys: static void __start_cpu_write(struct drm_i915_gem_object *obj) { - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; if (cpu_write_needs_clflush(obj)) obj->cache_dirty = true; } @@ -257,7 +257,7 @@ __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj, obj->mm.dirty = false; if (needs_clflush && - (obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 && + (obj->read_domains & I915_GEM_DOMAIN_CPU) == 0 && !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ)) drm_clflush_sg(pages); @@ -703,10 +703,10 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) struct drm_i915_private *dev_priv = to_i915(obj->base.dev); struct i915_vma *vma; - if (!(obj->base.write_domain & flush_domains)) + if (!(obj->write_domain & flush_domains)) return; - switch (obj->base.write_domain) { + switch (obj->write_domain) { case I915_GEM_DOMAIN_GTT: i915_gem_flush_ggtt_writes(dev_priv); @@ -731,7 +731,7 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) break; } - obj->base.write_domain = 0; + obj->write_domain = 0; } static inline int @@ -831,7 +831,7 @@ int i915_gem_obj_prepare_shmem_read(struct drm_i915_gem_object *obj, * anyway again before the next pread happens. */ if (!obj->cache_dirty && - !(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) + !(obj->read_domains & I915_GEM_DOMAIN_CPU)) *needs_clflush = CLFLUSH_BEFORE; out: @@ -890,7 +890,7 @@ int i915_gem_obj_prepare_shmem_write(struct drm_i915_gem_object *obj, * Same trick applies to invalidate partially written * cachelines read before writing. */ - if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) + if (!(obj->read_domains & I915_GEM_DOMAIN_CPU)) *needs_clflush |= CLFLUSH_BEFORE; } @@ -2391,8 +2391,8 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * wasn't in the GTT, there shouldn't be any way it could have been in * a GPU cache */ - GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); - GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); + GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) @@ -3703,7 +3703,7 @@ static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) flush_write_domain(obj, ~I915_GEM_DOMAIN_CPU); if (obj->cache_dirty) i915_gem_clflush_object(obj, I915_CLFLUSH_FORCE); - obj->base.write_domain = 0; + obj->write_domain = 0; } void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) @@ -3740,7 +3740,7 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write) if (ret) return ret; - if (obj->base.write_domain == I915_GEM_DOMAIN_WC) + if (obj->write_domain == I915_GEM_DOMAIN_WC) return 0; /* Flush and acquire obj->pages so that we are coherent through @@ -3761,17 +3761,17 @@ i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write) * coherent writes from the GPU, by effectively invalidating the * WC domain upon first access. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_WC) == 0) + if ((obj->read_domains & I915_GEM_DOMAIN_WC) == 0) mb(); /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_WC) != 0); - obj->base.read_domains |= I915_GEM_DOMAIN_WC; + GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_WC) != 0); + obj->read_domains |= I915_GEM_DOMAIN_WC; if (write) { - obj->base.read_domains = I915_GEM_DOMAIN_WC; - obj->base.write_domain = I915_GEM_DOMAIN_WC; + obj->read_domains = I915_GEM_DOMAIN_WC; + obj->write_domain = I915_GEM_DOMAIN_WC; obj->mm.dirty = true; } @@ -3803,7 +3803,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) if (ret) return ret; - if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) + if (obj->write_domain == I915_GEM_DOMAIN_GTT) return 0; /* Flush and acquire obj->pages so that we are coherent through @@ -3824,17 +3824,17 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) * coherent writes from the GPU, by effectively invalidating the * GTT domain upon first access. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) + if ((obj->read_domains & I915_GEM_DOMAIN_GTT) == 0) mb(); /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); - obj->base.read_domains |= I915_GEM_DOMAIN_GTT; + GEM_BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; if (write) { - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = I915_GEM_DOMAIN_GTT; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; obj->mm.dirty = true; } @@ -4146,7 +4146,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - obj->base.read_domains |= I915_GEM_DOMAIN_GTT; + obj->read_domains |= I915_GEM_DOMAIN_GTT; return vma; @@ -4199,15 +4199,15 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) flush_write_domain(obj, ~I915_GEM_DOMAIN_CPU); /* Flush the CPU cache if it's still invalid. */ - if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) { + if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { i915_gem_clflush_object(obj, I915_CLFLUSH_SYNC); - obj->base.read_domains |= I915_GEM_DOMAIN_CPU; + obj->read_domains |= I915_GEM_DOMAIN_CPU; } /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - GEM_BUG_ON(obj->base.write_domain & ~I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain & ~I915_GEM_DOMAIN_CPU); /* If we're writing through the CPU, then the GPU read domains will * need to be invalidated at next use. @@ -4643,8 +4643,8 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) i915_gem_object_init(obj, &i915_gem_object_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; if (HAS_LLC(dev_priv)) /* On some devices, we can have the GPU use the LLC (the CPU @@ -5702,7 +5702,7 @@ i915_gem_object_create_from_data(struct drm_i915_private *dev_priv, if (IS_ERR(obj)) return obj; - GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); file = obj->base.filp; offset = 0; diff --git a/drivers/gpu/drm/i915/i915_gem_clflush.c b/drivers/gpu/drm/i915/i915_gem_clflush.c index b9b53ac14176..f5c570d35b2a 100644 --- a/drivers/gpu/drm/i915/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/i915_gem_clflush.c @@ -177,7 +177,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, } else if (obj->mm.pages) { __i915_do_clflush(obj); } else { - GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU); } obj->cache_dirty = false; diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 864439a214c8..69a7aec49e84 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -330,8 +330,8 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, * write-combined buffer or a delay through the chipset for GTT * writes that do require us to treat GTT as a separate cache domain.) */ - obj->base.read_domains = I915_GEM_DOMAIN_GTT; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT; + obj->write_domain = 0; return &obj->base; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ed6e9db51e67..51f3c32c64bf 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1073,7 +1073,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, u32 *cmd; int err; - GEM_BUG_ON(vma->obj->base.write_domain & I915_GEM_DOMAIN_CPU); + GEM_BUG_ON(vma->obj->write_domain & I915_GEM_DOMAIN_CPU); obj = i915_gem_batch_pool_get(&eb->engine->batch_pool, PAGE_SIZE); if (IS_ERR(obj)) @@ -1861,16 +1861,16 @@ void i915_vma_move_to_active(struct i915_vma *vma, i915_gem_active_set(&vma->last_read[idx], req); list_move_tail(&vma->vm_link, &vma->vm->active_list); - obj->base.write_domain = 0; + obj->write_domain = 0; if (flags & EXEC_OBJECT_WRITE) { - obj->base.write_domain = I915_GEM_DOMAIN_RENDER; + obj->write_domain = I915_GEM_DOMAIN_RENDER; if (intel_fb_obj_invalidate(obj, ORIGIN_CS)) i915_gem_active_set(&obj->frontbuffer_write, req); - obj->base.read_domains = 0; + obj->read_domains = 0; } - obj->base.read_domains |= I915_GEM_GPU_DOMAINS; + obj->read_domains |= I915_GEM_GPU_DOMAINS; if (flags & EXEC_OBJECT_NEEDS_FENCE) i915_gem_active_set(&vma->last_fence, req); diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index 8301c06c952f..0d0144b2104c 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -201,8 +201,8 @@ i915_gem_object_create_internal(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &i915_gem_object_internal_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h index 05e89e1c0a08..ca2b3b62569d 100644 --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -148,6 +148,21 @@ struct drm_i915_gem_object { #define I915_BO_CACHE_COHERENT_FOR_WRITE BIT(1) unsigned int cache_dirty:1; + /** + * @read_domains: Read memory domains. + * + * These monitor which caches contain read/write data related to the + * object. When transitioning from one set of domains to another, + * the driver is called to ensure that caches are suitably flushed and + * invalidated. + */ + u16 read_domains; + + /** + * @write_domain: Corresponding unique write memory domain. + */ + u16 write_domain; + atomic_t frontbuffer_bits; unsigned int frontbuffer_ggtt_origin; /* write once */ struct i915_gem_active frontbuffer_write; diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f18da9e2be8e..62aa67960bf4 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -516,7 +516,7 @@ _i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, i915_gem_object_init(obj, &i915_gem_object_stolen_ops); obj->stolen = stolen; - obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; + obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; cache_level = HAS_LLC(dev_priv) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 1f9d24021cbb..d596a8302ca3 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -798,8 +798,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, drm_gem_private_object_init(dev, &obj->base, args->user_size); i915_gem_object_init(obj, &i915_gem_userptr_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC); obj->userptr.ptr = args->user_ptr; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 161d9103a65e..65c0bef73ee5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1021,8 +1021,8 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->engine = __active_get_engine_id(&obj->frontbuffer_write); err->gtt_offset = vma->node.start; - err->read_domains = obj->base.read_domains; - err->write_domain = obj->base.write_domain; + err->read_domains = obj->read_domains; + err->write_domain = obj->write_domain; err->fence_reg = vma->fence ? vma->fence->id : -1; err->tiling = i915_gem_object_get_tiling(obj); err->dirty = obj->mm.dirty; diff --git a/drivers/gpu/drm/i915/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/selftests/huge_gem_object.c index a2632df39173..391f3d9ffdf1 100644 --- a/drivers/gpu/drm/i915/selftests/huge_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/huge_gem_object.c @@ -129,8 +129,8 @@ huge_gem_object(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, dma_size); i915_gem_object_init(obj, &huge_ops); - obj->base.read_domains = I915_GEM_DOMAIN_CPU; - obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE; i915_gem_object_set_cache_coherency(obj, cache_level); obj->scratch = phys_size; diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 2ea69394f428..52b1bd17bf46 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -178,8 +178,8 @@ huge_pages_object(struct drm_i915_private *i915, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &huge_page_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; obj->mm.page_mask = page_mask; @@ -329,8 +329,8 @@ fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single) else i915_gem_object_init(obj, &fake_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; return obj; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 56a803d11916..6da2a2f29c54 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -215,8 +215,8 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) } i915_gem_obj_finish_shmem_access(obj); - obj->base.read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; - obj->base.write_domain = 0; + obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; + obj->write_domain = 0; return 0; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 89b6ca9b14a7..f7dc926f4ef1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -113,8 +113,8 @@ fake_dma_object(struct drm_i915_private *i915, u64 size) drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &fake_ops); - obj->base.write_domain = I915_GEM_DOMAIN_CPU; - obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->read_domains = I915_GEM_DOMAIN_CPU; obj->cache_level = I915_CACHE_NONE; /* Preallocate the "backing storage" */ diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 9c55c2acaa2b..3583b98a1718 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -115,21 +115,6 @@ struct drm_gem_object { */ int name; - /** - * @read_domains: - * - * Read memory domains. These monitor which caches contain read/write data - * related to the object. When transitioning from one set of domains - * to another, the driver is called to ensure that caches are suitably - * flushed and invalidated. - */ - uint32_t read_domains; - - /** - * @write_domain: Corresponding unique write memory domain. - */ - uint32_t write_domain; - /** * @dma_buf: * From 339ccd35b42cb679b1a218fdbac4c029058c671c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 16:25:53 +0000 Subject: [PATCH 095/113] drm/i915: Assert that we always complete a submission to guc/execlists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The continual resubmission model for execlists (and emulated over guc) requires that we keep feeding requests into the HW in order to generate more CS interrupts to drain the rest of the queue. Add a couple of asserts to ensure that we don't skip a cycle and come to a grinding halt. Signed-off-by: Chris Wilson Cc: Michał Winiarski Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180215162553.23348-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_guc_submission.c | 6 ++++++ drivers/gpu/drm/i915/intel_lrc.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index b43b58cc599b..946766b62459 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -747,6 +747,12 @@ done: execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); guc_submit(engine); } + + /* We must always keep the beast fed if we have work piled up */ + GEM_BUG_ON(port_isset(execlists->port) && + !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); + GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); + unlock: spin_unlock_irq(&engine->timeline->lock); } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c2c8380a0121..6fbe1a8a37ad 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -642,6 +642,12 @@ done: execlists->first = rb; if (submit) port_assign(port, last); + + /* We must always keep the beast fed if we have work piled up */ + GEM_BUG_ON(port_isset(execlists->port) && + !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); + GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); + unlock: spin_unlock_irq(&engine->timeline->lock); From d081e021fd62497412f8c0c16ea6644cc7d4a154 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 16 Feb 2018 15:32:10 +0000 Subject: [PATCH 096/113] drm/i915/execlists: Remove too early assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't assert that the execlists are active before we set the flag. So perform the assert after we are expected to have marked the execlists active. Fixes: 339ccd35b42c ("drm/i915: Assert that we always complete a submission to guc/execlists") Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Mika Kuoppala Acked-by: Tomi Sarvela Link: https://patchwork.freedesktop.org/patch/msgid/20180216153210.30551-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6fbe1a8a37ad..9b6d781b22ec 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -644,8 +644,6 @@ done: port_assign(port, last); /* We must always keep the beast fed if we have work piled up */ - GEM_BUG_ON(port_isset(execlists->port) && - !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); GEM_BUG_ON(execlists->first && !port_isset(execlists->port)); unlock: @@ -655,6 +653,9 @@ unlock: execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); execlists_submit_ports(engine); } + + GEM_BUG_ON(port_isset(execlists->port) && + !execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); } void From bd67a8c15a3b59ea9b21aee31e867c728661977d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 15 Feb 2018 10:14:25 +0100 Subject: [PATCH 097/113] drm/i915: Release connector iterator on a digital port conflict. Hitting the failure path through check_digital_port_conflicts triggers: ================================================ WARNING: lock held when returning to user space! 4.16.0-rc1-CI-kasan_1+ #1 Tainted: G W ------------------------------------------------ kms_3d/1439 is leaving the kernel with locks still held! 1 lock held by kms_3d/1439: #0: (drm_connector_list_iter){.+.+}, at: [<000000003745d183>] intel_atomic_check+0x1d9d/0x3ff0 [i915] Rearrange the code to have a single exit path through the unlock. Signed-off-by: Maarten Lankhorst Reported-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180215091425.42364-1-maarten.lankhorst@linux.intel.com Reviewed-by: Chris Wilson Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cafb72716e14..3c479e3fd553 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10705,6 +10705,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) struct drm_connector_list_iter conn_iter; unsigned int used_ports = 0; unsigned int used_mst_ports = 0; + bool ret = true; /* * Walk the connector list instead of the encoder @@ -10739,7 +10740,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) /* the same port mustn't appear more than once */ if (used_ports & port_mask) - return false; + ret = false; used_ports |= port_mask; break; @@ -10757,7 +10758,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) if (used_ports & used_mst_ports) return false; - return true; + return ret; } static void From 41e1bd56487059f511a172db943c5791e2302bb2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 16 Feb 2018 11:48:20 -0200 Subject: [PATCH 098/113] drm: intel_dpio_phy: fix kernel-doc comments at nested struct The in-lined comments for channel.port doesn't follow the syntax described at kernel-doc document, causing the following warning: $ ./scripts/kernel-doc -none drivers/gpu/drm/i915/intel_dpio_phy.c drivers/gpu/drm/i915/intel_dpio_phy.c:154: warning: Function parameter or member 'channel.port' not described in 'bxt_ddi_phy_info' While the best would be for the Kernel to deduce that from the context, supporting it is not trivial. So, let's just stick with the existing syntax. [Jani: depends on "scripts: kernel-doc: support in-line comments on nested structs/unions" to actually fix the warning.] Reported-by: Chris Wilson Reported-by: Jani Nikula Tested-by: Jani Nikula Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/9ba9ac773f4f9e60770bd9169b0e46ac974d858a.1518788761.git.mchehab@s-opensource.com --- drivers/gpu/drm/i915/intel_dpio_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 76473e9836c6..c8e9e44e5981 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -147,7 +147,7 @@ struct bxt_ddi_phy_info { */ struct { /** - * @port: which port maps to this channel. + * @channel.port: which port maps to this channel. */ enum port port; } channel[2]; From acb79148dc69217c3aa5773a4e87b73d62d2f2a1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 19 Feb 2018 12:50:46 +0000 Subject: [PATCH 099/113] drm/i915: Remove WARN_ONCE for failing to pm_runtime_if_in_use As the driver is called to handle circumstances beyond it's control, we cannot assume that the pm_runtime core is happy to see us. For example, if we are called from shrink_slab to free up our pages during suspend, rpm may be disabled and pm_runtime_if_in_use() decides to fail with -EINVAL rather than simply say no. This is expected to happen, so don't warn. For example, [ 217.429228] Suspending console(s) (use no_console_suspend to debug) [ 217.557179] sd 0:0:0:0: [sda] Synchronizing SCSI cache [ 217.559399] sd 0:0:0:0: [sda] Stopping disk [ 218.661567] i915 0000:00:02.0: Resetting chip after gpu hang [ 219.523879] ------------[ cut here ]------------ [ 219.524474] pm_runtime_get_if_in_use() failed: -22 [ 219.524817] WARNING: CPU: 1 PID: 14 at drivers/gpu/drm/i915/intel_runtime_pm.c:3351 intel_runtime_pm_get_if_in_use+0xe3/0x150 [i915] [ 219.524836] Modules linked in: vgem i915 snd_hda_codec_realtek snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec r8169 lpc_ich snd_hwdep mii snd_hda_core snd_pcm prime_numbers [ 219.525054] CPU: 1 PID: 14 Comm: cpuhp/1 Tainted: G U 4.16.0-rc1-g740f57c54ecf-kasan_6+ #1 [ 219.525070] Hardware name: /D510MO, BIOS MOPNV10J.86A.0311.2010.0802.2346 08/02/2010 [ 219.525294] RIP: 0010:intel_runtime_pm_get_if_in_use+0xe3/0x150 [i915] [ 219.525313] RSP: 0018:ffff880018f5edf8 EFLAGS: 00010286 [ 219.525344] RAX: dffffc0000000008 RBX: ffff880007fc0000 RCX: 0000000000000000 [ 219.525361] RDX: 0000000000000001 RSI: ffffffff850609c0 RDI: ffffffff872992a0 [ 219.525377] RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 [ 219.525394] R10: 0000000000000000 R11: 0000000000000000 R12: ffff880007fc0000 [ 219.525411] R13: ffff880018f5f0f8 R14: ffff880007fc8de8 R15: ffff880018f5f0f0 [ 219.525429] FS: 0000000000000000(0000) GS:ffff880019c80000(0000) knlGS:0000000000000000 [ 219.525446] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 219.525463] CR2: 0000564df7897e86 CR3: 0000000000d7c000 CR4: 00000000000006e0 [ 219.525478] Call Trace: [ 219.525734] i915_gem_shrink+0x841/0xb50 [i915] [ 219.525802] ? debug_check_no_locks_freed+0x2a0/0x2a0 [ 219.525842] ? trace_hardirqs_on_thunk+0x1a/0x1c [ 219.526083] ? i915_gem_shrinker_count+0x2f0/0x2f0 [i915] [ 219.526131] ? lock_acquire+0x138/0x3c0 [ 219.526157] ? lock_acquire+0x138/0x3c0 [ 219.526391] ? shrinker_lock+0x49/0x210 [i915] [ 219.526465] ? mutex_trylock+0x15c/0x1a0 [ 219.526694] ? shrinker_lock+0x49/0x210 [i915] [ 219.526969] ? i915_gem_shrinker_scan+0xc4/0x320 [i915] [ 219.527200] i915_gem_shrinker_scan+0xc4/0x320 [i915] [ 219.527448] ? i915_gem_shrinker_vmap+0x3a0/0x3a0 [i915] [ 219.527533] shrink_slab.part.18+0x2d0/0x8d0 [ 219.527613] ? unregister_shrinker+0x1f0/0x1f0 [ 219.527668] ? mem_cgroup_iter+0x37d/0xc50 [ 219.527728] shrink_node+0x882/0xbe0 [ 219.527847] ? shrink_node_memcg+0x11c0/0x11c0 [ 219.527882] ? mark_held_locks+0xa8/0xf0 [ 219.527931] ? trace_hardirqs_on_caller+0x33f/0x590 [ 219.527961] ? ktime_get+0xad/0x140 [ 219.528015] do_try_to_free_pages+0x2d3/0xd70 [ 219.528099] ? allow_direct_reclaim.part.23+0x1d0/0x1d0 [ 219.528132] ? shrink_node+0xbe0/0xbe0 [ 219.528213] try_to_free_pages+0x1cd/0x570 [ 219.528257] ? do_try_to_free_pages+0xd70/0xd70 [ 219.528355] __alloc_pages_nodemask+0xadf/0x2110 [ 219.528423] ? unwind_next_frame+0x870/0x1970 [ 219.528465] ? deref_stack_reg+0x97/0xc0 [ 219.528503] ? gfp_pfmemalloc_allowed+0x150/0x150 [ 219.528539] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.528588] ? unwind_next_frame+0x138/0x1970 [ 219.528619] ? kthread+0x30a/0x3d0 [ 219.528677] ? __read_once_size_nocheck.constprop.4+0x10/0x10 [ 219.528698] ? deref_stack_reg+0xc0/0xc0 [ 219.528762] ? __save_stack_trace+0x6e/0xd0 [ 219.528822] depot_save_stack+0x3bc/0x430 [ 219.528870] kasan_kmalloc+0x142/0x170 [ 219.528912] ? __kmalloc+0xf7/0x340 [ 219.528935] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.528957] ? partition_sched_domains+0x4d4/0x840 [ 219.528978] ? sched_cpu_deactivate+0x11b/0x150 [ 219.529001] ? cpuhp_invoke_callback+0x160/0x15f0 [ 219.529023] ? cpuhp_thread_fun+0x35e/0x710 [ 219.529044] ? smpboot_thread_fn+0x50a/0x7f0 [ 219.529065] ? kthread+0x30a/0x3d0 [ 219.529086] ? ret_from_fork+0x24/0x50 [ 219.529141] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529169] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529198] ? set_track+0x87/0x100 [ 219.529225] ? init_object+0x6e/0x80 [ 219.529275] ? ___slab_alloc.constprop.36+0x232/0x3e0 [ 219.529303] ? ___slab_alloc.constprop.36+0x232/0x3e0 [ 219.529325] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529410] ? mark_held_locks+0xa8/0xf0 [ 219.529453] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529479] ? trace_hardirqs_on_caller+0x33f/0x590 [ 219.529532] __kmalloc+0xf7/0x340 [ 219.529557] ? register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529604] register_sched_domain_sysctl+0x23a/0x1b90 [ 219.529684] ? sched_debug_show+0x20/0x20 [ 219.529713] ? debug_object_activate+0x530/0x530 [ 219.529771] ? rcu_lockdep_current_cpu_online+0xdc/0x130 [ 219.529802] ? partition_sched_domains+0x4ae/0x840 [ 219.529825] ? rcu_read_lock_sched_held+0x10f/0x130 [ 219.529875] partition_sched_domains+0x4d4/0x840 [ 219.529955] ? sched_init_domains+0x110/0x110 [ 219.529981] ? __wait_rcu_gp+0x24f/0x390 [ 219.530054] sched_cpu_deactivate+0x11b/0x150 [ 219.530086] ? sched_cpu_activate+0x1e0/0x1e0 [ 219.530112] ? __call_rcu.constprop.53+0x680/0x680 [ 219.530132] ? call_rcu_bh+0x10/0x10 [ 219.530166] ? debug_check_no_locks_freed+0x2a0/0x2a0 [ 219.530201] ? trace_raw_output_rcu_utilization+0xa0/0xa0 [ 219.530267] ? trace_raw_output_rcu_utilization+0xa0/0xa0 [ 219.530337] ? rcu_lockdep_current_cpu_online+0xdc/0x130 [ 219.530370] ? sched_cpu_activate+0x1e0/0x1e0 [ 219.530397] cpuhp_invoke_callback+0x160/0x15f0 [ 219.530424] ? lock_acquire+0x138/0x3c0 [ 219.530445] ? lock_acquire+0x138/0x3c0 [ 219.530471] ? cpuhp_thread_fun+0xaf/0x710 [ 219.530507] ? pci_mmcfg_check_reserved+0x100/0x100 [ 219.530565] cpuhp_thread_fun+0x35e/0x710 [ 219.530618] ? cpuhp_complete_idle_dead+0x10/0x10 [ 219.530639] smpboot_thread_fn+0x50a/0x7f0 [ 219.530678] ? sort_range+0x20/0x20 [ 219.530709] ? __kthread_parkme+0xba/0x1f0 [ 219.530739] ? schedule+0x84/0x1a0 [ 219.530768] ? __kthread_parkme+0xbf/0x1f0 [ 219.530805] ? sort_range+0x20/0x20 [ 219.530831] kthread+0x30a/0x3d0 [ 219.530859] ? _kthread_create_on_node+0xb0/0xb0 [ 219.530900] ret_from_fork+0x24/0x50 [ 219.530999] Code: 01 00 00 00 85 c0 74 4a 89 e8 5b 5d c3 80 3d 48 37 4e 00 00 75 f2 89 c6 48 c7 c7 40 f0 61 c0 c6 05 36 37 4e 00 01 e8 ed 2a e1 c2 <0f> ff eb d9 80 3d 3f 37 4e 00 00 75 94 48 c7 c7 60 e8 61 c0 c6 [ 219.531880] ---[ end trace 18ec0139488ea0c8 ]--- [ 219.607967] IRQ 16: no longer affine to CPU1 [ 219.670291] IRQ 24: no longer affine to CPU2 [ 219.701489] IRQ 8: no longer affine to CPU3 [ 219.701529] IRQ 9: no longer affine to CPU3 [ 219.701582] IRQ 18: no longer affine to CPU3 [ 219.701640] IRQ 25: no longer affine to CPU3 [ 219.743857] cache: parent cpu1 should not be sleeping [ 219.784549] cache: parent cpu2 should not be sleeping [ 219.816041] cache: parent cpu3 should not be sleeping v2: Add Returns: information to intel_runtime_pm_get_if_in_use() kerneldoc. Signed-off-by: Chris Wilson Cc: Imre Deak Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20180219125046.19363-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_runtime_pm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 16790f2576ec..b7924feb9f27 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -3328,18 +3328,19 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) * @dev_priv: i915 device instance * * This function grabs a device-level runtime pm reference if the device is - * already in use and ensures that it is powered up. + * already in use and ensures that it is powered up. It is illegal to try + * and access the HW should intel_runtime_pm_get_if_in_use() report failure. * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put() to release the reference again. + * + * Returns: True if the wakeref was acquired, or False otherwise. */ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev_priv->drm.pdev; - struct device *kdev = &pdev->dev; - if (IS_ENABLED(CONFIG_PM)) { - int ret = pm_runtime_get_if_in_use(kdev); + struct pci_dev *pdev = dev_priv->drm.pdev; + struct device *kdev = &pdev->dev; /* * In cases runtime PM is disabled by the RPM core and we get @@ -3347,9 +3348,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) * function, since the power state is undefined. This applies * atm to the late/early system suspend/resume handlers. */ - WARN_ONCE(ret < 0, - "pm_runtime_get_if_in_use() failed: %d\n", ret); - if (ret <= 0) + if (pm_runtime_get_if_in_use(kdev) <= 0) return false; } From f0fd96f546fb9e726ff66b1e53b115ada61ebc35 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Feb 2018 07:37:12 +0000 Subject: [PATCH 100/113] drm/i915: Track GT interrupt handling using the master iir Keep the master iir and use it to reduce the number of reads and writes to the GT iir array, i.e. only the bits marked as set by the master iir are valid inside GT iir array and will be handled during the interrupt. Signed-off-by: Chris Wilson Cc: Ville Syrjala Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180215073713.26985-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 51 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7617826b7705..c7f6b719e86d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1416,6 +1416,14 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) static void gen8_gt_irq_ack(struct drm_i915_private *dev_priv, u32 master_ctl, u32 gt_iir[4]) { +#define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ + GEN8_GT_BCS_IRQ | \ + GEN8_GT_VCS1_IRQ | \ + GEN8_GT_VCS2_IRQ | \ + GEN8_GT_VECS_IRQ | \ + GEN8_GT_PM_IRQ | \ + GEN8_GT_GUC_IRQ) + if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { gt_iir[0] = I915_READ_FW(GEN8_GT_IIR(0)); if (gt_iir[0]) @@ -1446,31 +1454,34 @@ static void gen8_gt_irq_ack(struct drm_i915_private *dev_priv, } static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, - u32 gt_iir[4]) + u32 master_ctl, u32 gt_iir[4]) { - if (gt_iir[0]) { + if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { gen8_cs_irq_handler(dev_priv->engine[RCS], gt_iir[0], GEN8_RCS_IRQ_SHIFT); gen8_cs_irq_handler(dev_priv->engine[BCS], gt_iir[0], GEN8_BCS_IRQ_SHIFT); } - if (gt_iir[1]) { + if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { gen8_cs_irq_handler(dev_priv->engine[VCS], gt_iir[1], GEN8_VCS1_IRQ_SHIFT); gen8_cs_irq_handler(dev_priv->engine[VCS2], gt_iir[1], GEN8_VCS2_IRQ_SHIFT); } - if (gt_iir[3]) + if (master_ctl & GEN8_GT_VECS_IRQ) { gen8_cs_irq_handler(dev_priv->engine[VECS], gt_iir[3], GEN8_VECS_IRQ_SHIFT); + } - if (gt_iir[2] & dev_priv->pm_rps_events) - gen6_rps_irq_handler(dev_priv, gt_iir[2]); + if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { + if (gt_iir[2] & dev_priv->pm_rps_events) + gen6_rps_irq_handler(dev_priv, gt_iir[2]); - if (gt_iir[2] & dev_priv->pm_guc_events) - gen9_guc_irq_handler(dev_priv, gt_iir[2]); + if (gt_iir[2] & dev_priv->pm_guc_events) + gen9_guc_irq_handler(dev_priv, gt_iir[2]); + } } static bool bxt_port_hotplug_long_detect(enum port port, u32 val) @@ -2085,9 +2096,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) do { u32 master_ctl, iir; - u32 gt_iir[4] = {}; u32 pipe_stats[I915_MAX_PIPES] = {}; u32 hotplug_status = 0; + u32 gt_iir[4]; u32 ier = 0; master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; @@ -2140,7 +2151,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); POSTING_READ(GEN8_MASTER_IRQ); - gen8_gt_irq_handler(dev_priv, gt_iir); + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); if (hotplug_status) i9xx_hpd_irq_handler(dev_priv, hotplug_status); @@ -2675,10 +2686,9 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl) static irqreturn_t gen8_irq_handler(int irq, void *arg) { - struct drm_device *dev = arg; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(arg); u32 master_ctl; - u32 gt_iir[4] = {}; + u32 gt_iir[4]; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -2690,18 +2700,19 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) I915_WRITE_FW(GEN8_MASTER_IRQ, 0); - /* IRQs are synced during runtime_suspend, we don't require a wakeref */ - disable_rpm_wakeref_asserts(dev_priv); - /* Find, clear, then process each source of interrupt */ gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir); - gen8_gt_irq_handler(dev_priv, gt_iir); - gen8_de_irq_handler(dev_priv, master_ctl); + + /* IRQs are synced during runtime_suspend, we don't require a wakeref */ + if (master_ctl & ~GEN8_GT_IRQS) { + disable_rpm_wakeref_asserts(dev_priv); + gen8_de_irq_handler(dev_priv, master_ctl); + enable_rpm_wakeref_asserts(dev_priv); + } I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); - POSTING_READ_FW(GEN8_MASTER_IRQ); - enable_rpm_wakeref_asserts(dev_priv); + gen8_gt_irq_handler(dev_priv, master_ctl, gt_iir); return IRQ_HANDLED; } From 2e4a5b25886cde308d3fc896fd584c844bde92a2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 19 Feb 2018 10:09:26 +0000 Subject: [PATCH 101/113] drm/i915: Prune gen8_gt_irq_handler The compiler is not automatically caching the i915->regs address inside a register and emitting a load for every mmio access. For simple functions like gen8_gt_irq_handler that are already using the raw accessors, we can open-code them for substantial savings: add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-83 (-83) Function old new delta gen8_gt_irq_handler 290 266 -24 gen8_gt_irq_ack 181 122 -59 Total: Before=954637, After=954554, chg -0.01% v2: Add raw_reg_read/raw_reg_write. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180219100926.16554-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_irq.c | 60 ++++++++++++++--------------- drivers/gpu/drm/i915/intel_uncore.h | 5 +++ 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c7f6b719e86d..17de6cef2a30 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1413,9 +1413,11 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) tasklet_hi_schedule(&execlists->tasklet); } -static void gen8_gt_irq_ack(struct drm_i915_private *dev_priv, +static void gen8_gt_irq_ack(struct drm_i915_private *i915, u32 master_ctl, u32 gt_iir[4]) { + void __iomem * const regs = i915->regs; + #define GEN8_GT_IRQS (GEN8_GT_RCS_IRQ | \ GEN8_GT_BCS_IRQ | \ GEN8_GT_VCS1_IRQ | \ @@ -1425,62 +1427,58 @@ static void gen8_gt_irq_ack(struct drm_i915_private *dev_priv, GEN8_GT_GUC_IRQ) if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - gt_iir[0] = I915_READ_FW(GEN8_GT_IIR(0)); - if (gt_iir[0]) - I915_WRITE_FW(GEN8_GT_IIR(0), gt_iir[0]); + gt_iir[0] = raw_reg_read(regs, GEN8_GT_IIR(0)); + if (likely(gt_iir[0])) + raw_reg_write(regs, GEN8_GT_IIR(0), gt_iir[0]); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - gt_iir[1] = I915_READ_FW(GEN8_GT_IIR(1)); - if (gt_iir[1]) - I915_WRITE_FW(GEN8_GT_IIR(1), gt_iir[1]); - } - - if (master_ctl & GEN8_GT_VECS_IRQ) { - gt_iir[3] = I915_READ_FW(GEN8_GT_IIR(3)); - if (gt_iir[3]) - I915_WRITE_FW(GEN8_GT_IIR(3), gt_iir[3]); + gt_iir[1] = raw_reg_read(regs, GEN8_GT_IIR(1)); + if (likely(gt_iir[1])) + raw_reg_write(regs, GEN8_GT_IIR(1), gt_iir[1]); } if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { - gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2)); - if (gt_iir[2] & (dev_priv->pm_rps_events | - dev_priv->pm_guc_events)) { - I915_WRITE_FW(GEN8_GT_IIR(2), - gt_iir[2] & (dev_priv->pm_rps_events | - dev_priv->pm_guc_events)); - } + gt_iir[2] = raw_reg_read(regs, GEN8_GT_IIR(2)); + if (likely(gt_iir[2] & (i915->pm_rps_events | + i915->pm_guc_events))) + raw_reg_write(regs, GEN8_GT_IIR(2), + gt_iir[2] & (i915->pm_rps_events | + i915->pm_guc_events)); + } + + if (master_ctl & GEN8_GT_VECS_IRQ) { + gt_iir[3] = raw_reg_read(regs, GEN8_GT_IIR(3)); + if (likely(gt_iir[3])) + raw_reg_write(regs, GEN8_GT_IIR(3), gt_iir[3]); } } -static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, +static void gen8_gt_irq_handler(struct drm_i915_private *i915, u32 master_ctl, u32 gt_iir[4]) { if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) { - gen8_cs_irq_handler(dev_priv->engine[RCS], + gen8_cs_irq_handler(i915->engine[RCS], gt_iir[0], GEN8_RCS_IRQ_SHIFT); - gen8_cs_irq_handler(dev_priv->engine[BCS], + gen8_cs_irq_handler(i915->engine[BCS], gt_iir[0], GEN8_BCS_IRQ_SHIFT); } if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) { - gen8_cs_irq_handler(dev_priv->engine[VCS], + gen8_cs_irq_handler(i915->engine[VCS], gt_iir[1], GEN8_VCS1_IRQ_SHIFT); - gen8_cs_irq_handler(dev_priv->engine[VCS2], + gen8_cs_irq_handler(i915->engine[VCS2], gt_iir[1], GEN8_VCS2_IRQ_SHIFT); } if (master_ctl & GEN8_GT_VECS_IRQ) { - gen8_cs_irq_handler(dev_priv->engine[VECS], + gen8_cs_irq_handler(i915->engine[VECS], gt_iir[3], GEN8_VECS_IRQ_SHIFT); } if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) { - if (gt_iir[2] & dev_priv->pm_rps_events) - gen6_rps_irq_handler(dev_priv, gt_iir[2]); - - if (gt_iir[2] & dev_priv->pm_guc_events) - gen9_guc_irq_handler(dev_priv, gt_iir[2]); + gen6_rps_irq_handler(i915, gt_iir[2]); + gen9_guc_irq_handler(i915, gt_iir[2]); } } diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 9ce079b5dd0d..6e6b3675d0a0 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -186,4 +186,9 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv, 2, timeout_ms, NULL); } +#define raw_reg_read(base, reg) \ + readl(base + i915_mmio_reg_offset(reg)) +#define raw_reg_write(base, reg, value) \ + writel(value, base + i915_mmio_reg_offset(reg)) + #endif /* !__INTEL_UNCORE_H__ */ From ed2f3532321083cf40e4da4e36234880e0136136 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 19 Feb 2018 14:01:44 +0000 Subject: [PATCH 102/113] drm/i915: Clear the in-use marker on execbuf failure If we fail to unbind the vma (due to a signal on an active buffer that needs to be moved for the next execbuf), then we need to clear the persistent tracking state we setup for this execbuf. Fixes: c7c6e46f913b ("drm/i915: Convert execbuf to use struct-of-array packing for critical fields") Testcase: igt/gem_fenced_exec_thrash/no-spare-fences-busy* Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: # v4.14+ Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180219140144.24004-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 51f3c32c64bf..4eb28e84fda4 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -505,6 +505,8 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma) list_add_tail(&vma->exec_link, &eb->unbound); if (drm_mm_node_allocated(&vma->node)) err = i915_vma_unbind(vma); + if (unlikely(err)) + vma->exec_flags = NULL; } return err; } From be3fa66857051e2943960a06f8046e8445cdfe6e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Nov 2017 10:50:35 +0000 Subject: [PATCH 103/113] drm/i915/: Initialise trans_min for skl_compute_transition_wm() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clang spots drivers/gpu/drm/i915/intel_pm.c:4655:6: warning: variable 'trans_min' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized] if (INTEL_GEN(dev_priv) >= 10) but fortunately for us we skip the function unless on a gen10+ device. However, to keep the function generic in case we do want to re-enable it for gen9 again, initialise trans_min to 0. References: ca47667f523e ("drm/i915/gen10: Calculate and enable transition WM") Signed-off-by: Chris Wilson Cc: Mahesh Kumar Cc: Maarten Lankhorst Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20171115105036.1094-3-chris@chris-wilson.co.uk Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 158d00fdf549..a88f0f213604 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4713,6 +4713,7 @@ static void skl_compute_transition_wm(struct intel_crtc_state *cstate, if (!dev_priv->ipc_enabled) goto exit; + trans_min = 0; if (INTEL_GEN(dev_priv) >= 10) trans_min = 4; From c9c70471549a0f5956bb3da4fc2609cd567a809d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 19 Feb 2018 22:06:31 +0000 Subject: [PATCH 104/113] drm/i915: Track number of pending freed objects During igt, we frequently call into the driver to reset both HW and driver state (idling the device, waiting for it to become idle and freeing off old objects) to ensure that we start each test/subtest/pass from known state. This process incurs an RCU barrier or two to ensure that any such pending frees are indeed flushed before we return. However, unconditionally waiting on the RCU barrier adds needless delay to many callers, which adds up to several seconds when repeated thousands of times. We can skip the rcu_barrier() if by tracking how many outstanding frees we have, we know there are none. The same path is used along suspend, where we may be able to save the unconditional RCU barrier. To put it into perspective with a completely meaningless microbenchmark, igt/gem_sync/idle is improved from 50ms to 30us on bdw. v2: Remove the extra synchronize_rcu() inside i915_drop_caches_set() Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180219220631.25001-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 4 +--- drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/i915_gem.c | 7 ++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0cbe154e517d..05b41045b8f9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4079,10 +4079,8 @@ i915_drop_caches_set(void *data, u64 val) if (val & DROP_IDLE) drain_delayed_work(&dev_priv->gt.idle_work); - if (val & DROP_FREED) { - synchronize_rcu(); + if (val & DROP_FREED) i915_gem_drain_freed_objects(dev_priv); - } return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3a222f1165af..0d8cb74e7d02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1095,6 +1095,11 @@ struct i915_gem_mm { struct llist_head free_list; struct work_struct free_work; spinlock_t free_lock; + /** + * Count of objects pending destructions. Used to skip needlessly + * waiting on an RCU barrier if no objects are waiting to be freed. + */ + atomic_t free_count; /** * Small stash of WC pages @@ -3134,6 +3139,9 @@ void i915_gem_free_object(struct drm_gem_object *obj); static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915) { + if (!atomic_read(&i915->mm.free_count)) + return; + /* A single pass should suffice to release all the freed objects (along * most call paths) , but be a little more paranoid in that freeing * the objects does take a little amount of time, during which the rcu diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f530cd247724..631a2db2bb6e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4758,6 +4758,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, kfree(obj->bit_17); i915_gem_object_free(obj); + GEM_BUG_ON(!atomic_read(&i915->mm.free_count)); + atomic_dec(&i915->mm.free_count); + if (on) cond_resched(); } @@ -4846,6 +4849,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj) * i915_gem_busy_ioctl(). For the corresponding synchronized * lookup see i915_gem_object_lookup_rcu(). */ + atomic_inc(&to_i915(obj->base.dev)->mm.free_count); call_rcu(&obj->rcu, __i915_gem_free_object_rcu); } @@ -5546,7 +5550,8 @@ err_out: void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) { i915_gem_drain_freed_objects(dev_priv); - WARN_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); + GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); WARN_ON(dev_priv->mm.object_count); mutex_lock(&dev_priv->drm.struct_mutex); From aa81e2c334824d399f16e7cabe272ebf3c0e43df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 24 Jan 2018 20:36:42 +0200 Subject: [PATCH 105/113] drm/i915: Assert that we don't overflow frontbuffer tracking bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some compile time assrts to the frontbuffer tracking to make sure that we have enough bits per pipe to cover all the planes, and that we have enough total bits to cover all the planes across all pipes. We'll ignore any potential clash between the overlay bit and the plane bits because that will allow us to keep using a total of 32 bits for the foreseeable future. While at it change the macros to use BIT() and GENMASK(). The latter gets rid of the hardcoded 0xff and thus means we can change the number of bits per pipe by just changing INTEL_FRONTBUFFER_BITS_PER_PIPE. Cc: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180124183642.32549-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0d8cb74e7d02..816183da06de 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2429,12 +2429,16 @@ enum hdmi_force_audio { * We have one bit per pipe and per scanout plane type. */ #define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 -#define INTEL_FRONTBUFFER(pipe, plane_id) \ - (1 << ((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) +#define INTEL_FRONTBUFFER(pipe, plane_id) ({ \ + BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 32); \ + BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); \ + BIT((plane_id) + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)); \ +}) #define INTEL_FRONTBUFFER_OVERLAY(pipe) \ - (1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + BIT(INTEL_FRONTBUFFER_BITS_PER_PIPE - 1 + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) #define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ - (0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + GENMASK(INTEL_FRONTBUFFER_BITS_PER_PIPE * ((pipe) + 1) - 1, \ + INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)) /* * Optimised SGL iterator for GEM objects From 32ea06b67eb2b693c78bd795b8a8f7fdac03fb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 30 Jan 2018 22:38:01 +0200 Subject: [PATCH 106/113] drm/i915: Don't set cursor pipe select bits on g4x+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit G4x cursor control registers still allow us to write to the pipe select bits even though cursors are supposed to be fixed to a specific pipe. Bspec tells us that we should only ever write 0 to these bits. Let's follow that recommendation. On ilk+ the bits become hardwired to 0. Also looks like ICL repurposes these bits for some other use, so we had better stop setting them to bogus values there. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180130203807.13721-1-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/intel_display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c479e3fd553..a0d9b0ab6f25 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9540,7 +9540,8 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, if (HAS_DDI(dev_priv)) cntl |= CURSOR_PIPE_CSC_ENABLE; - cntl |= MCURSOR_PIPE_SELECT(crtc->pipe); + if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) + cntl |= MCURSOR_PIPE_SELECT(crtc->pipe); switch (plane_state->base.crtc_w) { case 64: From c154d1e0aabf77212a49f0cf3d54eecb0ae395a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 30 Jan 2018 22:38:02 +0200 Subject: [PATCH 107/113] drm/i915: Set the primary plane pipe select bits on gen4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i965 and g4x still have the pipe select bits in the plane control registers, they're just hardcoded to select a specific pipe. However plane C on i965 can still move between the pipes, thus we should program the pipe select bits on i965 if we want to expose plane C some day. Since there is no harm in programming the bits on any plane on i965/g4x let's just always set them. This will also make our pre-computed register value match what the hardware register would read, should we want to cross check the two. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180130203807.13721-2-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a0d9b0ab6f25..8cdf4dd2b334 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3163,7 +3163,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; - if (INTEL_GEN(dev_priv) < 4) + if (INTEL_GEN(dev_priv) < 5) dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe); switch (fb->format->format) { From 9171433100c4d7f1c11b5f2483778b60a0c73f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 30 Jan 2018 22:38:06 +0200 Subject: [PATCH 108/113] drm/i915: Drop WaDoubleCursorLP3Latency:ivb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WaDoubleCursorLP3Latency was meant for pre-production hardware. Drop it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180130203807.13721-6-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/intel_pm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a88f0f213604..abf80e462833 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2917,10 +2917,6 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, /* ILK cursor LP0 latency is 1300 ns */ if (IS_GEN5(dev_priv)) wm[0] = 13; - - /* WaDoubleCursorLP3Latency:ivb */ - if (IS_IVYBRIDGE(dev_priv)) - wm[3] *= 2; } int ilk_wm_max_level(const struct drm_i915_private *dev_priv) From ac87a6fd3631e43053d3dd228e96bbbf314566bf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Feb 2018 13:42:05 +0000 Subject: [PATCH 109/113] drm/i915: Also check view->type for a normal GGTT view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We cannot simply use !view as shorthand for all normal GGTT views as a few callers will always populate a i915_ggtt_view struct and set the type to NORMAL instead. So check for (!view || view->type == NORMAL) inside i915_gem_object_ggtt_pin(). Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 631a2db2bb6e..1a64e88c50e1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4282,7 +4282,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); - if (!view && flags & PIN_MAPPABLE) { + if (flags & PIN_MAPPABLE && + (!view || view->type == I915_GGTT_VIEW_NORMAL)) { /* If the required space is larger than the available * aperture, we will not able to find a slot for the * object and unbinding the object now will be in From 5935485f8eee356f6bb7b2b1cfb43d69e5c03662 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Feb 2018 13:42:06 +0000 Subject: [PATCH 110/113] drm/i915: Move the policy for placement of the GGTT vma into the caller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/i915_gem.c | 26 ++++--------- drivers/gpu/drm/i915/intel_atomic_plane.c | 1 + drivers/gpu/drm/i915/intel_display.c | 45 ++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 9 ++++- drivers/gpu/drm/i915/intel_fbdev.c | 10 +++-- drivers/gpu/drm/i915/intel_overlay.c | 3 +- 7 files changed, 62 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 816183da06de..3e1ad3f8e55d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3417,7 +3417,8 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write); struct i915_vma * __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - const struct i915_ggtt_view *view); + const struct i915_ggtt_view *view, + unsigned int flags); void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma); int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1a64e88c50e1..43afa1c1b14f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4078,7 +4078,8 @@ out: struct i915_vma * i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, u32 alignment, - const struct i915_ggtt_view *view) + const struct i915_ggtt_view *view, + unsigned int flags) { struct i915_vma *vma; int ret; @@ -4115,25 +4116,14 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, * try to preserve the existing ABI). */ vma = ERR_PTR(-ENOSPC); - if (!view || view->type == I915_GGTT_VIEW_NORMAL) + if ((flags & PIN_MAPPABLE) == 0 && + (!view || view->type == I915_GGTT_VIEW_NORMAL)) vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, - PIN_MAPPABLE | PIN_NONBLOCK); - if (IS_ERR(vma)) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - unsigned int flags; - - /* Valleyview is definitely limited to scanning out the first - * 512MiB. Lets presume this behaviour was inherited from the - * g4x display engine and that all earlier gen are similarly - * limited. Testing suggests that it is a little more - * complicated than this. For example, Cherryview appears quite - * happy to scanout from anywhere within its global aperture. - */ - flags = 0; - if (HAS_GMCH_DISPLAY(i915)) - flags = PIN_MAPPABLE; + flags | + PIN_MAPPABLE | + PIN_NONBLOCK); + if (IS_ERR(vma)) vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); - } if (IS_ERR(vma)) goto err_unpin_global; diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 57ee8b786cd8..1ce99dc978d9 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -85,6 +85,7 @@ intel_plane_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, state); intel_state->vma = NULL; + intel_state->flags = 0; return state; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8cdf4dd2b334..75baa5dab877 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2068,13 +2068,16 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, } struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation, + unsigned long *out_flags) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct i915_ggtt_view view; struct i915_vma *vma; + unsigned int pinctl; u32 alignment; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -2102,7 +2105,20 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view); + pinctl = 0; + + /* Valleyview is definitely limited to scanning out the first + * 512MiB. Lets presume this behaviour was inherited from the + * g4x display engine and that all earlier gen are similarly + * limited. Testing suggests that it is a little more + * complicated than this. For example, Cherryview appears quite + * happy to scanout from anywhere within its global aperture. + */ + if (HAS_GMCH_DISPLAY(dev_priv)) + pinctl |= PIN_MAPPABLE; + + vma = i915_gem_object_pin_to_display_plane(obj, + alignment, &view, pinctl); if (IS_ERR(vma)) goto err; @@ -2123,7 +2139,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) * something and try to run the system in a "less than optimal" * mode that matches the user configuration. */ - i915_vma_pin_fence(vma); + if (i915_vma_pin_fence(vma) == 0 && vma->fence) + *out_flags |= PLANE_HAS_FENCE; } i915_vma_get(vma); @@ -2134,11 +2151,12 @@ err: return vma; } -void intel_unpin_fb_vma(struct i915_vma *vma) +void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) { lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); - i915_vma_unpin_fence(vma); + if (flags & PLANE_HAS_FENCE) + i915_vma_unpin_fence(vma); i915_gem_object_unpin_from_display_plane(vma); i915_vma_put(vma); } @@ -2808,7 +2826,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, valid_fb: mutex_lock(&dev->struct_mutex); intel_state->vma = - intel_pin_and_fence_fb_obj(fb, primary->state->rotation); + intel_pin_and_fence_fb_obj(fb, + primary->state->rotation, + &intel_state->flags); mutex_unlock(&dev->struct_mutex); if (IS_ERR(intel_state->vma)) { DRM_ERROR("failed to pin boot fb on pipe %d: %li\n", @@ -12700,7 +12720,9 @@ intel_prepare_plane_fb(struct drm_plane *plane, } else { struct i915_vma *vma; - vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation); + vma = intel_pin_and_fence_fb_obj(fb, + new_state->rotation, + &to_intel_plane_state(new_state)->flags); if (!IS_ERR(vma)) to_intel_plane_state(new_state)->vma = vma; else @@ -12755,7 +12777,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane, vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma); if (vma) { mutex_lock(&plane->dev->struct_mutex); - intel_unpin_fb_vma(vma); + intel_unpin_fb_vma(vma, to_intel_plane_state(old_state)->flags); mutex_unlock(&plane->dev->struct_mutex); } } @@ -13111,7 +13133,9 @@ intel_legacy_cursor_update(struct drm_plane *plane, goto out_unlock; } } else { - vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation); + vma = intel_pin_and_fence_fb_obj(fb, + new_plane_state->rotation, + &to_intel_plane_state(new_plane_state)->flags); if (IS_ERR(vma)) { DRM_DEBUG_KMS("failed to pin object\n"); @@ -13142,7 +13166,8 @@ intel_legacy_cursor_update(struct drm_plane *plane, old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma); if (old_vma) - intel_unpin_fb_vma(old_vma); + intel_unpin_fb_vma(old_vma, + to_intel_plane_state(old_plane_state)->flags); out_unlock: mutex_unlock(&dev_priv->drm.struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5853d92a6512..c81be2c7b582 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -201,6 +201,7 @@ struct intel_fbdev { struct drm_fb_helper helper; struct intel_framebuffer *fb; struct i915_vma *vma; + unsigned long vma_flags; async_cookie_t cookie; int preferred_bpp; }; @@ -408,6 +409,8 @@ struct intel_plane_state { struct drm_plane_state base; struct drm_rect clip; struct i915_vma *vma; + unsigned long flags; +#define PLANE_HAS_FENCE BIT(0) struct { u32 offset; @@ -1419,8 +1422,10 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, struct intel_load_detect_pipe *old, struct drm_modeset_acquire_ctx *ctx); struct i915_vma * -intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation); -void intel_unpin_fb_vma(struct i915_vma *vma); +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation, + unsigned long *out_flags); +void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags); struct drm_framebuffer * intel_framebuffer_create(struct drm_i915_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index da48af11eb6b..3d8ce3a62743 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -177,6 +177,7 @@ static int intelfb_create(struct drm_fb_helper *helper, struct fb_info *info; struct drm_framebuffer *fb; struct i915_vma *vma; + unsigned long flags = 0; bool prealloc = false; void __iomem *vaddr; int ret; @@ -211,7 +212,9 @@ static int intelfb_create(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, DRM_MODE_ROTATE_0); + vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, + DRM_MODE_ROTATE_0, + &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; @@ -268,6 +271,7 @@ static int intelfb_create(struct drm_fb_helper *helper, DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n", fb->width, fb->height, i915_ggtt_offset(vma)); ifbdev->vma = vma; + ifbdev->vma_flags = flags; intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -275,7 +279,7 @@ static int intelfb_create(struct drm_fb_helper *helper, return 0; out_unpin: - intel_unpin_fb_vma(vma); + intel_unpin_fb_vma(vma, flags); out_unlock: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -513,7 +517,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev) if (ifbdev->vma) { mutex_lock(&ifbdev->helper.dev->struct_mutex); - intel_unpin_fb_vma(ifbdev->vma); + intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags); mutex_unlock(&ifbdev->helper.dev->struct_mutex); } diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 41e9465d44a8..89f568e739ee 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -801,7 +801,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, atomic_inc(&dev_priv->gpu_error.pending_fb_pin); - vma = i915_gem_object_pin_to_display_plane(new_bo, 0, NULL); + vma = i915_gem_object_pin_to_display_plane(new_bo, + 0, NULL, PIN_MAPPABLE); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_pin_section; From e3c017f15f7ee4c088697d41ee4260986c42a885 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Feb 2018 13:42:07 +0000 Subject: [PATCH 111/113] drm/i915/fbdev: Use the PLANE_HAS_FENCE flags from the time of pinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the information about the fence state from the time of pinning to determine if the fbdev writes are going through a fence. This avoids any confusion in cases where the fence may appear or disappear unconnected to the use by fbdev. Suggested-by: Ville Syrjälä Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_fbdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 3d8ce3a62743..055f409f8b75 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -48,7 +48,8 @@ static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev) { struct drm_i915_gem_object *obj = ifbdev->fb->obj; - unsigned int origin = ifbdev->vma->fence ? ORIGIN_GTT : ORIGIN_CPU; + unsigned int origin = + ifbdev->vma_flags & PLANE_HAS_FENCE ? ORIGIN_GTT : ORIGIN_CPU; intel_fb_obj_invalidate(obj, origin); } From 1c9b6b133e658f9efde8706124f185fde3f273bb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 20 Feb 2018 13:42:08 +0000 Subject: [PATCH 112/113] drm/i915/fbc: Use PLANE_HAS_FENCE to determine if the plane is fenced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than trusting the cached value of plane_state->vma->fence to imply whether the plane_state itself holds a reference on the framebuffer's fence, use the information provided in the plane_state->flags (PLANE_HAS_FENCE). Note that we still assume that FBC is entirely bounded by the plane_state active life span; it's not clear if that is a safe assumption. Suggested-by: Ville Syrjälä Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_fbc.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3e1ad3f8e55d..1cdb543d4fce 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -667,6 +667,7 @@ struct intel_fbc { */ struct intel_fbc_state_cache { struct i915_vma *vma; + unsigned long flags; struct { unsigned int mode_flags; @@ -705,6 +706,7 @@ struct intel_fbc { */ struct intel_fbc_reg_params { struct i915_vma *vma; + unsigned long flags; struct { enum pipe pipe; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 80682a418a70..2cc2eada5576 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -183,7 +183,7 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv) else dpfc_ctl |= DPFC_CTL_LIMIT_1X; - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id; I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset); } else { @@ -241,7 +241,7 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= DPFC_CTL_FENCE_EN; if (IS_GEN5(dev_priv)) dpfc_ctl |= params->vma->fence->id; @@ -324,7 +324,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv) break; } - if (params->vma->fence) { + if (params->flags & PLANE_HAS_FENCE) { dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN; I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | @@ -753,6 +753,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, struct drm_framebuffer *fb = plane_state->base.fb; cache->vma = NULL; + cache->flags = 0; cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -778,6 +779,9 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->fb.stride = fb->pitches[0]; cache->vma = plane_state->vma; + cache->flags = plane_state->flags; + if (WARN_ON(cache->flags & PLANE_HAS_FENCE && !cache->vma->fence)) + cache->flags &= ~PLANE_HAS_FENCE; } static bool intel_fbc_can_activate(struct intel_crtc *crtc) @@ -817,7 +821,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) * so have no fence associated with it) due to aperture constaints * at the time of pinning. */ - if (!cache->vma->fence) { + if (!(cache->flags & PLANE_HAS_FENCE)) { fbc->no_fbc_reason = "framebuffer not tiled or fenced"; return false; } @@ -898,6 +902,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, memset(params, 0, sizeof(*params)); params->vma = cache->vma; + params->flags = cache->flags; params->crtc.pipe = crtc->pipe; params->crtc.i9xx_plane = to_intel_plane(crtc->base.primary)->i9xx_plane; From fed8165851e262575585b22055ff5dba7d91b0e5 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 21 Feb 2018 15:21:30 +0200 Subject: [PATCH 113/113] drm/i915: Update DRIVER_DATE to 20180221 Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1cdb543d4fce..4a279be84f66 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -83,8 +83,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20180214" -#define DRIVER_TIMESTAMP 1518601107 +#define DRIVER_DATE "20180221" +#define DRIVER_TIMESTAMP 1519219289 /* 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