diff options
author | Dave Airlie <airlied@redhat.com> | 2019-03-13 21:56:59 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-03-13 21:57:11 -0400 |
commit | ad7ad48e09871e7bf6d75db80243f2abb30b4db9 (patch) | |
tree | 1ce55ec72e0d0e5fd8cdd9b48d426a24fc3fc447 | |
parent | 74cd45fa90a234de92a3f3ce8bdabeb643b546a5 (diff) | |
parent | ca22f32a6296cbfa29de56328c8505560a18cfa8 (diff) |
Merge tag 'drm-intel-next-fixes-2019-03-12' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
- HDCP state handling in ddi_update_pipe
- Protect i915_active iterators from the shrinker
- Reacquire priolist cache after dropping the engine lock
- (Selftest) Always free spinner on __sseu_prepare error
- Acquire breadcrumb ref before canceling
- Fix atomic state leak on HDMI link reset
- Relax mmap VMA check
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190312205551.GA7701@intel.com
-rw-r--r-- | drivers/gpu/drm/i915/i915_active.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_scheduler.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_breadcrumbs.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/selftests/i915_gem_context.c | 69 |
6 files changed, 94 insertions, 73 deletions
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 215b6ff8aa73..db7bb5bd5add 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c | |||
@@ -163,17 +163,25 @@ int i915_active_ref(struct i915_active *ref, | |||
163 | struct i915_request *rq) | 163 | struct i915_request *rq) |
164 | { | 164 | { |
165 | struct i915_active_request *active; | 165 | struct i915_active_request *active; |
166 | int err = 0; | ||
167 | |||
168 | /* Prevent reaping in case we malloc/wait while building the tree */ | ||
169 | i915_active_acquire(ref); | ||
166 | 170 | ||
167 | active = active_instance(ref, timeline); | 171 | active = active_instance(ref, timeline); |
168 | if (IS_ERR(active)) | 172 | if (IS_ERR(active)) { |
169 | return PTR_ERR(active); | 173 | err = PTR_ERR(active); |
174 | goto out; | ||
175 | } | ||
170 | 176 | ||
171 | if (!i915_active_request_isset(active)) | 177 | if (!i915_active_request_isset(active)) |
172 | ref->count++; | 178 | ref->count++; |
173 | __i915_active_request_set(active, rq); | 179 | __i915_active_request_set(active, rq); |
174 | 180 | ||
175 | GEM_BUG_ON(!ref->count); | 181 | GEM_BUG_ON(!ref->count); |
176 | return 0; | 182 | out: |
183 | i915_active_release(ref); | ||
184 | return err; | ||
177 | } | 185 | } |
178 | 186 | ||
179 | bool i915_active_acquire(struct i915_active *ref) | 187 | bool i915_active_acquire(struct i915_active *ref) |
@@ -223,19 +231,25 @@ int i915_request_await_active_request(struct i915_request *rq, | |||
223 | int i915_request_await_active(struct i915_request *rq, struct i915_active *ref) | 231 | int i915_request_await_active(struct i915_request *rq, struct i915_active *ref) |
224 | { | 232 | { |
225 | struct active_node *it, *n; | 233 | struct active_node *it, *n; |
226 | int ret; | 234 | int err = 0; |
227 | 235 | ||
228 | ret = i915_request_await_active_request(rq, &ref->last); | 236 | /* await allocates and so we need to avoid hitting the shrinker */ |
229 | if (ret) | 237 | if (i915_active_acquire(ref)) |
230 | return ret; | 238 | goto out; /* was idle */ |
239 | |||
240 | err = i915_request_await_active_request(rq, &ref->last); | ||
241 | if (err) | ||
242 | goto out; | ||
231 | 243 | ||
232 | rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) { | 244 | rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) { |
233 | ret = i915_request_await_active_request(rq, &it->base); | 245 | err = i915_request_await_active_request(rq, &it->base); |
234 | if (ret) | 246 | if (err) |
235 | return ret; | 247 | goto out; |
236 | } | 248 | } |
237 | 249 | ||
238 | return 0; | 250 | out: |
251 | i915_active_release(ref); | ||
252 | return err; | ||
239 | } | 253 | } |
240 | 254 | ||
241 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) | 255 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6728ea5c71d4..30d516e975c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1688,7 +1688,8 @@ __vma_matches(struct vm_area_struct *vma, struct file *filp, | |||
1688 | if (vma->vm_file != filp) | 1688 | if (vma->vm_file != filp) |
1689 | return false; | 1689 | return false; |
1690 | 1690 | ||
1691 | return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size; | 1691 | return vma->vm_start == addr && |
1692 | (vma->vm_end - vma->vm_start) == PAGE_ALIGN(size); | ||
1692 | } | 1693 | } |
1693 | 1694 | ||
1694 | /** | 1695 | /** |
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index d01683167c77..8bc042551692 100644 --- a/drivers/gpu/drm/i915/i915_scheduler.c +++ b/drivers/gpu/drm/i915/i915_scheduler.c | |||
@@ -223,8 +223,14 @@ out: | |||
223 | return &p->requests[idx]; | 223 | return &p->requests[idx]; |
224 | } | 224 | } |
225 | 225 | ||
226 | struct sched_cache { | ||
227 | struct list_head *priolist; | ||
228 | }; | ||
229 | |||
226 | static struct intel_engine_cs * | 230 | static struct intel_engine_cs * |
227 | sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked) | 231 | sched_lock_engine(const struct i915_sched_node *node, |
232 | struct intel_engine_cs *locked, | ||
233 | struct sched_cache *cache) | ||
228 | { | 234 | { |
229 | struct intel_engine_cs *engine = node_to_request(node)->engine; | 235 | struct intel_engine_cs *engine = node_to_request(node)->engine; |
230 | 236 | ||
@@ -232,6 +238,7 @@ sched_lock_engine(struct i915_sched_node *node, struct intel_engine_cs *locked) | |||
232 | 238 | ||
233 | if (engine != locked) { | 239 | if (engine != locked) { |
234 | spin_unlock(&locked->timeline.lock); | 240 | spin_unlock(&locked->timeline.lock); |
241 | memset(cache, 0, sizeof(*cache)); | ||
235 | spin_lock(&engine->timeline.lock); | 242 | spin_lock(&engine->timeline.lock); |
236 | } | 243 | } |
237 | 244 | ||
@@ -253,11 +260,11 @@ static bool inflight(const struct i915_request *rq, | |||
253 | static void __i915_schedule(struct i915_request *rq, | 260 | static void __i915_schedule(struct i915_request *rq, |
254 | const struct i915_sched_attr *attr) | 261 | const struct i915_sched_attr *attr) |
255 | { | 262 | { |
256 | struct list_head *uninitialized_var(pl); | 263 | struct intel_engine_cs *engine; |
257 | struct intel_engine_cs *engine, *last; | ||
258 | struct i915_dependency *dep, *p; | 264 | struct i915_dependency *dep, *p; |
259 | struct i915_dependency stack; | 265 | struct i915_dependency stack; |
260 | const int prio = attr->priority; | 266 | const int prio = attr->priority; |
267 | struct sched_cache cache; | ||
261 | LIST_HEAD(dfs); | 268 | LIST_HEAD(dfs); |
262 | 269 | ||
263 | /* Needed in order to use the temporary link inside i915_dependency */ | 270 | /* Needed in order to use the temporary link inside i915_dependency */ |
@@ -328,7 +335,7 @@ static void __i915_schedule(struct i915_request *rq, | |||
328 | __list_del_entry(&stack.dfs_link); | 335 | __list_del_entry(&stack.dfs_link); |
329 | } | 336 | } |
330 | 337 | ||
331 | last = NULL; | 338 | memset(&cache, 0, sizeof(cache)); |
332 | engine = rq->engine; | 339 | engine = rq->engine; |
333 | spin_lock_irq(&engine->timeline.lock); | 340 | spin_lock_irq(&engine->timeline.lock); |
334 | 341 | ||
@@ -338,7 +345,7 @@ static void __i915_schedule(struct i915_request *rq, | |||
338 | 345 | ||
339 | INIT_LIST_HEAD(&dep->dfs_link); | 346 | INIT_LIST_HEAD(&dep->dfs_link); |
340 | 347 | ||
341 | engine = sched_lock_engine(node, engine); | 348 | engine = sched_lock_engine(node, engine, &cache); |
342 | lockdep_assert_held(&engine->timeline.lock); | 349 | lockdep_assert_held(&engine->timeline.lock); |
343 | 350 | ||
344 | /* Recheck after acquiring the engine->timeline.lock */ | 351 | /* Recheck after acquiring the engine->timeline.lock */ |
@@ -347,11 +354,11 @@ static void __i915_schedule(struct i915_request *rq, | |||
347 | 354 | ||
348 | node->attr.priority = prio; | 355 | node->attr.priority = prio; |
349 | if (!list_empty(&node->link)) { | 356 | if (!list_empty(&node->link)) { |
350 | if (last != engine) { | 357 | if (!cache.priolist) |
351 | pl = i915_sched_lookup_priolist(engine, prio); | 358 | cache.priolist = |
352 | last = engine; | 359 | i915_sched_lookup_priolist(engine, |
353 | } | 360 | prio); |
354 | list_move_tail(&node->link, pl); | 361 | list_move_tail(&node->link, cache.priolist); |
355 | } else { | 362 | } else { |
356 | /* | 363 | /* |
357 | * If the request is not in the priolist queue because | 364 | * If the request is not in the priolist queue because |
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index cacaa1d04d17..09ed90c0ba00 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
@@ -106,16 +106,6 @@ bool intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) | |||
106 | 106 | ||
107 | GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_SIGNAL, | 107 | GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_SIGNAL, |
108 | &rq->fence.flags)); | 108 | &rq->fence.flags)); |
109 | clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); | ||
110 | |||
111 | /* | ||
112 | * We may race with direct invocation of | ||
113 | * dma_fence_signal(), e.g. i915_request_retire(), | ||
114 | * in which case we can skip processing it ourselves. | ||
115 | */ | ||
116 | if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, | ||
117 | &rq->fence.flags)) | ||
118 | continue; | ||
119 | 109 | ||
120 | /* | 110 | /* |
121 | * Queue for execution after dropping the signaling | 111 | * Queue for execution after dropping the signaling |
@@ -123,6 +113,14 @@ bool intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) | |||
123 | * more signalers to the same context or engine. | 113 | * more signalers to the same context or engine. |
124 | */ | 114 | */ |
125 | i915_request_get(rq); | 115 | i915_request_get(rq); |
116 | |||
117 | /* | ||
118 | * We may race with direct invocation of | ||
119 | * dma_fence_signal(), e.g. i915_request_retire(), | ||
120 | * so we need to acquire our reference to the request | ||
121 | * before we cancel the breadcrumb. | ||
122 | */ | ||
123 | clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); | ||
126 | list_add_tail(&rq->signal_link, &signal); | 124 | list_add_tail(&rq->signal_link, &signal); |
127 | } | 125 | } |
128 | 126 | ||
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index ca705546a0ab..14d580cdefd3 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -3568,6 +3568,13 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder, | |||
3568 | { | 3568 | { |
3569 | if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) | 3569 | if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) |
3570 | intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state); | 3570 | intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state); |
3571 | |||
3572 | if (conn_state->content_protection == | ||
3573 | DRM_MODE_CONTENT_PROTECTION_DESIRED) | ||
3574 | intel_hdcp_enable(to_intel_connector(conn_state->connector)); | ||
3575 | else if (conn_state->content_protection == | ||
3576 | DRM_MODE_CONTENT_PROTECTION_UNDESIRED) | ||
3577 | intel_hdcp_disable(to_intel_connector(conn_state->connector)); | ||
3571 | } | 3578 | } |
3572 | 3579 | ||
3573 | static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder, | 3580 | static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder, |
@@ -3962,12 +3969,7 @@ static int modeset_pipe(struct drm_crtc *crtc, | |||
3962 | goto out; | 3969 | goto out; |
3963 | 3970 | ||
3964 | ret = drm_atomic_commit(state); | 3971 | ret = drm_atomic_commit(state); |
3965 | if (ret) | 3972 | out: |
3966 | goto out; | ||
3967 | |||
3968 | return 0; | ||
3969 | |||
3970 | out: | ||
3971 | drm_atomic_state_put(state); | 3973 | drm_atomic_state_put(state); |
3972 | 3974 | ||
3973 | return ret; | 3975 | return ret; |
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index d00d0bb07784..7eb58a9d1319 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c | |||
@@ -710,47 +710,45 @@ __sseu_prepare(struct drm_i915_private *i915, | |||
710 | unsigned int flags, | 710 | unsigned int flags, |
711 | struct i915_gem_context *ctx, | 711 | struct i915_gem_context *ctx, |
712 | struct intel_engine_cs *engine, | 712 | struct intel_engine_cs *engine, |
713 | struct igt_spinner **spin_out) | 713 | struct igt_spinner **spin) |
714 | { | 714 | { |
715 | int ret = 0; | 715 | struct i915_request *rq; |
716 | 716 | int ret; | |
717 | if (flags & (TEST_BUSY | TEST_RESET)) { | ||
718 | struct igt_spinner *spin; | ||
719 | struct i915_request *rq; | ||
720 | 717 | ||
721 | spin = kzalloc(sizeof(*spin), GFP_KERNEL); | 718 | *spin = NULL; |
722 | if (!spin) { | 719 | if (!(flags & (TEST_BUSY | TEST_RESET))) |
723 | ret = -ENOMEM; | 720 | return 0; |
724 | goto out; | ||
725 | } | ||
726 | 721 | ||
727 | ret = igt_spinner_init(spin, i915); | 722 | *spin = kzalloc(sizeof(**spin), GFP_KERNEL); |
728 | if (ret) | 723 | if (!*spin) |
729 | return ret; | 724 | return -ENOMEM; |
730 | 725 | ||
731 | rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP); | 726 | ret = igt_spinner_init(*spin, i915); |
732 | if (IS_ERR(rq)) { | 727 | if (ret) |
733 | ret = PTR_ERR(rq); | 728 | goto err_free; |
734 | igt_spinner_fini(spin); | ||
735 | kfree(spin); | ||
736 | goto out; | ||
737 | } | ||
738 | 729 | ||
739 | i915_request_add(rq); | 730 | rq = igt_spinner_create_request(*spin, ctx, engine, MI_NOOP); |
731 | if (IS_ERR(rq)) { | ||
732 | ret = PTR_ERR(rq); | ||
733 | goto err_fini; | ||
734 | } | ||
740 | 735 | ||
741 | if (!igt_wait_for_spinner(spin, rq)) { | 736 | i915_request_add(rq); |
742 | pr_err("%s: Spinner failed to start!\n", name); | ||
743 | igt_spinner_end(spin); | ||
744 | igt_spinner_fini(spin); | ||
745 | kfree(spin); | ||
746 | ret = -ETIMEDOUT; | ||
747 | goto out; | ||
748 | } | ||
749 | 737 | ||
750 | *spin_out = spin; | 738 | if (!igt_wait_for_spinner(*spin, rq)) { |
739 | pr_err("%s: Spinner failed to start!\n", name); | ||
740 | ret = -ETIMEDOUT; | ||
741 | goto err_end; | ||
751 | } | 742 | } |
752 | 743 | ||
753 | out: | 744 | return 0; |
745 | |||
746 | err_end: | ||
747 | igt_spinner_end(*spin); | ||
748 | err_fini: | ||
749 | igt_spinner_fini(*spin); | ||
750 | err_free: | ||
751 | kfree(fetch_and_zero(spin)); | ||
754 | return ret; | 752 | return ret; |
755 | } | 753 | } |
756 | 754 | ||
@@ -897,22 +895,23 @@ __sseu_test(struct drm_i915_private *i915, | |||
897 | 895 | ||
898 | ret = __sseu_prepare(i915, name, flags, ctx, engine, &spin); | 896 | ret = __sseu_prepare(i915, name, flags, ctx, engine, &spin); |
899 | if (ret) | 897 | if (ret) |
900 | goto out; | 898 | goto out_context; |
901 | 899 | ||
902 | ret = __i915_gem_context_reconfigure_sseu(ctx, engine, sseu); | 900 | ret = __i915_gem_context_reconfigure_sseu(ctx, engine, sseu); |
903 | if (ret) | 901 | if (ret) |
904 | goto out; | 902 | goto out_spin; |
905 | 903 | ||
906 | ret = __sseu_finish(i915, name, flags, ctx, kctx, engine, obj, | 904 | ret = __sseu_finish(i915, name, flags, ctx, kctx, engine, obj, |
907 | hweight32(sseu.slice_mask), spin); | 905 | hweight32(sseu.slice_mask), spin); |
908 | 906 | ||
909 | out: | 907 | out_spin: |
910 | if (spin) { | 908 | if (spin) { |
911 | igt_spinner_end(spin); | 909 | igt_spinner_end(spin); |
912 | igt_spinner_fini(spin); | 910 | igt_spinner_fini(spin); |
913 | kfree(spin); | 911 | kfree(spin); |
914 | } | 912 | } |
915 | 913 | ||
914 | out_context: | ||
916 | kernel_context_close(kctx); | 915 | kernel_context_close(kctx); |
917 | 916 | ||
918 | return ret; | 917 | return ret; |