diff options
author | Dave Airlie <airlied@redhat.com> | 2017-11-13 14:18:21 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-11-13 14:18:21 -0500 |
commit | 9c117313afbaba6f7613fa2b305b7da5d6058fb1 (patch) | |
tree | 4dfd2b8c3003586d107785551c9b5d2d1e37b04e /drivers | |
parent | fee25cb965f9e1360f845a7a3fb16bca1bbadc84 (diff) | |
parent | e8c49fa96838101435b9e4884d49b30da7a4e0c6 (diff) |
Merge tag 'drm-intel-next-fixes-2017-11-10' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
drm/i915 fixes for v4.15
* tag 'drm-intel-next-fixes-2017-11-10' of git://anongit.freedesktop.org/drm/drm-intel:
drm/i915: Reorder context-close to avoid calling i915_vma_close() under RCU
drm/i915: Move init_clock_gating() back to where it was
drm/i915: Prune the reservation shared fence array
drm/i915: Idle the GPU before shinking everything
drm/i915: Lock llist_del_first() vs llist_del_all()
drm/i915: Calculate ironlake intermediate watermarks correctly, v2.
drm/i915: Disable lazy PPGTT page table optimization for vGPU
drm/i915/execlists: Remove the priority "optimisation"
drm/i915: Filter out spurious execlists context-switch interrupts
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_shrinker.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_guc_submission.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_vma.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_engine_cs.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 53 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 34 |
12 files changed, 133 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 026cb52ece0b..94b23fcbc989 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -4603,11 +4603,17 @@ static void __i915_gem_free_work(struct work_struct *work) | |||
4603 | * unbound now. | 4603 | * unbound now. |
4604 | */ | 4604 | */ |
4605 | 4605 | ||
4606 | spin_lock(&i915->mm.free_lock); | ||
4606 | while ((freed = llist_del_all(&i915->mm.free_list))) { | 4607 | while ((freed = llist_del_all(&i915->mm.free_list))) { |
4608 | spin_unlock(&i915->mm.free_lock); | ||
4609 | |||
4607 | __i915_gem_free_objects(i915, freed); | 4610 | __i915_gem_free_objects(i915, freed); |
4608 | if (need_resched()) | 4611 | if (need_resched()) |
4609 | break; | 4612 | return; |
4613 | |||
4614 | spin_lock(&i915->mm.free_lock); | ||
4610 | } | 4615 | } |
4616 | spin_unlock(&i915->mm.free_lock); | ||
4611 | } | 4617 | } |
4612 | 4618 | ||
4613 | static void __i915_gem_free_object_rcu(struct rcu_head *head) | 4619 | static void __i915_gem_free_object_rcu(struct rcu_head *head) |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5bf96a258509..e304dcbc6042 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -106,14 +106,9 @@ static void lut_close(struct i915_gem_context *ctx) | |||
106 | 106 | ||
107 | radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) { | 107 | radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) { |
108 | struct i915_vma *vma = rcu_dereference_raw(*slot); | 108 | struct i915_vma *vma = rcu_dereference_raw(*slot); |
109 | struct drm_i915_gem_object *obj = vma->obj; | ||
110 | 109 | ||
111 | radix_tree_iter_delete(&ctx->handles_vma, &iter, slot); | 110 | radix_tree_iter_delete(&ctx->handles_vma, &iter, slot); |
112 | 111 | __i915_gem_object_release_unless_active(vma->obj); | |
113 | if (!i915_vma_is_ggtt(vma)) | ||
114 | i915_vma_close(vma); | ||
115 | |||
116 | __i915_gem_object_release_unless_active(obj); | ||
117 | } | 112 | } |
118 | } | 113 | } |
119 | 114 | ||
@@ -198,6 +193,11 @@ static void context_close(struct i915_gem_context *ctx) | |||
198 | { | 193 | { |
199 | i915_gem_context_set_closed(ctx); | 194 | i915_gem_context_set_closed(ctx); |
200 | 195 | ||
196 | /* | ||
197 | * The LUT uses the VMA as a backpointer to unref the object, | ||
198 | * so we need to clear the LUT before we close all the VMA (inside | ||
199 | * the ppgtt). | ||
200 | */ | ||
201 | lut_close(ctx); | 201 | lut_close(ctx); |
202 | if (ctx->ppgtt) | 202 | if (ctx->ppgtt) |
203 | i915_ppgtt_close(&ctx->ppgtt->base); | 203 | i915_ppgtt_close(&ctx->ppgtt->base); |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 527a2d2d6281..5eaa6893daaa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -1341,7 +1341,7 @@ static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm, | |||
1341 | if (IS_ERR(pt)) | 1341 | if (IS_ERR(pt)) |
1342 | goto unwind; | 1342 | goto unwind; |
1343 | 1343 | ||
1344 | if (count < GEN8_PTES) | 1344 | if (count < GEN8_PTES || intel_vgpu_active(vm->i915)) |
1345 | gen8_initialize_pt(vm, pt); | 1345 | gen8_initialize_pt(vm, pt); |
1346 | 1346 | ||
1347 | gen8_ppgtt_set_pde(vm, pd, pt, pde); | 1347 | gen8_ppgtt_set_pde(vm, pd, pt, pde); |
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index eb31f8aa5c21..3770e3323fc8 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c | |||
@@ -162,6 +162,18 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, | |||
162 | if (!shrinker_lock(dev_priv, &unlock)) | 162 | if (!shrinker_lock(dev_priv, &unlock)) |
163 | return 0; | 163 | return 0; |
164 | 164 | ||
165 | /* | ||
166 | * When shrinking the active list, also consider active contexts. | ||
167 | * Active contexts are pinned until they are retired, and so can | ||
168 | * not be simply unbound to retire and unpin their pages. To shrink | ||
169 | * the contexts, we must wait until the gpu is idle. | ||
170 | * | ||
171 | * We don't care about errors here; if we cannot wait upon the GPU, | ||
172 | * we will free as much as we can and hope to get a second chance. | ||
173 | */ | ||
174 | if (flags & I915_SHRINK_ACTIVE) | ||
175 | i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); | ||
176 | |||
165 | trace_i915_gem_shrink(dev_priv, target, flags); | 177 | trace_i915_gem_shrink(dev_priv, target, flags); |
166 | i915_gem_retire_requests(dev_priv); | 178 | i915_gem_retire_requests(dev_priv); |
167 | 179 | ||
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index a2e8114b739d..f84c267728fd 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c | |||
@@ -610,6 +610,7 @@ done: | |||
610 | execlists->first = rb; | 610 | execlists->first = rb; |
611 | if (submit) { | 611 | if (submit) { |
612 | port_assign(port, last); | 612 | port_assign(port, last); |
613 | execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | ||
613 | i915_guc_submit(engine); | 614 | i915_guc_submit(engine); |
614 | } | 615 | } |
615 | spin_unlock_irq(&engine->timeline->lock); | 616 | spin_unlock_irq(&engine->timeline->lock); |
@@ -633,6 +634,8 @@ static void i915_guc_irq_handler(unsigned long data) | |||
633 | 634 | ||
634 | rq = port_request(&port[0]); | 635 | rq = port_request(&port[0]); |
635 | } | 636 | } |
637 | if (!rq) | ||
638 | execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); | ||
636 | 639 | ||
637 | if (!port_isset(last_port)) | 640 | if (!port_isset(last_port)) |
638 | i915_guc_dequeue(engine); | 641 | i915_guc_dequeue(engine); |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b1296a55c1e4..f8205841868b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1388,8 +1388,10 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) | |||
1388 | bool tasklet = false; | 1388 | bool tasklet = false; |
1389 | 1389 | ||
1390 | if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { | 1390 | if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { |
1391 | __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 1391 | if (READ_ONCE(engine->execlists.active)) { |
1392 | tasklet = true; | 1392 | __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); |
1393 | tasklet = true; | ||
1394 | } | ||
1393 | } | 1395 | } |
1394 | 1396 | ||
1395 | if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { | 1397 | if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { |
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index fc77e8191eb5..fbfab2f33023 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c | |||
@@ -54,6 +54,13 @@ i915_vma_retire(struct i915_gem_active *active, | |||
54 | if (--obj->active_count) | 54 | if (--obj->active_count) |
55 | return; | 55 | return; |
56 | 56 | ||
57 | /* Prune the shared fence arrays iff completely idle (inc. external) */ | ||
58 | if (reservation_object_trylock(obj->resv)) { | ||
59 | if (reservation_object_test_signaled_rcu(obj->resv, true)) | ||
60 | reservation_object_add_excl_fence(obj->resv, NULL); | ||
61 | reservation_object_unlock(obj->resv); | ||
62 | } | ||
63 | |||
57 | /* Bump our place on the bound list to keep it roughly in LRU order | 64 | /* Bump our place on the bound list to keep it roughly in LRU order |
58 | * so that we don't steal from recently used but inactive objects | 65 | * so that we don't steal from recently used but inactive objects |
59 | * (unless we are forced to ofc!) | 66 | * (unless we are forced to ofc!) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e2ac976844d8..f4a9a182868f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3676,6 +3676,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) | |||
3676 | 3676 | ||
3677 | intel_pps_unlock_regs_wa(dev_priv); | 3677 | intel_pps_unlock_regs_wa(dev_priv); |
3678 | intel_modeset_init_hw(dev); | 3678 | intel_modeset_init_hw(dev); |
3679 | intel_init_clock_gating(dev_priv); | ||
3679 | 3680 | ||
3680 | spin_lock_irq(&dev_priv->irq_lock); | 3681 | spin_lock_irq(&dev_priv->irq_lock); |
3681 | if (dev_priv->display.hpd_irq_setup) | 3682 | if (dev_priv->display.hpd_irq_setup) |
@@ -14350,8 +14351,6 @@ void intel_modeset_init_hw(struct drm_device *dev) | |||
14350 | 14351 | ||
14351 | intel_update_cdclk(dev_priv); | 14352 | intel_update_cdclk(dev_priv); |
14352 | dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw; | 14353 | dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw; |
14353 | |||
14354 | intel_init_clock_gating(dev_priv); | ||
14355 | } | 14354 | } |
14356 | 14355 | ||
14357 | /* | 14356 | /* |
@@ -15063,6 +15062,15 @@ intel_modeset_setup_hw_state(struct drm_device *dev, | |||
15063 | struct intel_encoder *encoder; | 15062 | struct intel_encoder *encoder; |
15064 | int i; | 15063 | int i; |
15065 | 15064 | ||
15065 | if (IS_HASWELL(dev_priv)) { | ||
15066 | /* | ||
15067 | * WaRsPkgCStateDisplayPMReq:hsw | ||
15068 | * System hang if this isn't done before disabling all planes! | ||
15069 | */ | ||
15070 | I915_WRITE(CHICKEN_PAR1_1, | ||
15071 | I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); | ||
15072 | } | ||
15073 | |||
15066 | intel_modeset_readout_hw_state(dev); | 15074 | intel_modeset_readout_hw_state(dev); |
15067 | 15075 | ||
15068 | /* HW state is read out, now we need to sanitize this mess. */ | 15076 | /* HW state is read out, now we need to sanitize this mess. */ |
@@ -15160,6 +15168,8 @@ void intel_modeset_gem_init(struct drm_device *dev) | |||
15160 | 15168 | ||
15161 | intel_init_gt_powersave(dev_priv); | 15169 | intel_init_gt_powersave(dev_priv); |
15162 | 15170 | ||
15171 | intel_init_clock_gating(dev_priv); | ||
15172 | |||
15163 | intel_setup_overlay(dev_priv); | 15173 | intel_setup_overlay(dev_priv); |
15164 | } | 15174 | } |
15165 | 15175 | ||
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index a47a9c6bea52..ab5bf4e2e28e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
@@ -1548,8 +1548,8 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) | |||
1548 | if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) | 1548 | if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) |
1549 | return false; | 1549 | return false; |
1550 | 1550 | ||
1551 | /* Both ports drained, no more ELSP submission? */ | 1551 | /* Waiting to drain ELSP? */ |
1552 | if (port_request(&engine->execlists.port[0])) | 1552 | if (READ_ONCE(engine->execlists.active)) |
1553 | return false; | 1553 | return false; |
1554 | 1554 | ||
1555 | /* ELSP is empty, but there are ready requests? */ | 1555 | /* ELSP is empty, but there are ready requests? */ |
@@ -1749,6 +1749,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) | |||
1749 | idx); | 1749 | idx); |
1750 | } | 1750 | } |
1751 | } | 1751 | } |
1752 | drm_printf(m, "\t\tHW active? 0x%x\n", execlists->active); | ||
1752 | rcu_read_unlock(); | 1753 | rcu_read_unlock(); |
1753 | } else if (INTEL_GEN(dev_priv) > 6) { | 1754 | } else if (INTEL_GEN(dev_priv) > 6) { |
1754 | drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n", | 1755 | drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n", |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7f45dd7dc3e5..d36e25607435 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -575,7 +575,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine) | |||
575 | * the state of the GPU is known (idle). | 575 | * the state of the GPU is known (idle). |
576 | */ | 576 | */ |
577 | inject_preempt_context(engine); | 577 | inject_preempt_context(engine); |
578 | execlists->preempt = true; | 578 | execlists_set_active(execlists, |
579 | EXECLISTS_ACTIVE_PREEMPT); | ||
579 | goto unlock; | 580 | goto unlock; |
580 | } else { | 581 | } else { |
581 | /* | 582 | /* |
@@ -683,8 +684,10 @@ done: | |||
683 | unlock: | 684 | unlock: |
684 | spin_unlock_irq(&engine->timeline->lock); | 685 | spin_unlock_irq(&engine->timeline->lock); |
685 | 686 | ||
686 | if (submit) | 687 | if (submit) { |
688 | execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); | ||
687 | execlists_submit_ports(engine); | 689 | execlists_submit_ports(engine); |
690 | } | ||
688 | } | 691 | } |
689 | 692 | ||
690 | static void | 693 | static void |
@@ -696,6 +699,7 @@ execlist_cancel_port_requests(struct intel_engine_execlists *execlists) | |||
696 | while (num_ports-- && port_isset(port)) { | 699 | while (num_ports-- && port_isset(port)) { |
697 | struct drm_i915_gem_request *rq = port_request(port); | 700 | struct drm_i915_gem_request *rq = port_request(port); |
698 | 701 | ||
702 | GEM_BUG_ON(!execlists->active); | ||
699 | execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_PREEMPTED); | 703 | execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_PREEMPTED); |
700 | i915_gem_request_put(rq); | 704 | i915_gem_request_put(rq); |
701 | 705 | ||
@@ -730,7 +734,6 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
730 | 734 | ||
731 | list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { | 735 | list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { |
732 | INIT_LIST_HEAD(&rq->priotree.link); | 736 | INIT_LIST_HEAD(&rq->priotree.link); |
733 | rq->priotree.priority = INT_MAX; | ||
734 | 737 | ||
735 | dma_fence_set_error(&rq->fence, -EIO); | 738 | dma_fence_set_error(&rq->fence, -EIO); |
736 | __i915_gem_request_submit(rq); | 739 | __i915_gem_request_submit(rq); |
@@ -861,15 +864,21 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
861 | unwind_incomplete_requests(engine); | 864 | unwind_incomplete_requests(engine); |
862 | spin_unlock_irq(&engine->timeline->lock); | 865 | spin_unlock_irq(&engine->timeline->lock); |
863 | 866 | ||
864 | GEM_BUG_ON(!execlists->preempt); | 867 | GEM_BUG_ON(!execlists_is_active(execlists, |
865 | execlists->preempt = false; | 868 | EXECLISTS_ACTIVE_PREEMPT)); |
869 | execlists_clear_active(execlists, | ||
870 | EXECLISTS_ACTIVE_PREEMPT); | ||
866 | continue; | 871 | continue; |
867 | } | 872 | } |
868 | 873 | ||
869 | if (status & GEN8_CTX_STATUS_PREEMPTED && | 874 | if (status & GEN8_CTX_STATUS_PREEMPTED && |
870 | execlists->preempt) | 875 | execlists_is_active(execlists, |
876 | EXECLISTS_ACTIVE_PREEMPT)) | ||
871 | continue; | 877 | continue; |
872 | 878 | ||
879 | GEM_BUG_ON(!execlists_is_active(execlists, | ||
880 | EXECLISTS_ACTIVE_USER)); | ||
881 | |||
873 | /* Check the context/desc id for this event matches */ | 882 | /* Check the context/desc id for this event matches */ |
874 | GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); | 883 | GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); |
875 | 884 | ||
@@ -881,7 +890,6 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
881 | execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); | 890 | execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT); |
882 | 891 | ||
883 | trace_i915_gem_request_out(rq); | 892 | trace_i915_gem_request_out(rq); |
884 | rq->priotree.priority = INT_MAX; | ||
885 | i915_gem_request_put(rq); | 893 | i915_gem_request_put(rq); |
886 | 894 | ||
887 | execlists_port_complete(execlists, port); | 895 | execlists_port_complete(execlists, port); |
@@ -892,6 +900,9 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
892 | /* After the final element, the hw should be idle */ | 900 | /* After the final element, the hw should be idle */ |
893 | GEM_BUG_ON(port_count(port) == 0 && | 901 | GEM_BUG_ON(port_count(port) == 0 && |
894 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); | 902 | !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); |
903 | if (port_count(port) == 0) | ||
904 | execlists_clear_active(execlists, | ||
905 | EXECLISTS_ACTIVE_USER); | ||
895 | } | 906 | } |
896 | 907 | ||
897 | if (head != execlists->csb_head) { | 908 | if (head != execlists->csb_head) { |
@@ -901,7 +912,7 @@ static void intel_lrc_irq_handler(unsigned long data) | |||
901 | } | 912 | } |
902 | } | 913 | } |
903 | 914 | ||
904 | if (!execlists->preempt) | 915 | if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT)) |
905 | execlists_dequeue(engine); | 916 | execlists_dequeue(engine); |
906 | 917 | ||
907 | intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); | 918 | intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); |
@@ -1460,7 +1471,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) | |||
1460 | GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); | 1471 | GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); |
1461 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 1472 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); |
1462 | execlists->csb_head = -1; | 1473 | execlists->csb_head = -1; |
1463 | execlists->preempt = false; | 1474 | execlists->active = 0; |
1464 | 1475 | ||
1465 | /* After a GPU reset, we may have requests to replay */ | 1476 | /* After a GPU reset, we may have requests to replay */ |
1466 | if (!i915_modparams.enable_guc_submission && execlists->first) | 1477 | if (!i915_modparams.enable_guc_submission && execlists->first) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c42a65a93b3a..aa12a44e9a76 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -3133,7 +3133,11 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, | |||
3133 | struct intel_crtc_state *newstate) | 3133 | struct intel_crtc_state *newstate) |
3134 | { | 3134 | { |
3135 | struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; | 3135 | struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; |
3136 | struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; | 3136 | struct intel_atomic_state *intel_state = |
3137 | to_intel_atomic_state(newstate->base.state); | ||
3138 | const struct intel_crtc_state *oldstate = | ||
3139 | intel_atomic_get_old_crtc_state(intel_state, intel_crtc); | ||
3140 | const struct intel_pipe_wm *b = &oldstate->wm.ilk.optimal; | ||
3137 | int level, max_level = ilk_wm_max_level(to_i915(dev)); | 3141 | int level, max_level = ilk_wm_max_level(to_i915(dev)); |
3138 | 3142 | ||
3139 | /* | 3143 | /* |
@@ -3142,6 +3146,9 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, | |||
3142 | * and after the vblank. | 3146 | * and after the vblank. |
3143 | */ | 3147 | */ |
3144 | *a = newstate->wm.ilk.optimal; | 3148 | *a = newstate->wm.ilk.optimal; |
3149 | if (!newstate->base.active || drm_atomic_crtc_needs_modeset(&newstate->base)) | ||
3150 | return 0; | ||
3151 | |||
3145 | a->pipe_enabled |= b->pipe_enabled; | 3152 | a->pipe_enabled |= b->pipe_enabled; |
3146 | a->sprites_enabled |= b->sprites_enabled; | 3153 | a->sprites_enabled |= b->sprites_enabled; |
3147 | a->sprites_scaled |= b->sprites_scaled; | 3154 | a->sprites_scaled |= b->sprites_scaled; |
@@ -5755,12 +5762,30 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) | |||
5755 | mutex_unlock(&dev_priv->wm.wm_mutex); | 5762 | mutex_unlock(&dev_priv->wm.wm_mutex); |
5756 | } | 5763 | } |
5757 | 5764 | ||
5765 | /* | ||
5766 | * FIXME should probably kill this and improve | ||
5767 | * the real watermark readout/sanitation instead | ||
5768 | */ | ||
5769 | static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) | ||
5770 | { | ||
5771 | I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); | ||
5772 | I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); | ||
5773 | I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); | ||
5774 | |||
5775 | /* | ||
5776 | * Don't touch WM1S_LP_EN here. | ||
5777 | * Doing so could cause underruns. | ||
5778 | */ | ||
5779 | } | ||
5780 | |||
5758 | void ilk_wm_get_hw_state(struct drm_device *dev) | 5781 | void ilk_wm_get_hw_state(struct drm_device *dev) |
5759 | { | 5782 | { |
5760 | struct drm_i915_private *dev_priv = to_i915(dev); | 5783 | struct drm_i915_private *dev_priv = to_i915(dev); |
5761 | struct ilk_wm_values *hw = &dev_priv->wm.hw; | 5784 | struct ilk_wm_values *hw = &dev_priv->wm.hw; |
5762 | struct drm_crtc *crtc; | 5785 | struct drm_crtc *crtc; |
5763 | 5786 | ||
5787 | ilk_init_lp_watermarks(dev_priv); | ||
5788 | |||
5764 | for_each_crtc(dev, crtc) | 5789 | for_each_crtc(dev, crtc) |
5765 | ilk_pipe_wm_get_hw_state(crtc); | 5790 | ilk_pipe_wm_get_hw_state(crtc); |
5766 | 5791 | ||
@@ -8207,18 +8232,6 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) | |||
8207 | } | 8232 | } |
8208 | } | 8233 | } |
8209 | 8234 | ||
8210 | static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) | ||
8211 | { | ||
8212 | I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); | ||
8213 | I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); | ||
8214 | I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); | ||
8215 | |||
8216 | /* | ||
8217 | * Don't touch WM1S_LP_EN here. | ||
8218 | * Doing so could cause underruns. | ||
8219 | */ | ||
8220 | } | ||
8221 | |||
8222 | static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) | 8235 | static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) |
8223 | { | 8236 | { |
8224 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; | 8237 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; |
@@ -8252,8 +8265,6 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8252 | (I915_READ(DISP_ARB_CTL) | | 8265 | (I915_READ(DISP_ARB_CTL) | |
8253 | DISP_FBC_WM_DIS)); | 8266 | DISP_FBC_WM_DIS)); |
8254 | 8267 | ||
8255 | ilk_init_lp_watermarks(dev_priv); | ||
8256 | |||
8257 | /* | 8268 | /* |
8258 | * Based on the document from hardware guys the following bits | 8269 | * Based on the document from hardware guys the following bits |
8259 | * should be set unconditionally in order to enable FBC. | 8270 | * should be set unconditionally in order to enable FBC. |
@@ -8366,8 +8377,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8366 | I915_WRITE(GEN6_GT_MODE, | 8377 | I915_WRITE(GEN6_GT_MODE, |
8367 | _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4)); | 8378 | _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4)); |
8368 | 8379 | ||
8369 | ilk_init_lp_watermarks(dev_priv); | ||
8370 | |||
8371 | I915_WRITE(CACHE_MODE_0, | 8380 | I915_WRITE(CACHE_MODE_0, |
8372 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); | 8381 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); |
8373 | 8382 | ||
@@ -8594,8 +8603,6 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8594 | I915_GTT_PAGE_SIZE_2M); | 8603 | I915_GTT_PAGE_SIZE_2M); |
8595 | enum pipe pipe; | 8604 | enum pipe pipe; |
8596 | 8605 | ||
8597 | ilk_init_lp_watermarks(dev_priv); | ||
8598 | |||
8599 | /* WaSwitchSolVfFArbitrationPriority:bdw */ | 8606 | /* WaSwitchSolVfFArbitrationPriority:bdw */ |
8600 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); | 8607 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); |
8601 | 8608 | ||
@@ -8646,8 +8653,6 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8646 | 8653 | ||
8647 | static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) | 8654 | static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) |
8648 | { | 8655 | { |
8649 | ilk_init_lp_watermarks(dev_priv); | ||
8650 | |||
8651 | /* L3 caching of data atomics doesn't work -- disable it. */ | 8656 | /* L3 caching of data atomics doesn't work -- disable it. */ |
8652 | I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); | 8657 | I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); |
8653 | I915_WRITE(HSW_ROW_CHICKEN3, | 8658 | I915_WRITE(HSW_ROW_CHICKEN3, |
@@ -8691,10 +8696,6 @@ static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8691 | /* WaSwitchSolVfFArbitrationPriority:hsw */ | 8696 | /* WaSwitchSolVfFArbitrationPriority:hsw */ |
8692 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); | 8697 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); |
8693 | 8698 | ||
8694 | /* WaRsPkgCStateDisplayPMReq:hsw */ | ||
8695 | I915_WRITE(CHICKEN_PAR1_1, | ||
8696 | I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); | ||
8697 | |||
8698 | lpt_init_clock_gating(dev_priv); | 8699 | lpt_init_clock_gating(dev_priv); |
8699 | } | 8700 | } |
8700 | 8701 | ||
@@ -8702,8 +8703,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) | |||
8702 | { | 8703 | { |
8703 | uint32_t snpcr; | 8704 | uint32_t snpcr; |
8704 | 8705 | ||
8705 | ilk_init_lp_watermarks(dev_priv); | ||
8706 | |||
8707 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); | 8706 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); |
8708 | 8707 | ||
8709 | /* WaDisableEarlyCull:ivb */ | 8708 | /* WaDisableEarlyCull:ivb */ |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 17186f067408..6a42ed618a28 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -241,9 +241,17 @@ struct intel_engine_execlists { | |||
241 | } port[EXECLIST_MAX_PORTS]; | 241 | } port[EXECLIST_MAX_PORTS]; |
242 | 242 | ||
243 | /** | 243 | /** |
244 | * @preempt: are we currently handling a preempting context switch? | 244 | * @active: is the HW active? We consider the HW as active after |
245 | * submitting any context for execution and until we have seen the | ||
246 | * last context completion event. After that, we do not expect any | ||
247 | * more events until we submit, and so can park the HW. | ||
248 | * | ||
249 | * As we have a small number of different sources from which we feed | ||
250 | * the HW, we track the state of each inside a single bitfield. | ||
245 | */ | 251 | */ |
246 | bool preempt; | 252 | unsigned int active; |
253 | #define EXECLISTS_ACTIVE_USER 0 | ||
254 | #define EXECLISTS_ACTIVE_PREEMPT 1 | ||
247 | 255 | ||
248 | /** | 256 | /** |
249 | * @port_mask: number of execlist ports - 1 | 257 | * @port_mask: number of execlist ports - 1 |
@@ -525,6 +533,27 @@ struct intel_engine_cs { | |||
525 | u32 (*get_cmd_length_mask)(u32 cmd_header); | 533 | u32 (*get_cmd_length_mask)(u32 cmd_header); |
526 | }; | 534 | }; |
527 | 535 | ||
536 | static inline void | ||
537 | execlists_set_active(struct intel_engine_execlists *execlists, | ||
538 | unsigned int bit) | ||
539 | { | ||
540 | __set_bit(bit, (unsigned long *)&execlists->active); | ||
541 | } | ||
542 | |||
543 | static inline void | ||
544 | execlists_clear_active(struct intel_engine_execlists *execlists, | ||
545 | unsigned int bit) | ||
546 | { | ||
547 | __clear_bit(bit, (unsigned long *)&execlists->active); | ||
548 | } | ||
549 | |||
550 | static inline bool | ||
551 | execlists_is_active(const struct intel_engine_execlists *execlists, | ||
552 | unsigned int bit) | ||
553 | { | ||
554 | return test_bit(bit, (unsigned long *)&execlists->active); | ||
555 | } | ||
556 | |||
528 | static inline unsigned int | 557 | static inline unsigned int |
529 | execlists_num_ports(const struct intel_engine_execlists * const execlists) | 558 | execlists_num_ports(const struct intel_engine_execlists * const execlists) |
530 | { | 559 | { |
@@ -538,6 +567,7 @@ execlists_port_complete(struct intel_engine_execlists * const execlists, | |||
538 | const unsigned int m = execlists->port_mask; | 567 | const unsigned int m = execlists->port_mask; |
539 | 568 | ||
540 | GEM_BUG_ON(port_index(port, execlists) != 0); | 569 | GEM_BUG_ON(port_index(port, execlists) != 0); |
570 | GEM_BUG_ON(!execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); | ||
541 | 571 | ||
542 | memmove(port, port + 1, m * sizeof(struct execlist_port)); | 572 | memmove(port, port + 1, m * sizeof(struct execlist_port)); |
543 | memset(port + m, 0, sizeof(struct execlist_port)); | 573 | memset(port + m, 0, sizeof(struct execlist_port)); |