diff options
author | Dave Airlie <airlied@redhat.com> | 2016-01-17 16:02:19 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-01-17 16:02:19 -0500 |
commit | 1df59b8497f47495e873c23abd6d3d290c730505 (patch) | |
tree | 8fe819870ce75e21c413aabaa483b699c186d938 /drivers/gpu | |
parent | 28f03607bb2e7a3dab71d0a377fd13f6ed3ebb9f (diff) | |
parent | 48ea1e32c39db94c59b63580b965222c7782112f (diff) |
Merge tag 'drm-intel-next-fixes-2016-01-14' of git://anongit.freedesktop.org/drm-intel into drm-next
misc i915 fixes all over the place.
* tag 'drm-intel-next-fixes-2016-01-14' of git://anongit.freedesktop.org/drm-intel:
drm/i915/gen9: Set PIN_ZONE_4G end to 4GB - 1 page
drm/i915: Widen return value for reservation_object_wait_timeout_rcu to long.
drm/i915: intel_hpd_init(): Fix suspend/resume reprobing
drm/i915: shut up gen8+ SDE irq dmesg noise, again
drm/i915: Restore inhibiting the load of the default context
drm/i915: Tune down rpm wakelock debug checks
drm/i915: Avoid writing relocs with addresses in non-canonical form
drm/i915: Move Braswell stop_machine GGTT insertion workaround
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 52 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hotplug.c | 9 |
8 files changed, 108 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6c60e04fc09c..ddc21d4b388d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3488,7 +3488,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | |||
3488 | if (flags & PIN_MAPPABLE) | 3488 | if (flags & PIN_MAPPABLE) |
3489 | end = min_t(u64, end, dev_priv->gtt.mappable_end); | 3489 | end = min_t(u64, end, dev_priv->gtt.mappable_end); |
3490 | if (flags & PIN_ZONE_4G) | 3490 | if (flags & PIN_ZONE_4G) |
3491 | end = min_t(u64, end, (1ULL << 32)); | 3491 | end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE); |
3492 | 3492 | ||
3493 | if (alignment == 0) | 3493 | if (alignment == 0) |
3494 | alignment = flags & PIN_MAPPABLE ? fence_alignment : | 3494 | alignment = flags & PIN_MAPPABLE ? fence_alignment : |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 900ffd044db8..c25083c78ba7 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -347,6 +347,10 @@ void i915_gem_context_reset(struct drm_device *dev) | |||
347 | i915_gem_context_unreference(lctx); | 347 | i915_gem_context_unreference(lctx); |
348 | ring->last_context = NULL; | 348 | ring->last_context = NULL; |
349 | } | 349 | } |
350 | |||
351 | /* Force the GPU state to be reinitialised on enabling */ | ||
352 | if (ring->default_context) | ||
353 | ring->default_context->legacy_hw_ctx.initialized = false; | ||
350 | } | 354 | } |
351 | } | 355 | } |
352 | 356 | ||
@@ -715,7 +719,7 @@ static int do_switch(struct drm_i915_gem_request *req) | |||
715 | if (ret) | 719 | if (ret) |
716 | goto unpin_out; | 720 | goto unpin_out; |
717 | 721 | ||
718 | if (!to->legacy_hw_ctx.initialized) { | 722 | if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) { |
719 | hw_flags |= MI_RESTORE_INHIBIT; | 723 | hw_flags |= MI_RESTORE_INHIBIT; |
720 | /* NB: If we inhibit the restore, the context is not allowed to | 724 | /* NB: If we inhibit the restore, the context is not allowed to |
721 | * die because future work may end up depending on valid address | 725 | * die because future work may end up depending on valid address |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5d01ea680dc1..dccb517361b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -249,6 +249,31 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) | |||
249 | obj->cache_level != I915_CACHE_NONE); | 249 | obj->cache_level != I915_CACHE_NONE); |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Used to convert any address to canonical form. | ||
253 | * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS, | ||
254 | * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the | ||
255 | * addresses to be in a canonical form: | ||
256 | * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct | ||
257 | * canonical form [63:48] == [47]." | ||
258 | */ | ||
259 | #define GEN8_HIGH_ADDRESS_BIT 47 | ||
260 | static inline uint64_t gen8_canonical_addr(uint64_t address) | ||
261 | { | ||
262 | return sign_extend64(address, GEN8_HIGH_ADDRESS_BIT); | ||
263 | } | ||
264 | |||
265 | static inline uint64_t gen8_noncanonical_addr(uint64_t address) | ||
266 | { | ||
267 | return address & ((1ULL << (GEN8_HIGH_ADDRESS_BIT + 1)) - 1); | ||
268 | } | ||
269 | |||
270 | static inline uint64_t | ||
271 | relocation_target(struct drm_i915_gem_relocation_entry *reloc, | ||
272 | uint64_t target_offset) | ||
273 | { | ||
274 | return gen8_canonical_addr((int)reloc->delta + target_offset); | ||
275 | } | ||
276 | |||
252 | static int | 277 | static int |
253 | relocate_entry_cpu(struct drm_i915_gem_object *obj, | 278 | relocate_entry_cpu(struct drm_i915_gem_object *obj, |
254 | struct drm_i915_gem_relocation_entry *reloc, | 279 | struct drm_i915_gem_relocation_entry *reloc, |
@@ -256,7 +281,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj, | |||
256 | { | 281 | { |
257 | struct drm_device *dev = obj->base.dev; | 282 | struct drm_device *dev = obj->base.dev; |
258 | uint32_t page_offset = offset_in_page(reloc->offset); | 283 | uint32_t page_offset = offset_in_page(reloc->offset); |
259 | uint64_t delta = reloc->delta + target_offset; | 284 | uint64_t delta = relocation_target(reloc, target_offset); |
260 | char *vaddr; | 285 | char *vaddr; |
261 | int ret; | 286 | int ret; |
262 | 287 | ||
@@ -292,7 +317,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, | |||
292 | { | 317 | { |
293 | struct drm_device *dev = obj->base.dev; | 318 | struct drm_device *dev = obj->base.dev; |
294 | struct drm_i915_private *dev_priv = dev->dev_private; | 319 | struct drm_i915_private *dev_priv = dev->dev_private; |
295 | uint64_t delta = reloc->delta + target_offset; | 320 | uint64_t delta = relocation_target(reloc, target_offset); |
296 | uint64_t offset; | 321 | uint64_t offset; |
297 | void __iomem *reloc_page; | 322 | void __iomem *reloc_page; |
298 | int ret; | 323 | int ret; |
@@ -347,7 +372,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj, | |||
347 | { | 372 | { |
348 | struct drm_device *dev = obj->base.dev; | 373 | struct drm_device *dev = obj->base.dev; |
349 | uint32_t page_offset = offset_in_page(reloc->offset); | 374 | uint32_t page_offset = offset_in_page(reloc->offset); |
350 | uint64_t delta = (int)reloc->delta + target_offset; | 375 | uint64_t delta = relocation_target(reloc, target_offset); |
351 | char *vaddr; | 376 | char *vaddr; |
352 | int ret; | 377 | int ret; |
353 | 378 | ||
@@ -395,7 +420,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
395 | target_i915_obj = target_vma->obj; | 420 | target_i915_obj = target_vma->obj; |
396 | target_obj = &target_vma->obj->base; | 421 | target_obj = &target_vma->obj->base; |
397 | 422 | ||
398 | target_offset = target_vma->node.start; | 423 | target_offset = gen8_canonical_addr(target_vma->node.start); |
399 | 424 | ||
400 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and | 425 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and |
401 | * pipe_control writes because the gpu doesn't properly redirect them | 426 | * pipe_control writes because the gpu doesn't properly redirect them |
@@ -994,6 +1019,21 @@ validate_exec_list(struct drm_device *dev, | |||
994 | if (exec[i].flags & invalid_flags) | 1019 | if (exec[i].flags & invalid_flags) |
995 | return -EINVAL; | 1020 | return -EINVAL; |
996 | 1021 | ||
1022 | /* Offset can be used as input (EXEC_OBJECT_PINNED), reject | ||
1023 | * any non-page-aligned or non-canonical addresses. | ||
1024 | */ | ||
1025 | if (exec[i].flags & EXEC_OBJECT_PINNED) { | ||
1026 | if (exec[i].offset != | ||
1027 | gen8_canonical_addr(exec[i].offset & PAGE_MASK)) | ||
1028 | return -EINVAL; | ||
1029 | |||
1030 | /* From drm_mm perspective address space is continuous, | ||
1031 | * so from this point we're always using non-canonical | ||
1032 | * form internally. | ||
1033 | */ | ||
1034 | exec[i].offset = gen8_noncanonical_addr(exec[i].offset); | ||
1035 | } | ||
1036 | |||
997 | if (exec[i].alignment && !is_power_of_2(exec[i].alignment)) | 1037 | if (exec[i].alignment && !is_power_of_2(exec[i].alignment)) |
998 | return -EINVAL; | 1038 | return -EINVAL; |
999 | 1039 | ||
@@ -1687,6 +1727,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1687 | 1727 | ||
1688 | /* Copy the new buffer offsets back to the user's exec list. */ | 1728 | /* Copy the new buffer offsets back to the user's exec list. */ |
1689 | for (i = 0; i < args->buffer_count; i++) { | 1729 | for (i = 0; i < args->buffer_count; i++) { |
1730 | exec2_list[i].offset = | ||
1731 | gen8_canonical_addr(exec2_list[i].offset); | ||
1690 | ret = __copy_to_user(&user_exec_list[i].offset, | 1732 | ret = __copy_to_user(&user_exec_list[i].offset, |
1691 | &exec2_list[i].offset, | 1733 | &exec2_list[i].offset, |
1692 | sizeof(user_exec_list[i].offset)); | 1734 | sizeof(user_exec_list[i].offset)); |
@@ -1752,6 +1794,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data, | |||
1752 | int i; | 1794 | int i; |
1753 | 1795 | ||
1754 | for (i = 0; i < args->buffer_count; i++) { | 1796 | for (i = 0; i < args->buffer_count; i++) { |
1797 | exec2_list[i].offset = | ||
1798 | gen8_canonical_addr(exec2_list[i].offset); | ||
1755 | ret = __copy_to_user(&user_exec_list[i].offset, | 1799 | ret = __copy_to_user(&user_exec_list[i].offset, |
1756 | &exec2_list[i].offset, | 1800 | &exec2_list[i].offset, |
1757 | sizeof(user_exec_list[i].offset)); | 1801 | sizeof(user_exec_list[i].offset)); |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 52bc6c3dfe04..56f4f2e58d53 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -2384,6 +2384,32 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, | |||
2384 | assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); | 2384 | assert_rpm_atomic_end(dev_priv, rpm_atomic_seq); |
2385 | } | 2385 | } |
2386 | 2386 | ||
2387 | struct insert_entries { | ||
2388 | struct i915_address_space *vm; | ||
2389 | struct sg_table *st; | ||
2390 | uint64_t start; | ||
2391 | enum i915_cache_level level; | ||
2392 | u32 flags; | ||
2393 | }; | ||
2394 | |||
2395 | static int gen8_ggtt_insert_entries__cb(void *_arg) | ||
2396 | { | ||
2397 | struct insert_entries *arg = _arg; | ||
2398 | gen8_ggtt_insert_entries(arg->vm, arg->st, | ||
2399 | arg->start, arg->level, arg->flags); | ||
2400 | return 0; | ||
2401 | } | ||
2402 | |||
2403 | static void gen8_ggtt_insert_entries__BKL(struct i915_address_space *vm, | ||
2404 | struct sg_table *st, | ||
2405 | uint64_t start, | ||
2406 | enum i915_cache_level level, | ||
2407 | u32 flags) | ||
2408 | { | ||
2409 | struct insert_entries arg = { vm, st, start, level, flags }; | ||
2410 | stop_machine(gen8_ggtt_insert_entries__cb, &arg, NULL); | ||
2411 | } | ||
2412 | |||
2387 | /* | 2413 | /* |
2388 | * Binds an object into the global gtt with the specified cache level. The object | 2414 | * Binds an object into the global gtt with the specified cache level. The object |
2389 | * will be accessible to the GPU via commands whose operands reference offsets | 2415 | * will be accessible to the GPU via commands whose operands reference offsets |
@@ -2560,26 +2586,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, | |||
2560 | return 0; | 2586 | return 0; |
2561 | } | 2587 | } |
2562 | 2588 | ||
2563 | struct ggtt_bind_vma__cb { | ||
2564 | struct i915_vma *vma; | ||
2565 | enum i915_cache_level cache_level; | ||
2566 | u32 flags; | ||
2567 | }; | ||
2568 | |||
2569 | static int ggtt_bind_vma__cb(void *_arg) | ||
2570 | { | ||
2571 | struct ggtt_bind_vma__cb *arg = _arg; | ||
2572 | return ggtt_bind_vma(arg->vma, arg->cache_level, arg->flags); | ||
2573 | } | ||
2574 | |||
2575 | static int ggtt_bind_vma__BKL(struct i915_vma *vma, | ||
2576 | enum i915_cache_level cache_level, | ||
2577 | u32 flags) | ||
2578 | { | ||
2579 | struct ggtt_bind_vma__cb arg = { vma, cache_level, flags }; | ||
2580 | return stop_machine(ggtt_bind_vma__cb, &arg, NULL); | ||
2581 | } | ||
2582 | |||
2583 | static int aliasing_gtt_bind_vma(struct i915_vma *vma, | 2589 | static int aliasing_gtt_bind_vma(struct i915_vma *vma, |
2584 | enum i915_cache_level cache_level, | 2590 | enum i915_cache_level cache_level, |
2585 | u32 flags) | 2591 | u32 flags) |
@@ -3048,8 +3054,8 @@ static int gen8_gmch_probe(struct drm_device *dev, | |||
3048 | dev_priv->gtt.base.bind_vma = ggtt_bind_vma; | 3054 | dev_priv->gtt.base.bind_vma = ggtt_bind_vma; |
3049 | dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; | 3055 | dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; |
3050 | 3056 | ||
3051 | if (IS_CHERRYVIEW(dev)) | 3057 | if (IS_CHERRYVIEW(dev_priv)) |
3052 | dev_priv->gtt.base.bind_vma = ggtt_bind_vma__BKL; | 3058 | dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; |
3053 | 3059 | ||
3054 | return ret; | 3060 | return ret; |
3055 | } | 3061 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3f8c753997ba..fa8afa7860ae 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -2414,9 +2414,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) | |||
2414 | spt_irq_handler(dev, pch_iir); | 2414 | spt_irq_handler(dev, pch_iir); |
2415 | else | 2415 | else |
2416 | cpt_irq_handler(dev, pch_iir); | 2416 | cpt_irq_handler(dev, pch_iir); |
2417 | } else | 2417 | } else { |
2418 | DRM_ERROR("The master control interrupt lied (SDE)!\n"); | 2418 | /* |
2419 | 2419 | * Like on previous PCH there seems to be something | |
2420 | * fishy going on with forwarding PCH interrupts. | ||
2421 | */ | ||
2422 | DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n"); | ||
2423 | } | ||
2420 | } | 2424 | } |
2421 | 2425 | ||
2422 | I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); | 2426 | I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ceaea7a3641a..580d094bfc1e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -13763,13 +13763,15 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
13763 | 13763 | ||
13764 | /* For framebuffer backed by dmabuf, wait for fence */ | 13764 | /* For framebuffer backed by dmabuf, wait for fence */ |
13765 | if (obj && obj->base.dma_buf) { | 13765 | if (obj && obj->base.dma_buf) { |
13766 | ret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, | 13766 | long lret; |
13767 | false, true, | 13767 | |
13768 | MAX_SCHEDULE_TIMEOUT); | 13768 | lret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv, |
13769 | if (ret == -ERESTARTSYS) | 13769 | false, true, |
13770 | return ret; | 13770 | MAX_SCHEDULE_TIMEOUT); |
13771 | if (lret == -ERESTARTSYS) | ||
13772 | return lret; | ||
13771 | 13773 | ||
13772 | WARN_ON(ret < 0); | 13774 | WARN(lret < 0, "waiting returns %li\n", lret); |
13773 | } | 13775 | } |
13774 | 13776 | ||
13775 | if (!obj) { | 13777 | if (!obj) { |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d523ebb2f89d..ea5415851c6e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -1442,8 +1442,10 @@ static inline void | |||
1442 | assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) | 1442 | assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) |
1443 | { | 1443 | { |
1444 | assert_rpm_device_not_suspended(dev_priv); | 1444 | assert_rpm_device_not_suspended(dev_priv); |
1445 | WARN_ONCE(!atomic_read(&dev_priv->pm.wakeref_count), | 1445 | /* FIXME: Needs to be converted back to WARN_ONCE, but currently causes |
1446 | "RPM wakelock ref not held during HW access"); | 1446 | * too much noise. */ |
1447 | if (!atomic_read(&dev_priv->pm.wakeref_count)) | ||
1448 | DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access"); | ||
1447 | } | 1449 | } |
1448 | 1450 | ||
1449 | static inline int | 1451 | static inline int |
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index a294a3cbaea1..bee673005d48 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c | |||
@@ -468,9 +468,14 @@ void intel_hpd_init(struct drm_i915_private *dev_priv) | |||
468 | list_for_each_entry(connector, &mode_config->connector_list, head) { | 468 | list_for_each_entry(connector, &mode_config->connector_list, head) { |
469 | struct intel_connector *intel_connector = to_intel_connector(connector); | 469 | struct intel_connector *intel_connector = to_intel_connector(connector); |
470 | connector->polled = intel_connector->polled; | 470 | connector->polled = intel_connector->polled; |
471 | if (connector->encoder && !connector->polled && I915_HAS_HOTPLUG(dev) && intel_connector->encoder->hpd_pin > HPD_NONE) | 471 | |
472 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 472 | /* MST has a dynamic intel_connector->encoder and it's reprobing |
473 | * is all handled by the MST helpers. */ | ||
473 | if (intel_connector->mst_port) | 474 | if (intel_connector->mst_port) |
475 | continue; | ||
476 | |||
477 | if (!connector->polled && I915_HAS_HOTPLUG(dev) && | ||
478 | intel_connector->encoder->hpd_pin > HPD_NONE) | ||
474 | connector->polled = DRM_CONNECTOR_POLL_HPD; | 479 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
475 | } | 480 | } |
476 | 481 | ||