diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_execbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 227 |
1 files changed, 118 insertions, 109 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 60998fc4e5b2..1a0611bb576b 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #define __EXEC_OBJECT_HAS_PIN (1<<31) | 36 | #define __EXEC_OBJECT_HAS_PIN (1<<31) |
37 | #define __EXEC_OBJECT_HAS_FENCE (1<<30) | 37 | #define __EXEC_OBJECT_HAS_FENCE (1<<30) |
38 | #define __EXEC_OBJECT_NEEDS_MAP (1<<29) | ||
38 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) | 39 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) |
39 | 40 | ||
40 | #define BATCH_OFFSET_BIAS (256*1024) | 41 | #define BATCH_OFFSET_BIAS (256*1024) |
@@ -94,7 +95,6 @@ eb_lookup_vmas(struct eb_vmas *eb, | |||
94 | struct i915_address_space *vm, | 95 | struct i915_address_space *vm, |
95 | struct drm_file *file) | 96 | struct drm_file *file) |
96 | { | 97 | { |
97 | struct drm_i915_private *dev_priv = vm->dev->dev_private; | ||
98 | struct drm_i915_gem_object *obj; | 98 | struct drm_i915_gem_object *obj; |
99 | struct list_head objects; | 99 | struct list_head objects; |
100 | int i, ret; | 100 | int i, ret; |
@@ -129,20 +129,6 @@ eb_lookup_vmas(struct eb_vmas *eb, | |||
129 | i = 0; | 129 | i = 0; |
130 | while (!list_empty(&objects)) { | 130 | while (!list_empty(&objects)) { |
131 | struct i915_vma *vma; | 131 | struct i915_vma *vma; |
132 | struct i915_address_space *bind_vm = vm; | ||
133 | |||
134 | if (exec[i].flags & EXEC_OBJECT_NEEDS_GTT && | ||
135 | USES_FULL_PPGTT(vm->dev)) { | ||
136 | ret = -EINVAL; | ||
137 | goto err; | ||
138 | } | ||
139 | |||
140 | /* If we have secure dispatch, or the userspace assures us that | ||
141 | * they know what they're doing, use the GGTT VM. | ||
142 | */ | ||
143 | if (((args->flags & I915_EXEC_SECURE) && | ||
144 | (i == (args->buffer_count - 1)))) | ||
145 | bind_vm = &dev_priv->gtt.base; | ||
146 | 132 | ||
147 | obj = list_first_entry(&objects, | 133 | obj = list_first_entry(&objects, |
148 | struct drm_i915_gem_object, | 134 | struct drm_i915_gem_object, |
@@ -156,7 +142,7 @@ eb_lookup_vmas(struct eb_vmas *eb, | |||
156 | * from the (obj, vm) we don't run the risk of creating | 142 | * from the (obj, vm) we don't run the risk of creating |
157 | * duplicated vmas for the same vm. | 143 | * duplicated vmas for the same vm. |
158 | */ | 144 | */ |
159 | vma = i915_gem_obj_lookup_or_create_vma(obj, bind_vm); | 145 | vma = i915_gem_obj_lookup_or_create_vma(obj, vm); |
160 | if (IS_ERR(vma)) { | 146 | if (IS_ERR(vma)) { |
161 | DRM_DEBUG("Failed to lookup VMA\n"); | 147 | DRM_DEBUG("Failed to lookup VMA\n"); |
162 | ret = PTR_ERR(vma); | 148 | ret = PTR_ERR(vma); |
@@ -307,7 +293,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, | |||
307 | struct drm_device *dev = obj->base.dev; | 293 | struct drm_device *dev = obj->base.dev; |
308 | struct drm_i915_private *dev_priv = dev->dev_private; | 294 | struct drm_i915_private *dev_priv = dev->dev_private; |
309 | uint64_t delta = reloc->delta + target_offset; | 295 | uint64_t delta = reloc->delta + target_offset; |
310 | uint32_t __iomem *reloc_entry; | 296 | uint64_t offset; |
311 | void __iomem *reloc_page; | 297 | void __iomem *reloc_page; |
312 | int ret; | 298 | int ret; |
313 | 299 | ||
@@ -320,25 +306,24 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, | |||
320 | return ret; | 306 | return ret; |
321 | 307 | ||
322 | /* Map the page containing the relocation we're going to perform. */ | 308 | /* Map the page containing the relocation we're going to perform. */ |
323 | reloc->offset += i915_gem_obj_ggtt_offset(obj); | 309 | offset = i915_gem_obj_ggtt_offset(obj); |
310 | offset += reloc->offset; | ||
324 | reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, | 311 | reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, |
325 | reloc->offset & PAGE_MASK); | 312 | offset & PAGE_MASK); |
326 | reloc_entry = (uint32_t __iomem *) | 313 | iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset)); |
327 | (reloc_page + offset_in_page(reloc->offset)); | ||
328 | iowrite32(lower_32_bits(delta), reloc_entry); | ||
329 | 314 | ||
330 | if (INTEL_INFO(dev)->gen >= 8) { | 315 | if (INTEL_INFO(dev)->gen >= 8) { |
331 | reloc_entry += 1; | 316 | offset += sizeof(uint32_t); |
332 | 317 | ||
333 | if (offset_in_page(reloc->offset + sizeof(uint32_t)) == 0) { | 318 | if (offset_in_page(offset) == 0) { |
334 | io_mapping_unmap_atomic(reloc_page); | 319 | io_mapping_unmap_atomic(reloc_page); |
335 | reloc_page = io_mapping_map_atomic_wc( | 320 | reloc_page = |
336 | dev_priv->gtt.mappable, | 321 | io_mapping_map_atomic_wc(dev_priv->gtt.mappable, |
337 | reloc->offset + sizeof(uint32_t)); | 322 | offset); |
338 | reloc_entry = reloc_page; | ||
339 | } | 323 | } |
340 | 324 | ||
341 | iowrite32(upper_32_bits(delta), reloc_entry); | 325 | iowrite32(upper_32_bits(delta), |
326 | reloc_page + offset_in_page(offset)); | ||
342 | } | 327 | } |
343 | 328 | ||
344 | io_mapping_unmap_atomic(reloc_page); | 329 | io_mapping_unmap_atomic(reloc_page); |
@@ -535,34 +520,18 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb) | |||
535 | } | 520 | } |
536 | 521 | ||
537 | static int | 522 | static int |
538 | need_reloc_mappable(struct i915_vma *vma) | ||
539 | { | ||
540 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | ||
541 | return entry->relocation_count && !use_cpu_reloc(vma->obj) && | ||
542 | i915_is_ggtt(vma->vm); | ||
543 | } | ||
544 | |||
545 | static int | ||
546 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | 523 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, |
547 | struct intel_engine_cs *ring, | 524 | struct intel_engine_cs *ring, |
548 | bool *need_reloc) | 525 | bool *need_reloc) |
549 | { | 526 | { |
550 | struct drm_i915_gem_object *obj = vma->obj; | 527 | struct drm_i915_gem_object *obj = vma->obj; |
551 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | 528 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
552 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; | ||
553 | bool need_fence; | ||
554 | uint64_t flags; | 529 | uint64_t flags; |
555 | int ret; | 530 | int ret; |
556 | 531 | ||
557 | flags = 0; | 532 | flags = 0; |
558 | 533 | if (entry->flags & __EXEC_OBJECT_NEEDS_MAP) | |
559 | need_fence = | ||
560 | has_fenced_gpu_access && | ||
561 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
562 | obj->tiling_mode != I915_TILING_NONE; | ||
563 | if (need_fence || need_reloc_mappable(vma)) | ||
564 | flags |= PIN_MAPPABLE; | 534 | flags |= PIN_MAPPABLE; |
565 | |||
566 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) | 535 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) |
567 | flags |= PIN_GLOBAL; | 536 | flags |= PIN_GLOBAL; |
568 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) | 537 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) |
@@ -574,17 +543,13 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
574 | 543 | ||
575 | entry->flags |= __EXEC_OBJECT_HAS_PIN; | 544 | entry->flags |= __EXEC_OBJECT_HAS_PIN; |
576 | 545 | ||
577 | if (has_fenced_gpu_access) { | 546 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { |
578 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { | 547 | ret = i915_gem_object_get_fence(obj); |
579 | ret = i915_gem_object_get_fence(obj); | 548 | if (ret) |
580 | if (ret) | 549 | return ret; |
581 | return ret; | ||
582 | |||
583 | if (i915_gem_object_pin_fence(obj)) | ||
584 | entry->flags |= __EXEC_OBJECT_HAS_FENCE; | ||
585 | 550 | ||
586 | obj->pending_fenced_gpu_access = true; | 551 | if (i915_gem_object_pin_fence(obj)) |
587 | } | 552 | entry->flags |= __EXEC_OBJECT_HAS_FENCE; |
588 | } | 553 | } |
589 | 554 | ||
590 | if (entry->offset != vma->node.start) { | 555 | if (entry->offset != vma->node.start) { |
@@ -601,26 +566,40 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
601 | } | 566 | } |
602 | 567 | ||
603 | static bool | 568 | static bool |
604 | eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access) | 569 | need_reloc_mappable(struct i915_vma *vma) |
605 | { | 570 | { |
606 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | 571 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
607 | struct drm_i915_gem_object *obj = vma->obj; | ||
608 | bool need_fence, need_mappable; | ||
609 | 572 | ||
610 | need_fence = | 573 | if (entry->relocation_count == 0) |
611 | has_fenced_gpu_access && | 574 | return false; |
612 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | 575 | |
613 | obj->tiling_mode != I915_TILING_NONE; | 576 | if (!i915_is_ggtt(vma->vm)) |
614 | need_mappable = need_fence || need_reloc_mappable(vma); | 577 | return false; |
578 | |||
579 | /* See also use_cpu_reloc() */ | ||
580 | if (HAS_LLC(vma->obj->base.dev)) | ||
581 | return false; | ||
615 | 582 | ||
616 | WARN_ON((need_mappable || need_fence) && | 583 | if (vma->obj->base.write_domain == I915_GEM_DOMAIN_CPU) |
584 | return false; | ||
585 | |||
586 | return true; | ||
587 | } | ||
588 | |||
589 | static bool | ||
590 | eb_vma_misplaced(struct i915_vma *vma) | ||
591 | { | ||
592 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | ||
593 | struct drm_i915_gem_object *obj = vma->obj; | ||
594 | |||
595 | WARN_ON(entry->flags & __EXEC_OBJECT_NEEDS_MAP && | ||
617 | !i915_is_ggtt(vma->vm)); | 596 | !i915_is_ggtt(vma->vm)); |
618 | 597 | ||
619 | if (entry->alignment && | 598 | if (entry->alignment && |
620 | vma->node.start & (entry->alignment - 1)) | 599 | vma->node.start & (entry->alignment - 1)) |
621 | return true; | 600 | return true; |
622 | 601 | ||
623 | if (need_mappable && !obj->map_and_fenceable) | 602 | if (entry->flags & __EXEC_OBJECT_NEEDS_MAP && !obj->map_and_fenceable) |
624 | return true; | 603 | return true; |
625 | 604 | ||
626 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && | 605 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && |
@@ -642,9 +621,6 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, | |||
642 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; | 621 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
643 | int retry; | 622 | int retry; |
644 | 623 | ||
645 | if (list_empty(vmas)) | ||
646 | return 0; | ||
647 | |||
648 | i915_gem_retire_requests_ring(ring); | 624 | i915_gem_retire_requests_ring(ring); |
649 | 625 | ||
650 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; | 626 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; |
@@ -658,20 +634,21 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, | |||
658 | obj = vma->obj; | 634 | obj = vma->obj; |
659 | entry = vma->exec_entry; | 635 | entry = vma->exec_entry; |
660 | 636 | ||
637 | if (!has_fenced_gpu_access) | ||
638 | entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE; | ||
661 | need_fence = | 639 | need_fence = |
662 | has_fenced_gpu_access && | ||
663 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | 640 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
664 | obj->tiling_mode != I915_TILING_NONE; | 641 | obj->tiling_mode != I915_TILING_NONE; |
665 | need_mappable = need_fence || need_reloc_mappable(vma); | 642 | need_mappable = need_fence || need_reloc_mappable(vma); |
666 | 643 | ||
667 | if (need_mappable) | 644 | if (need_mappable) { |
645 | entry->flags |= __EXEC_OBJECT_NEEDS_MAP; | ||
668 | list_move(&vma->exec_list, &ordered_vmas); | 646 | list_move(&vma->exec_list, &ordered_vmas); |
669 | else | 647 | } else |
670 | list_move_tail(&vma->exec_list, &ordered_vmas); | 648 | list_move_tail(&vma->exec_list, &ordered_vmas); |
671 | 649 | ||
672 | obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND; | 650 | obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND; |
673 | obj->base.pending_write_domain = 0; | 651 | obj->base.pending_write_domain = 0; |
674 | obj->pending_fenced_gpu_access = false; | ||
675 | } | 652 | } |
676 | list_splice(&ordered_vmas, vmas); | 653 | list_splice(&ordered_vmas, vmas); |
677 | 654 | ||
@@ -696,7 +673,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, | |||
696 | if (!drm_mm_node_allocated(&vma->node)) | 673 | if (!drm_mm_node_allocated(&vma->node)) |
697 | continue; | 674 | continue; |
698 | 675 | ||
699 | if (eb_vma_misplaced(vma, has_fenced_gpu_access)) | 676 | if (eb_vma_misplaced(vma)) |
700 | ret = i915_vma_unbind(vma); | 677 | ret = i915_vma_unbind(vma); |
701 | else | 678 | else |
702 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); | 679 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
@@ -744,9 +721,6 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
744 | int i, total, ret; | 721 | int i, total, ret; |
745 | unsigned count = args->buffer_count; | 722 | unsigned count = args->buffer_count; |
746 | 723 | ||
747 | if (WARN_ON(list_empty(&eb->vmas))) | ||
748 | return 0; | ||
749 | |||
750 | vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm; | 724 | vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm; |
751 | 725 | ||
752 | /* We may process another execbuffer during the unlock... */ | 726 | /* We may process another execbuffer during the unlock... */ |
@@ -890,18 +864,24 @@ i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) | |||
890 | } | 864 | } |
891 | 865 | ||
892 | static int | 866 | static int |
893 | validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | 867 | validate_exec_list(struct drm_device *dev, |
868 | struct drm_i915_gem_exec_object2 *exec, | ||
894 | int count) | 869 | int count) |
895 | { | 870 | { |
896 | int i; | ||
897 | unsigned relocs_total = 0; | 871 | unsigned relocs_total = 0; |
898 | unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry); | 872 | unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry); |
873 | unsigned invalid_flags; | ||
874 | int i; | ||
875 | |||
876 | invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; | ||
877 | if (USES_FULL_PPGTT(dev)) | ||
878 | invalid_flags |= EXEC_OBJECT_NEEDS_GTT; | ||
899 | 879 | ||
900 | for (i = 0; i < count; i++) { | 880 | for (i = 0; i < count; i++) { |
901 | char __user *ptr = to_user_ptr(exec[i].relocs_ptr); | 881 | char __user *ptr = to_user_ptr(exec[i].relocs_ptr); |
902 | int length; /* limited by fault_in_pages_readable() */ | 882 | int length; /* limited by fault_in_pages_readable() */ |
903 | 883 | ||
904 | if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS) | 884 | if (exec[i].flags & invalid_flags) |
905 | return -EINVAL; | 885 | return -EINVAL; |
906 | 886 | ||
907 | /* First check for malicious input causing overflow in | 887 | /* First check for malicious input causing overflow in |
@@ -951,16 +931,26 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, | |||
951 | return ERR_PTR(-EIO); | 931 | return ERR_PTR(-EIO); |
952 | } | 932 | } |
953 | 933 | ||
934 | if (i915.enable_execlists && !ctx->engine[ring->id].state) { | ||
935 | int ret = intel_lr_context_deferred_create(ctx, ring); | ||
936 | if (ret) { | ||
937 | DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret); | ||
938 | return ERR_PTR(ret); | ||
939 | } | ||
940 | } | ||
941 | |||
954 | return ctx; | 942 | return ctx; |
955 | } | 943 | } |
956 | 944 | ||
957 | static void | 945 | void |
958 | i915_gem_execbuffer_move_to_active(struct list_head *vmas, | 946 | i915_gem_execbuffer_move_to_active(struct list_head *vmas, |
959 | struct intel_engine_cs *ring) | 947 | struct intel_engine_cs *ring) |
960 | { | 948 | { |
949 | u32 seqno = intel_ring_get_seqno(ring); | ||
961 | struct i915_vma *vma; | 950 | struct i915_vma *vma; |
962 | 951 | ||
963 | list_for_each_entry(vma, vmas, exec_list) { | 952 | list_for_each_entry(vma, vmas, exec_list) { |
953 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; | ||
964 | struct drm_i915_gem_object *obj = vma->obj; | 954 | struct drm_i915_gem_object *obj = vma->obj; |
965 | u32 old_read = obj->base.read_domains; | 955 | u32 old_read = obj->base.read_domains; |
966 | u32 old_write = obj->base.write_domain; | 956 | u32 old_write = obj->base.write_domain; |
@@ -969,24 +959,31 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, | |||
969 | if (obj->base.write_domain == 0) | 959 | if (obj->base.write_domain == 0) |
970 | obj->base.pending_read_domains |= obj->base.read_domains; | 960 | obj->base.pending_read_domains |= obj->base.read_domains; |
971 | obj->base.read_domains = obj->base.pending_read_domains; | 961 | obj->base.read_domains = obj->base.pending_read_domains; |
972 | obj->fenced_gpu_access = obj->pending_fenced_gpu_access; | ||
973 | 962 | ||
974 | i915_vma_move_to_active(vma, ring); | 963 | i915_vma_move_to_active(vma, ring); |
975 | if (obj->base.write_domain) { | 964 | if (obj->base.write_domain) { |
976 | obj->dirty = 1; | 965 | obj->dirty = 1; |
977 | obj->last_write_seqno = intel_ring_get_seqno(ring); | 966 | obj->last_write_seqno = seqno; |
978 | 967 | ||
979 | intel_fb_obj_invalidate(obj, ring); | 968 | intel_fb_obj_invalidate(obj, ring); |
980 | 969 | ||
981 | /* update for the implicit flush after a batch */ | 970 | /* update for the implicit flush after a batch */ |
982 | obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; | 971 | obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; |
983 | } | 972 | } |
973 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { | ||
974 | obj->last_fenced_seqno = seqno; | ||
975 | if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { | ||
976 | struct drm_i915_private *dev_priv = to_i915(ring->dev); | ||
977 | list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list, | ||
978 | &dev_priv->mm.fence_list); | ||
979 | } | ||
980 | } | ||
984 | 981 | ||
985 | trace_i915_gem_object_change_domain(obj, old_read, old_write); | 982 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
986 | } | 983 | } |
987 | } | 984 | } |
988 | 985 | ||
989 | static void | 986 | void |
990 | i915_gem_execbuffer_retire_commands(struct drm_device *dev, | 987 | i915_gem_execbuffer_retire_commands(struct drm_device *dev, |
991 | struct drm_file *file, | 988 | struct drm_file *file, |
992 | struct intel_engine_cs *ring, | 989 | struct intel_engine_cs *ring, |
@@ -1026,14 +1023,14 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, | |||
1026 | return 0; | 1023 | return 0; |
1027 | } | 1024 | } |
1028 | 1025 | ||
1029 | static int | 1026 | int |
1030 | legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, | 1027 | i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, |
1031 | struct intel_engine_cs *ring, | 1028 | struct intel_engine_cs *ring, |
1032 | struct intel_context *ctx, | 1029 | struct intel_context *ctx, |
1033 | struct drm_i915_gem_execbuffer2 *args, | 1030 | struct drm_i915_gem_execbuffer2 *args, |
1034 | struct list_head *vmas, | 1031 | struct list_head *vmas, |
1035 | struct drm_i915_gem_object *batch_obj, | 1032 | struct drm_i915_gem_object *batch_obj, |
1036 | u64 exec_start, u32 flags) | 1033 | u64 exec_start, u32 flags) |
1037 | { | 1034 | { |
1038 | struct drm_clip_rect *cliprects = NULL; | 1035 | struct drm_clip_rect *cliprects = NULL; |
1039 | struct drm_i915_private *dev_priv = dev->dev_private; | 1036 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -1254,7 +1251,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1254 | if (!i915_gem_check_execbuffer(args)) | 1251 | if (!i915_gem_check_execbuffer(args)) |
1255 | return -EINVAL; | 1252 | return -EINVAL; |
1256 | 1253 | ||
1257 | ret = validate_exec_list(exec, args->buffer_count); | 1254 | ret = validate_exec_list(dev, exec, args->buffer_count); |
1258 | if (ret) | 1255 | if (ret) |
1259 | return ret; | 1256 | return ret; |
1260 | 1257 | ||
@@ -1318,8 +1315,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1318 | 1315 | ||
1319 | i915_gem_context_reference(ctx); | 1316 | i915_gem_context_reference(ctx); |
1320 | 1317 | ||
1321 | vm = ctx->vm; | 1318 | if (ctx->ppgtt) |
1322 | if (!USES_FULL_PPGTT(dev)) | 1319 | vm = &ctx->ppgtt->base; |
1320 | else | ||
1323 | vm = &dev_priv->gtt.base; | 1321 | vm = &dev_priv->gtt.base; |
1324 | 1322 | ||
1325 | eb = eb_create(args); | 1323 | eb = eb_create(args); |
@@ -1386,25 +1384,36 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
1386 | /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure | 1384 | /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure |
1387 | * batch" bit. Hence we need to pin secure batches into the global gtt. | 1385 | * batch" bit. Hence we need to pin secure batches into the global gtt. |
1388 | * hsw should have this fixed, but bdw mucks it up again. */ | 1386 | * hsw should have this fixed, but bdw mucks it up again. */ |
1389 | if (flags & I915_DISPATCH_SECURE && | 1387 | if (flags & I915_DISPATCH_SECURE) { |
1390 | !batch_obj->has_global_gtt_mapping) { | 1388 | /* |
1391 | /* When we have multiple VMs, we'll need to make sure that we | 1389 | * So on first glance it looks freaky that we pin the batch here |
1392 | * allocate space first */ | 1390 | * outside of the reservation loop. But: |
1393 | struct i915_vma *vma = i915_gem_obj_to_ggtt(batch_obj); | 1391 | * - The batch is already pinned into the relevant ppgtt, so we |
1394 | BUG_ON(!vma); | 1392 | * already have the backing storage fully allocated. |
1395 | vma->bind_vma(vma, batch_obj->cache_level, GLOBAL_BIND); | 1393 | * - No other BO uses the global gtt (well contexts, but meh), |
1396 | } | 1394 | * so we don't really have issues with mutliple objects not |
1395 | * fitting due to fragmentation. | ||
1396 | * So this is actually safe. | ||
1397 | */ | ||
1398 | ret = i915_gem_obj_ggtt_pin(batch_obj, 0, 0); | ||
1399 | if (ret) | ||
1400 | goto err; | ||
1397 | 1401 | ||
1398 | if (flags & I915_DISPATCH_SECURE) | ||
1399 | exec_start += i915_gem_obj_ggtt_offset(batch_obj); | 1402 | exec_start += i915_gem_obj_ggtt_offset(batch_obj); |
1400 | else | 1403 | } else |
1401 | exec_start += i915_gem_obj_offset(batch_obj, vm); | 1404 | exec_start += i915_gem_obj_offset(batch_obj, vm); |
1402 | 1405 | ||
1403 | ret = legacy_ringbuffer_submission(dev, file, ring, ctx, | 1406 | ret = dev_priv->gt.do_execbuf(dev, file, ring, ctx, args, |
1404 | args, &eb->vmas, batch_obj, exec_start, flags); | 1407 | &eb->vmas, batch_obj, exec_start, flags); |
1405 | if (ret) | ||
1406 | goto err; | ||
1407 | 1408 | ||
1409 | /* | ||
1410 | * FIXME: We crucially rely upon the active tracking for the (ppgtt) | ||
1411 | * batch vma for correctness. For less ugly and less fragility this | ||
1412 | * needs to be adjusted to also track the ggtt batch vma properly as | ||
1413 | * active. | ||
1414 | */ | ||
1415 | if (flags & I915_DISPATCH_SECURE) | ||
1416 | i915_gem_object_ggtt_unpin(batch_obj); | ||
1408 | err: | 1417 | err: |
1409 | /* the request owns the ref now */ | 1418 | /* the request owns the ref now */ |
1410 | i915_gem_context_unreference(ctx); | 1419 | i915_gem_context_unreference(ctx); |