Rev 5060 | Rev 5367 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 5354 | ||
---|---|---|---|
Line 33... | Line 33... | ||
33 | #include "intel_drv.h" |
33 | #include "intel_drv.h" |
34 | #include |
34 | #include |
Line 35... | Line 35... | ||
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) |
Line 38... | Line 39... | ||
38 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) |
39 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) |
Line 39... | Line 40... | ||
39 | 40 | ||
Line 99... | Line 100... | ||
99 | struct drm_i915_gem_exec_object2 *exec, |
100 | struct drm_i915_gem_exec_object2 *exec, |
100 | const struct drm_i915_gem_execbuffer2 *args, |
101 | const struct drm_i915_gem_execbuffer2 *args, |
101 | struct i915_address_space *vm, |
102 | struct i915_address_space *vm, |
102 | struct drm_file *file) |
103 | struct drm_file *file) |
103 | { |
104 | { |
104 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
- | |
105 | struct drm_i915_gem_object *obj; |
105 | struct drm_i915_gem_object *obj; |
106 | struct list_head objects; |
106 | struct list_head objects; |
107 | int i, ret; |
107 | int i, ret; |
Line 108... | Line 108... | ||
108 | 108 | ||
Line 134... | Line 134... | ||
134 | spin_unlock(&file->table_lock); |
134 | spin_unlock(&file->table_lock); |
Line 135... | Line 135... | ||
135 | 135 | ||
136 | i = 0; |
136 | i = 0; |
137 | while (!list_empty(&objects)) { |
137 | while (!list_empty(&objects)) { |
138 | struct i915_vma *vma; |
- | |
139 | struct i915_address_space *bind_vm = vm; |
- | |
140 | - | ||
141 | if (exec[i].flags & EXEC_OBJECT_NEEDS_GTT && |
- | |
142 | USES_FULL_PPGTT(vm->dev)) { |
- | |
143 | ret = -EINVAL; |
- | |
144 | goto err; |
- | |
145 | } |
- | |
146 | - | ||
147 | /* If we have secure dispatch, or the userspace assures us that |
- | |
148 | * they know what they're doing, use the GGTT VM. |
- | |
149 | */ |
- | |
150 | if (((args->flags & I915_EXEC_SECURE) && |
- | |
151 | (i == (args->buffer_count - 1)))) |
- | |
Line 152... | Line 138... | ||
152 | bind_vm = &dev_priv->gtt.base; |
138 | struct i915_vma *vma; |
153 | 139 | ||
154 | obj = list_first_entry(&objects, |
140 | obj = list_first_entry(&objects, |
Line 161... | Line 147... | ||
161 | * vmas which are not actually bound. And since only |
147 | * vmas which are not actually bound. And since only |
162 | * lookup_or_create exists as an interface to get at the vma |
148 | * lookup_or_create exists as an interface to get at the vma |
163 | * from the (obj, vm) we don't run the risk of creating |
149 | * from the (obj, vm) we don't run the risk of creating |
164 | * duplicated vmas for the same vm. |
150 | * duplicated vmas for the same vm. |
165 | */ |
151 | */ |
166 | vma = i915_gem_obj_lookup_or_create_vma(obj, bind_vm); |
152 | vma = i915_gem_obj_lookup_or_create_vma(obj, vm); |
167 | if (IS_ERR(vma)) { |
153 | if (IS_ERR(vma)) { |
168 | DRM_DEBUG("Failed to lookup VMA\n"); |
154 | DRM_DEBUG("Failed to lookup VMA\n"); |
169 | ret = PTR_ERR(vma); |
155 | ret = PTR_ERR(vma); |
170 | goto err; |
156 | goto err; |
171 | } |
157 | } |
Line 274... | Line 260... | ||
274 | relocate_entry_cpu(struct drm_i915_gem_object *obj, |
260 | relocate_entry_cpu(struct drm_i915_gem_object *obj, |
275 | struct drm_i915_gem_relocation_entry *reloc, |
261 | struct drm_i915_gem_relocation_entry *reloc, |
276 | uint64_t target_offset) |
262 | uint64_t target_offset) |
277 | { |
263 | { |
278 | struct drm_device *dev = obj->base.dev; |
264 | struct drm_device *dev = obj->base.dev; |
279 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
280 | uint32_t page_offset = offset_in_page(reloc->offset); |
265 | uint32_t page_offset = offset_in_page(reloc->offset); |
281 | uint64_t delta = reloc->delta + target_offset; |
266 | uint64_t delta = reloc->delta + target_offset; |
282 | char *vaddr; |
267 | char *vaddr; |
283 | int ret; |
268 | int ret; |
Line 284... | Line 269... | ||
284 | 269 | ||
285 | ret = i915_gem_object_set_to_cpu_domain(obj, true); |
270 | ret = i915_gem_object_set_to_cpu_domain(obj, true); |
286 | if (ret) |
271 | if (ret) |
Line 287... | Line 272... | ||
287 | return ret; |
272 | return ret; |
288 | 273 | ||
289 | vaddr = (char*)dev_priv->gtt.mappable+4096; |
274 | vaddr = kmap_atomic(i915_gem_object_get_page(obj, |
Line 290... | Line 275... | ||
290 | MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj,reloc->offset >> PAGE_SHIFT), PG_SW); |
275 | reloc->offset >> PAGE_SHIFT)); |
291 | *(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta); |
276 | *(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta); |
Line 292... | Line 277... | ||
292 | 277 | ||
- | 278 | if (INTEL_INFO(dev)->gen >= 8) { |
|
293 | if (INTEL_INFO(dev)->gen >= 8) { |
279 | page_offset = offset_in_page(page_offset + sizeof(uint32_t)); |
294 | page_offset = offset_in_page(page_offset + sizeof(uint32_t)); |
280 | |
295 | 281 | if (page_offset == 0) { |
|
Line 296... | Line 282... | ||
296 | if (page_offset == 0) { |
282 | kunmap_atomic(vaddr); |
297 | MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj, |
283 | vaddr = kmap_atomic(i915_gem_object_get_page(obj, |
Line -... | Line 284... | ||
- | 284 | (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT)); |
|
- | 285 | } |
|
298 | (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT), PG_SW); |
286 | |
299 | } |
287 | *(uint32_t *)(vaddr + page_offset) = upper_32_bits(delta); |
Line 300... | Line 288... | ||
300 | 288 | } |
|
301 | *(uint32_t *)(vaddr + page_offset) = upper_32_bits(delta); |
289 | |
Line 310... | Line 298... | ||
310 | uint64_t target_offset) |
298 | uint64_t target_offset) |
311 | { |
299 | { |
312 | struct drm_device *dev = obj->base.dev; |
300 | struct drm_device *dev = obj->base.dev; |
313 | struct drm_i915_private *dev_priv = dev->dev_private; |
301 | struct drm_i915_private *dev_priv = dev->dev_private; |
314 | uint64_t delta = reloc->delta + target_offset; |
302 | uint64_t delta = reloc->delta + target_offset; |
315 | uint32_t __iomem *reloc_entry; |
303 | uint64_t offset; |
316 | void __iomem *reloc_page; |
304 | void __iomem *reloc_page; |
317 | int ret; |
305 | int ret; |
Line 318... | Line 306... | ||
318 | 306 | ||
319 | ret = i915_gem_object_set_to_gtt_domain(obj, true); |
307 | ret = i915_gem_object_set_to_gtt_domain(obj, true); |
Line 323... | Line 311... | ||
323 | ret = i915_gem_object_put_fence(obj); |
311 | ret = i915_gem_object_put_fence(obj); |
324 | if (ret) |
312 | if (ret) |
325 | return ret; |
313 | return ret; |
Line 326... | Line 314... | ||
326 | 314 | ||
327 | /* Map the page containing the relocation we're going to perform. */ |
315 | /* Map the page containing the relocation we're going to perform. */ |
- | 316 | offset = i915_gem_obj_ggtt_offset(obj); |
|
328 | reloc->offset += i915_gem_obj_ggtt_offset(obj); |
317 | offset += reloc->offset; |
329 | MapPage(dev_priv->gtt.mappable,dev_priv->gtt.mappable_base + |
318 | MapPage(dev_priv->gtt.mappable,dev_priv->gtt.mappable_base + |
330 | (reloc->offset & PAGE_MASK), PG_SW); |
319 | (offset & PAGE_MASK), PG_SW); |
331 | reloc_page = dev_priv->gtt.mappable; |
- | |
332 | reloc_entry = (uint32_t __iomem *) |
- | |
333 | (reloc_page + offset_in_page(reloc->offset)); |
320 | reloc_page = dev_priv->gtt.mappable; |
- | 321 | iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset)); |
|
Line 334... | Line 322... | ||
334 | iowrite32(lower_32_bits(delta), reloc_entry); |
322 | |
335 | 323 | ||
Line 361... | Line 349... | ||
361 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and |
349 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and |
362 | * pipe_control writes because the gpu doesn't properly redirect them |
350 | * pipe_control writes because the gpu doesn't properly redirect them |
363 | * through the ppgtt for non_secure batchbuffers. */ |
351 | * through the ppgtt for non_secure batchbuffers. */ |
364 | if (unlikely(IS_GEN6(dev) && |
352 | if (unlikely(IS_GEN6(dev) && |
365 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && |
353 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && |
366 | !target_i915_obj->has_global_gtt_mapping)) { |
354 | !(target_vma->bound & GLOBAL_BIND))) |
367 | struct i915_vma *vma = |
- | |
368 | list_first_entry(&target_i915_obj->vma_list, |
355 | target_vma->bind_vma(target_vma, target_i915_obj->cache_level, |
369 | typeof(*vma), vma_link); |
356 | GLOBAL_BIND); |
370 | vma->bind_vma(vma, target_i915_obj->cache_level, GLOBAL_BIND); |
- | |
371 | } |
- | |
Line 372... | Line 357... | ||
372 | 357 | ||
373 | /* Validate that the target is in a valid r/w GPU domain */ |
358 | /* Validate that the target is in a valid r/w GPU domain */ |
374 | if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { |
359 | if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { |
375 | DRM_DEBUG("reloc with multiple write domains: " |
360 | DRM_DEBUG("reloc with multiple write domains: " |
Line 521... | Line 506... | ||
521 | 506 | ||
522 | return ret; |
507 | return ret; |
Line 523... | Line 508... | ||
523 | } |
508 | } |
524 | - | ||
525 | static int |
- | |
526 | need_reloc_mappable(struct i915_vma *vma) |
- | |
527 | { |
- | |
528 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
- | |
529 | return entry->relocation_count && !use_cpu_reloc(vma->obj) && |
- | |
530 | i915_is_ggtt(vma->vm); |
- | |
531 | } |
- | |
532 | 509 | ||
533 | static int |
510 | static int |
534 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, |
511 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, |
535 | struct intel_engine_cs *ring, |
512 | struct intel_engine_cs *ring, |
536 | bool *need_reloc) |
513 | bool *need_reloc) |
537 | { |
514 | { |
538 | struct drm_i915_gem_object *obj = vma->obj; |
- | |
539 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
- | |
540 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
515 | struct drm_i915_gem_object *obj = vma->obj; |
541 | bool need_fence; |
516 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
Line 542... | Line 517... | ||
542 | uint64_t flags; |
517 | uint64_t flags; |
543 | int ret; |
- | |
544 | - | ||
545 | flags = 0; |
- | |
546 | 518 | int ret; |
|
547 | need_fence = |
- | |
548 | has_fenced_gpu_access && |
- | |
549 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
519 | |
550 | obj->tiling_mode != I915_TILING_NONE; |
- | |
551 | if (need_fence || need_reloc_mappable(vma)) |
520 | flags = 0; |
552 | flags |= PIN_MAPPABLE; |
521 | if (entry->flags & __EXEC_OBJECT_NEEDS_MAP) |
553 | 522 | flags |= PIN_GLOBAL | PIN_MAPPABLE; |
|
554 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) |
523 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) |
Line 560... | Line 529... | ||
560 | if (ret) |
529 | if (ret) |
561 | return ret; |
530 | return ret; |
Line 562... | Line 531... | ||
562 | 531 | ||
Line 563... | Line -... | ||
563 | entry->flags |= __EXEC_OBJECT_HAS_PIN; |
- | |
564 | 532 | entry->flags |= __EXEC_OBJECT_HAS_PIN; |
|
565 | if (has_fenced_gpu_access) { |
533 | |
566 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { |
534 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { |
567 | ret = i915_gem_object_get_fence(obj); |
535 | ret = i915_gem_object_get_fence(obj); |
Line 568... | Line 536... | ||
568 | if (ret) |
536 | if (ret) |
569 | return ret; |
537 | return ret; |
570 | - | ||
571 | if (i915_gem_object_pin_fence(obj)) |
- | |
572 | entry->flags |= __EXEC_OBJECT_HAS_FENCE; |
- | |
573 | 538 | ||
Line 574... | Line 539... | ||
574 | obj->pending_fenced_gpu_access = true; |
539 | if (i915_gem_object_pin_fence(obj)) |
575 | } |
540 | entry->flags |= __EXEC_OBJECT_HAS_FENCE; |
576 | } |
541 | } |
Line 587... | Line 552... | ||
587 | 552 | ||
588 | return 0; |
553 | return 0; |
Line 589... | Line 554... | ||
589 | } |
554 | } |
590 | 555 | ||
591 | static bool |
556 | static bool |
592 | eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access) |
557 | need_reloc_mappable(struct i915_vma *vma) |
593 | { |
- | |
594 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
- | |
Line -... | Line 558... | ||
- | 558 | { |
|
595 | struct drm_i915_gem_object *obj = vma->obj; |
559 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
- | 560 | ||
596 | bool need_fence, need_mappable; |
561 | if (entry->relocation_count == 0) |
- | 562 | return false; |
|
- | 563 | ||
597 | 564 | if (!i915_is_ggtt(vma->vm)) |
|
598 | need_fence = |
565 | return false; |
- | 566 | ||
- | 567 | /* See also use_cpu_reloc() */ |
|
599 | has_fenced_gpu_access && |
568 | if (HAS_LLC(vma->obj->base.dev)) |
- | 569 | return false; |
|
- | 570 | ||
- | 571 | if (vma->obj->base.write_domain == I915_GEM_DOMAIN_CPU) |
|
- | 572 | return false; |
|
Line -... | Line 573... | ||
- | 573 | ||
- | 574 | return true; |
|
- | 575 | } |
|
- | 576 | ||
- | 577 | static bool |
|
- | 578 | eb_vma_misplaced(struct i915_vma *vma) |
|
600 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
579 | { |
601 | obj->tiling_mode != I915_TILING_NONE; |
580 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
Line 602... | Line 581... | ||
602 | need_mappable = need_fence || need_reloc_mappable(vma); |
581 | struct drm_i915_gem_object *obj = vma->obj; |
603 | 582 | ||
604 | WARN_ON((need_mappable || need_fence) && |
583 | WARN_ON(entry->flags & __EXEC_OBJECT_NEEDS_MAP && |
Line 605... | Line 584... | ||
605 | !i915_is_ggtt(vma->vm)); |
584 | !i915_is_ggtt(vma->vm)); |
606 | 585 | ||
Line 607... | Line 586... | ||
607 | if (entry->alignment && |
586 | if (entry->alignment && |
608 | vma->node.start & (entry->alignment - 1)) |
587 | vma->node.start & (entry->alignment - 1)) |
609 | return true; |
588 | return true; |
Line 628... | Line 607... | ||
628 | struct i915_address_space *vm; |
607 | struct i915_address_space *vm; |
629 | struct list_head ordered_vmas; |
608 | struct list_head ordered_vmas; |
630 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
609 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
631 | int retry; |
610 | int retry; |
Line 632... | Line -... | ||
632 | - | ||
633 | if (list_empty(vmas)) |
- | |
634 | return 0; |
- | |
635 | 611 | ||
Line 636... | Line 612... | ||
636 | i915_gem_retire_requests_ring(ring); |
612 | i915_gem_retire_requests_ring(ring); |
Line 637... | Line 613... | ||
637 | 613 | ||
Line 644... | Line 620... | ||
644 | 620 | ||
645 | vma = list_first_entry(vmas, struct i915_vma, exec_list); |
621 | vma = list_first_entry(vmas, struct i915_vma, exec_list); |
646 | obj = vma->obj; |
622 | obj = vma->obj; |
Line -... | Line 623... | ||
- | 623 | entry = vma->exec_entry; |
|
- | 624 | ||
647 | entry = vma->exec_entry; |
625 | if (!has_fenced_gpu_access) |
648 | - | ||
649 | need_fence = |
626 | entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE; |
650 | has_fenced_gpu_access && |
627 | need_fence = |
651 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
628 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
Line 652... | Line 629... | ||
652 | obj->tiling_mode != I915_TILING_NONE; |
629 | obj->tiling_mode != I915_TILING_NONE; |
- | 630 | need_mappable = need_fence || need_reloc_mappable(vma); |
|
653 | need_mappable = need_fence || need_reloc_mappable(vma); |
631 | |
654 | 632 | if (need_mappable) { |
|
655 | if (need_mappable) |
633 | entry->flags |= __EXEC_OBJECT_NEEDS_MAP; |
Line 656... | Line 634... | ||
656 | list_move(&vma->exec_list, &ordered_vmas); |
634 | list_move(&vma->exec_list, &ordered_vmas); |
657 | else |
635 | } else |
658 | list_move_tail(&vma->exec_list, &ordered_vmas); |
- | |
659 | 636 | list_move_tail(&vma->exec_list, &ordered_vmas); |
|
660 | obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND; |
637 | |
Line 661... | Line 638... | ||
661 | obj->base.pending_write_domain = 0; |
638 | obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND; |
662 | obj->pending_fenced_gpu_access = false; |
639 | obj->base.pending_write_domain = 0; |
Line 682... | Line 659... | ||
682 | /* Unbind any ill-fitting objects or pin. */ |
659 | /* Unbind any ill-fitting objects or pin. */ |
683 | list_for_each_entry(vma, vmas, exec_list) { |
660 | list_for_each_entry(vma, vmas, exec_list) { |
684 | if (!drm_mm_node_allocated(&vma->node)) |
661 | if (!drm_mm_node_allocated(&vma->node)) |
685 | continue; |
662 | continue; |
Line 686... | Line 663... | ||
686 | 663 | ||
687 | if (eb_vma_misplaced(vma, has_fenced_gpu_access)) |
664 | if (eb_vma_misplaced(vma)) |
688 | ret = i915_vma_unbind(vma); |
665 | ret = i915_vma_unbind(vma); |
689 | else |
666 | else |
690 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
667 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
691 | if (ret) |
668 | if (ret) |
Line 730... | Line 707... | ||
730 | bool need_relocs; |
707 | bool need_relocs; |
731 | int *reloc_offset; |
708 | int *reloc_offset; |
732 | int i, total, ret; |
709 | int i, total, ret; |
733 | unsigned count = args->buffer_count; |
710 | unsigned count = args->buffer_count; |
Line 734... | Line -... | ||
734 | - | ||
735 | if (WARN_ON(list_empty(&eb->vmas))) |
- | |
736 | return 0; |
- | |
737 | 711 | ||
Line 738... | Line 712... | ||
738 | vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm; |
712 | vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm; |
739 | 713 | ||
740 | /* We may process another execbuffer during the unlock... */ |
714 | /* We may process another execbuffer during the unlock... */ |
Line 876... | Line 850... | ||
876 | 850 | ||
877 | return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0; |
851 | return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0; |
Line 878... | Line 852... | ||
878 | } |
852 | } |
- | 853 | ||
879 | 854 | static int |
|
880 | static int |
855 | validate_exec_list(struct drm_device *dev, |
881 | validate_exec_list(struct drm_i915_gem_exec_object2 *exec, |
856 | struct drm_i915_gem_exec_object2 *exec, |
882 | int count) |
- | |
883 | { |
857 | int count) |
884 | int i; |
858 | { |
- | 859 | unsigned relocs_total = 0; |
|
- | 860 | unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry); |
|
- | 861 | unsigned invalid_flags; |
|
- | 862 | int i; |
|
- | 863 | ||
- | 864 | invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; |
|
Line 885... | Line 865... | ||
885 | unsigned relocs_total = 0; |
865 | if (USES_FULL_PPGTT(dev)) |
886 | unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry); |
866 | invalid_flags |= EXEC_OBJECT_NEEDS_GTT; |
887 | 867 | ||
Line 888... | Line 868... | ||
888 | for (i = 0; i < count; i++) { |
868 | for (i = 0; i < count; i++) { |
889 | char __user *ptr = to_user_ptr(exec[i].relocs_ptr); |
869 | char __user *ptr = to_user_ptr(exec[i].relocs_ptr); |
Line 890... | Line 870... | ||
890 | int length; /* limited by fault_in_pages_readable() */ |
870 | int length; /* limited by fault_in_pages_readable() */ |
891 | 871 | ||
892 | if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS) |
872 | if (exec[i].flags & invalid_flags) |
Line 930... | Line 910... | ||
930 | if (hs->banned) { |
910 | if (hs->banned) { |
931 | DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id); |
911 | DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id); |
932 | return ERR_PTR(-EIO); |
912 | return ERR_PTR(-EIO); |
933 | } |
913 | } |
Line -... | Line 914... | ||
- | 914 | ||
- | 915 | if (i915.enable_execlists && !ctx->engine[ring->id].state) { |
|
- | 916 | int ret = intel_lr_context_deferred_create(ctx, ring); |
|
- | 917 | if (ret) { |
|
- | 918 | DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret); |
|
- | 919 | return ERR_PTR(ret); |
|
- | 920 | } |
|
- | 921 | } |
|
934 | 922 | ||
935 | return ctx; |
923 | return ctx; |
Line 936... | Line 924... | ||
936 | } |
924 | } |
937 | 925 | ||
938 | static void |
926 | void |
939 | i915_gem_execbuffer_move_to_active(struct list_head *vmas, |
927 | i915_gem_execbuffer_move_to_active(struct list_head *vmas, |
- | 928 | struct intel_engine_cs *ring) |
|
940 | struct intel_engine_cs *ring) |
929 | { |
Line 941... | Line 930... | ||
941 | { |
930 | u32 seqno = intel_ring_get_seqno(ring); |
- | 931 | struct i915_vma *vma; |
|
942 | struct i915_vma *vma; |
932 | |
943 | 933 | list_for_each_entry(vma, vmas, exec_list) { |
|
944 | list_for_each_entry(vma, vmas, exec_list) { |
934 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
Line 945... | Line 935... | ||
945 | struct drm_i915_gem_object *obj = vma->obj; |
935 | struct drm_i915_gem_object *obj = vma->obj; |
946 | u32 old_read = obj->base.read_domains; |
936 | u32 old_read = obj->base.read_domains; |
947 | u32 old_write = obj->base.write_domain; |
937 | u32 old_write = obj->base.write_domain; |
948 | 938 | ||
949 | obj->base.write_domain = obj->base.pending_write_domain; |
- | |
Line 950... | Line 939... | ||
950 | if (obj->base.write_domain == 0) |
939 | obj->base.write_domain = obj->base.pending_write_domain; |
951 | obj->base.pending_read_domains |= obj->base.read_domains; |
940 | if (obj->base.write_domain == 0) |
952 | obj->base.read_domains = obj->base.pending_read_domains; |
941 | obj->base.pending_read_domains |= obj->base.read_domains; |
953 | obj->fenced_gpu_access = obj->pending_fenced_gpu_access; |
942 | obj->base.read_domains = obj->base.pending_read_domains; |
Line 954... | Line 943... | ||
954 | 943 | ||
Line 955... | Line 944... | ||
955 | i915_vma_move_to_active(vma, ring); |
944 | i915_vma_move_to_active(vma, ring); |
956 | if (obj->base.write_domain) { |
945 | if (obj->base.write_domain) { |
957 | obj->dirty = 1; |
946 | obj->dirty = 1; |
- | 947 | obj->last_write_seqno = seqno; |
|
- | 948 | ||
- | 949 | intel_fb_obj_invalidate(obj, ring); |
|
- | 950 | ||
- | 951 | /* update for the implicit flush after a batch */ |
|
- | 952 | obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; |
|
- | 953 | } |
|
- | 954 | if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { |
|
Line 958... | Line 955... | ||
958 | obj->last_write_seqno = intel_ring_get_seqno(ring); |
955 | obj->last_fenced_seqno = seqno; |
959 | 956 | if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { |
|
960 | intel_fb_obj_invalidate(obj, ring); |
957 | struct drm_i915_private *dev_priv = to_i915(ring->dev); |
Line 961... | Line 958... | ||
961 | 958 | list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list, |
|
962 | /* update for the implicit flush after a batch */ |
959 | &dev_priv->mm.fence_list); |
963 | obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; |
960 | } |
964 | } |
961 | } |
965 | 962 | ||
966 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
963 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
Line 1006... | Line 1003... | ||
1006 | 1003 | ||
1007 | return 0; |
1004 | return 0; |
Line 1008... | Line 1005... | ||
1008 | } |
1005 | } |
- | 1006 | ||
- | 1007 | static int |
|
- | 1008 | i915_emit_box(struct intel_engine_cs *ring, |
|
- | 1009 | struct drm_clip_rect *box, |
|
- | 1010 | int DR1, int DR4) |
|
- | 1011 | { |
|
- | 1012 | int ret; |
|
- | 1013 | ||
- | 1014 | if (box->y2 <= box->y1 || box->x2 <= box->x1 || |
|
- | 1015 | box->y2 <= 0 || box->x2 <= 0) { |
|
- | 1016 | DRM_ERROR("Bad box %d,%d..%d,%d\n", |
|
- | 1017 | box->x1, box->y1, box->x2, box->y2); |
|
- | 1018 | return -EINVAL; |
|
- | 1019 | } |
|
- | 1020 | ||
- | 1021 | if (INTEL_INFO(ring->dev)->gen >= 4) { |
|
- | 1022 | ret = intel_ring_begin(ring, 4); |
|
- | 1023 | if (ret) |
|
- | 1024 | return ret; |
|
- | 1025 | ||
- | 1026 | intel_ring_emit(ring, GFX_OP_DRAWRECT_INFO_I965); |
|
- | 1027 | intel_ring_emit(ring, (box->x1 & 0xffff) | box->y1 << 16); |
|
- | 1028 | intel_ring_emit(ring, ((box->x2 - 1) & 0xffff) | (box->y2 - 1) << 16); |
|
- | 1029 | intel_ring_emit(ring, DR4); |
|
- | 1030 | } else { |
|
- | 1031 | ret = intel_ring_begin(ring, 6); |
|
- | 1032 | if (ret) |
|
- | 1033 | return ret; |
|
- | 1034 | ||
- | 1035 | intel_ring_emit(ring, GFX_OP_DRAWRECT_INFO); |
|
- | 1036 | intel_ring_emit(ring, DR1); |
|
- | 1037 | intel_ring_emit(ring, (box->x1 & 0xffff) | box->y1 << 16); |
|
- | 1038 | intel_ring_emit(ring, ((box->x2 - 1) & 0xffff) | (box->y2 - 1) << 16); |
|
- | 1039 | intel_ring_emit(ring, DR4); |
|
- | 1040 | intel_ring_emit(ring, 0); |
|
- | 1041 | } |
|
- | 1042 | intel_ring_advance(ring); |
|
- | 1043 | ||
- | 1044 | return 0; |
|
- | 1045 | } |
|
- | 1046 | ||
1009 | 1047 | ||
1010 | static int |
1048 | int |
1011 | legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, |
1049 | i915_gem_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, |
1012 | struct intel_engine_cs *ring, |
1050 | struct intel_engine_cs *ring, |
1013 | struct intel_context *ctx, |
1051 | struct intel_context *ctx, |
1014 | struct drm_i915_gem_execbuffer2 *args, |
1052 | struct drm_i915_gem_execbuffer2 *args, |
Line 1133... | Line 1171... | ||
1133 | } |
1171 | } |
Line 1134... | Line 1172... | ||
1134 | 1172 | ||
1135 | exec_len = args->batch_len; |
1173 | exec_len = args->batch_len; |
1136 | if (cliprects) { |
1174 | if (cliprects) { |
1137 | for (i = 0; i < args->num_cliprects; i++) { |
1175 | for (i = 0; i < args->num_cliprects; i++) { |
1138 | ret = i915_emit_box(dev, &cliprects[i], |
1176 | ret = i915_emit_box(ring, &cliprects[i], |
1139 | args->DR1, args->DR4); |
1177 | args->DR1, args->DR4); |
1140 | if (ret) |
1178 | if (ret) |
Line 1141... | Line 1179... | ||
1141 | goto error; |
1179 | goto error; |
Line 1233... | Line 1271... | ||
1233 | bool need_relocs; |
1271 | bool need_relocs; |
Line 1234... | Line 1272... | ||
1234 | 1272 | ||
1235 | if (!i915_gem_check_execbuffer(args)) |
1273 | if (!i915_gem_check_execbuffer(args)) |
Line 1236... | Line 1274... | ||
1236 | return -EINVAL; |
1274 | return -EINVAL; |
1237 | 1275 | ||
1238 | ret = validate_exec_list(exec, args->buffer_count); |
1276 | ret = validate_exec_list(dev, exec, args->buffer_count); |
Line 1239... | Line 1277... | ||
1239 | if (ret) |
1277 | if (ret) |
1240 | return ret; |
1278 | return ret; |
Line 1280... | Line 1318... | ||
1280 | 1318 | ||
1281 | ret = i915_mutex_lock_interruptible(dev); |
1319 | ret = i915_mutex_lock_interruptible(dev); |
1282 | if (ret) |
1320 | if (ret) |
Line 1283... | Line -... | ||
1283 | goto pre_mutex_err; |
- | |
1284 | - | ||
1285 | if (dev_priv->ums.mm_suspended) { |
- | |
1286 | mutex_unlock(&dev->struct_mutex); |
- | |
1287 | ret = -EBUSY; |
- | |
1288 | goto pre_mutex_err; |
- | |
1289 | } |
1321 | goto pre_mutex_err; |
1290 | 1322 | ||
1291 | ctx = i915_gem_validate_context(dev, file, ring, ctx_id); |
1323 | ctx = i915_gem_validate_context(dev, file, ring, ctx_id); |
1292 | if (IS_ERR(ctx)) { |
1324 | if (IS_ERR(ctx)) { |
1293 | mutex_unlock(&dev->struct_mutex); |
1325 | mutex_unlock(&dev->struct_mutex); |
1294 | ret = PTR_ERR(ctx); |
1326 | ret = PTR_ERR(ctx); |
Line 1295... | Line 1327... | ||
1295 | goto pre_mutex_err; |
1327 | goto pre_mutex_err; |
Line 1296... | Line 1328... | ||
1296 | } |
1328 | } |
1297 | 1329 | ||
- | 1330 | i915_gem_context_reference(ctx); |
|
1298 | i915_gem_context_reference(ctx); |
1331 | |
Line 1299... | Line 1332... | ||
1299 | 1332 | if (ctx->ppgtt) |
|
1300 | vm = ctx->vm; |
1333 | vm = &ctx->ppgtt->base; |
1301 | if (!USES_FULL_PPGTT(dev)) |
1334 | else |
Line 1363... | Line 1396... | ||
1363 | } |
1396 | } |
1364 | #endif |
1397 | #endif |
1365 | /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure |
1398 | /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure |
1366 | * batch" bit. Hence we need to pin secure batches into the global gtt. |
1399 | * batch" bit. Hence we need to pin secure batches into the global gtt. |
1367 | * hsw should have this fixed, but bdw mucks it up again. */ |
1400 | * hsw should have this fixed, but bdw mucks it up again. */ |
1368 | if (flags & I915_DISPATCH_SECURE && |
1401 | if (flags & I915_DISPATCH_SECURE) { |
- | 1402 | /* |
|
- | 1403 | * So on first glance it looks freaky that we pin the batch here |
|
1369 | !batch_obj->has_global_gtt_mapping) { |
1404 | * outside of the reservation loop. But: |
1370 | /* When we have multiple VMs, we'll need to make sure that we |
1405 | * - The batch is already pinned into the relevant ppgtt, so we |
1371 | * allocate space first */ |
1406 | * already have the backing storage fully allocated. |
1372 | struct i915_vma *vma = i915_gem_obj_to_ggtt(batch_obj); |
1407 | * - No other BO uses the global gtt (well contexts, but meh), |
- | 1408 | * so we don't really have issues with mutliple objects not |
|
1373 | BUG_ON(!vma); |
1409 | * fitting due to fragmentation. |
1374 | vma->bind_vma(vma, batch_obj->cache_level, GLOBAL_BIND); |
1410 | * So this is actually safe. |
1375 | } |
1411 | */ |
- | 1412 | ret = i915_gem_obj_ggtt_pin(batch_obj, 0, 0); |
|
- | 1413 | if (ret) |
|
- | 1414 | goto err; |
|
Line 1376... | Line -... | ||
1376 | - | ||
1377 | if (flags & I915_DISPATCH_SECURE) |
1415 | |
1378 | exec_start += i915_gem_obj_ggtt_offset(batch_obj); |
1416 | exec_start += i915_gem_obj_ggtt_offset(batch_obj); |
1379 | else |
1417 | } else |
Line 1380... | Line 1418... | ||
1380 | exec_start += i915_gem_obj_offset(batch_obj, vm); |
1418 | exec_start += i915_gem_obj_offset(batch_obj, vm); |
1381 | 1419 | ||
1382 | ret = legacy_ringbuffer_submission(dev, file, ring, ctx, |
- | |
1383 | args, &eb->vmas, batch_obj, exec_start, flags); |
- | |
Line -... | Line 1420... | ||
- | 1420 | ret = dev_priv->gt.do_execbuf(dev, file, ring, ctx, args, |
|
- | 1421 | &eb->vmas, batch_obj, exec_start, flags); |
|
- | 1422 | ||
- | 1423 | /* |
|
- | 1424 | * FIXME: We crucially rely upon the active tracking for the (ppgtt) |
|
- | 1425 | * batch vma for correctness. For less ugly and less fragility this |
|
- | 1426 | * needs to be adjusted to also track the ggtt batch vma properly as |
|
- | 1427 | * active. |
|
1384 | if (ret) |
1428 | */ |
1385 | goto err; |
1429 | if (flags & I915_DISPATCH_SECURE) |
1386 | 1430 | i915_gem_object_ggtt_unpin(batch_obj); |
|
1387 | err: |
1431 | err: |