Rev 4560 | Rev 5354 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | #include |
29 | #include |
30 | #include |
30 | #include |
31 | #include "i915_drv.h" |
31 | #include "i915_drv.h" |
32 | #include "i915_trace.h" |
32 | #include "i915_trace.h" |
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) |
|
Line 37... | Line -... | ||
37 | #define __EXEC_OBJECT_HAS_FENCE (1<<30) |
- | |
38 | - | ||
39 | static unsigned long |
- | |
40 | copy_to_user(void __user *to, const void *from, unsigned long n) |
38 | #define __EXEC_OBJECT_NEEDS_BIAS (1<<28) |
41 | { |
- | |
42 | memcpy(to, from, n); |
- | |
Line 43... | Line 39... | ||
43 | return 0; |
39 | |
44 | } |
40 | #define BATCH_OFFSET_BIAS (256*1024) |
45 | 41 | ||
46 | static unsigned long |
42 | static unsigned long |
Line 103... | Line 99... | ||
103 | struct drm_i915_gem_exec_object2 *exec, |
99 | struct drm_i915_gem_exec_object2 *exec, |
104 | const struct drm_i915_gem_execbuffer2 *args, |
100 | const struct drm_i915_gem_execbuffer2 *args, |
105 | struct i915_address_space *vm, |
101 | struct i915_address_space *vm, |
106 | struct drm_file *file) |
102 | struct drm_file *file) |
107 | { |
103 | { |
- | 104 | struct drm_i915_private *dev_priv = vm->dev->dev_private; |
|
108 | struct drm_i915_gem_object *obj; |
105 | struct drm_i915_gem_object *obj; |
109 | struct list_head objects; |
106 | struct list_head objects; |
110 | int i, ret; |
107 | int i, ret; |
Line 111... | Line 108... | ||
111 | 108 | ||
Line 137... | Line 134... | ||
137 | spin_unlock(&file->table_lock); |
134 | spin_unlock(&file->table_lock); |
Line 138... | Line 135... | ||
138 | 135 | ||
139 | i = 0; |
136 | i = 0; |
140 | 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 141... | Line 152... | ||
141 | struct i915_vma *vma; |
152 | bind_vm = &dev_priv->gtt.base; |
142 | 153 | ||
143 | obj = list_first_entry(&objects, |
154 | obj = list_first_entry(&objects, |
Line 150... | Line 161... | ||
150 | * vmas which are not actually bound. And since only |
161 | * vmas which are not actually bound. And since only |
151 | * lookup_or_create exists as an interface to get at the vma |
162 | * lookup_or_create exists as an interface to get at the vma |
152 | * from the (obj, vm) we don't run the risk of creating |
163 | * from the (obj, vm) we don't run the risk of creating |
153 | * duplicated vmas for the same vm. |
164 | * duplicated vmas for the same vm. |
154 | */ |
165 | */ |
155 | vma = i915_gem_obj_lookup_or_create_vma(obj, vm); |
166 | vma = i915_gem_obj_lookup_or_create_vma(obj, bind_vm); |
156 | if (IS_ERR(vma)) { |
167 | if (IS_ERR(vma)) { |
157 | DRM_DEBUG("Failed to lookup VMA\n"); |
168 | DRM_DEBUG("Failed to lookup VMA\n"); |
158 | ret = PTR_ERR(vma); |
169 | ret = PTR_ERR(vma); |
159 | goto err; |
170 | goto err; |
160 | } |
171 | } |
Line 229... | Line 240... | ||
229 | 240 | ||
230 | if (entry->flags & __EXEC_OBJECT_HAS_FENCE) |
241 | if (entry->flags & __EXEC_OBJECT_HAS_FENCE) |
Line 231... | Line 242... | ||
231 | i915_gem_object_unpin_fence(obj); |
242 | i915_gem_object_unpin_fence(obj); |
232 | 243 | ||
Line 233... | Line 244... | ||
233 | if (entry->flags & __EXEC_OBJECT_HAS_PIN) |
244 | if (entry->flags & __EXEC_OBJECT_HAS_PIN) |
234 | i915_gem_object_unpin(obj); |
245 | vma->pin_count--; |
Line 235... | Line 246... | ||
235 | 246 | ||
Line 259... | Line 270... | ||
259 | obj->cache_level != I915_CACHE_NONE); |
270 | obj->cache_level != I915_CACHE_NONE); |
260 | } |
271 | } |
Line 261... | Line 272... | ||
261 | 272 | ||
262 | static int |
273 | static int |
263 | relocate_entry_cpu(struct drm_i915_gem_object *obj, |
274 | relocate_entry_cpu(struct drm_i915_gem_object *obj, |
- | 275 | struct drm_i915_gem_relocation_entry *reloc, |
|
264 | struct drm_i915_gem_relocation_entry *reloc) |
276 | uint64_t target_offset) |
265 | { |
277 | { |
266 | struct drm_device *dev = obj->base.dev; |
278 | struct drm_device *dev = obj->base.dev; |
267 | struct drm_i915_private *dev_priv = dev->dev_private; |
279 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | 280 | uint32_t page_offset = offset_in_page(reloc->offset); |
|
268 | uint32_t page_offset = offset_in_page(reloc->offset); |
281 | uint64_t delta = reloc->delta + target_offset; |
269 | char *vaddr; |
282 | char *vaddr; |
Line 270... | Line 283... | ||
270 | int ret; |
283 | int ret; |
271 | 284 | ||
272 | ret = i915_gem_object_set_to_cpu_domain(obj, true); |
285 | ret = i915_gem_object_set_to_cpu_domain(obj, true); |
Line 273... | Line 286... | ||
273 | if (ret) |
286 | if (ret) |
274 | return ret; |
287 | return ret; |
275 | 288 | ||
- | 289 | vaddr = (char*)dev_priv->gtt.mappable+4096; |
|
- | 290 | MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj,reloc->offset >> PAGE_SHIFT), PG_SW); |
|
- | 291 | *(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta); |
|
- | 292 | ||
- | 293 | if (INTEL_INFO(dev)->gen >= 8) { |
|
- | 294 | page_offset = offset_in_page(page_offset + sizeof(uint32_t)); |
|
- | 295 | ||
- | 296 | if (page_offset == 0) { |
|
- | 297 | MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj, |
|
- | 298 | (reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT), PG_SW); |
|
- | 299 | } |
|
Line 276... | Line 300... | ||
276 | vaddr = dev_priv->gtt.mappable+4096; |
300 | |
277 | MapPage(vaddr,(addr_t)i915_gem_object_get_page(obj,reloc->offset >> PAGE_SHIFT), PG_SW); |
301 | *(uint32_t *)(vaddr + page_offset) = upper_32_bits(delta); |
Line 278... | Line 302... | ||
278 | *(uint32_t *)(vaddr + page_offset) = reloc->delta; |
302 | } |
279 | 303 | ||
280 | return 0; |
304 | return 0; |
- | 305 | } |
|
281 | } |
306 | |
282 | 307 | static int |
|
283 | static int |
308 | relocate_entry_gtt(struct drm_i915_gem_object *obj, |
- | 309 | struct drm_i915_gem_relocation_entry *reloc, |
|
284 | relocate_entry_gtt(struct drm_i915_gem_object *obj, |
310 | uint64_t target_offset) |
285 | struct drm_i915_gem_relocation_entry *reloc) |
311 | { |
286 | { |
312 | struct drm_device *dev = obj->base.dev; |
Line 287... | Line 313... | ||
287 | struct drm_device *dev = obj->base.dev; |
313 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 303... | Line 329... | ||
303 | MapPage(dev_priv->gtt.mappable,dev_priv->gtt.mappable_base + |
329 | MapPage(dev_priv->gtt.mappable,dev_priv->gtt.mappable_base + |
304 | (reloc->offset & PAGE_MASK), PG_SW); |
330 | (reloc->offset & PAGE_MASK), PG_SW); |
305 | reloc_page = dev_priv->gtt.mappable; |
331 | reloc_page = dev_priv->gtt.mappable; |
306 | reloc_entry = (uint32_t __iomem *) |
332 | reloc_entry = (uint32_t __iomem *) |
307 | (reloc_page + offset_in_page(reloc->offset)); |
333 | (reloc_page + offset_in_page(reloc->offset)); |
308 | iowrite32(reloc->delta, reloc_entry); |
334 | iowrite32(lower_32_bits(delta), reloc_entry); |
- | 335 | ||
Line 309... | Line 336... | ||
309 | 336 | ||
310 | return 0; |
337 | return 0; |
Line 311... | Line 338... | ||
311 | } |
338 | } |
312 | 339 | ||
313 | static int |
340 | static int |
314 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
341 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
315 | struct eb_vmas *eb, |
- | |
316 | struct drm_i915_gem_relocation_entry *reloc, |
342 | struct eb_vmas *eb, |
317 | struct i915_address_space *vm) |
343 | struct drm_i915_gem_relocation_entry *reloc) |
318 | { |
344 | { |
319 | struct drm_device *dev = obj->base.dev; |
345 | struct drm_device *dev = obj->base.dev; |
320 | struct drm_gem_object *target_obj; |
346 | struct drm_gem_object *target_obj; |
321 | struct drm_i915_gem_object *target_i915_obj; |
347 | struct drm_i915_gem_object *target_i915_obj; |
322 | struct i915_vma *target_vma; |
348 | struct i915_vma *target_vma; |
Line 323... | Line 349... | ||
323 | uint32_t target_offset; |
349 | uint64_t target_offset; |
324 | int ret; |
350 | int ret; |
325 | 351 | ||
Line 336... | Line 362... | ||
336 | * pipe_control writes because the gpu doesn't properly redirect them |
362 | * pipe_control writes because the gpu doesn't properly redirect them |
337 | * through the ppgtt for non_secure batchbuffers. */ |
363 | * through the ppgtt for non_secure batchbuffers. */ |
338 | if (unlikely(IS_GEN6(dev) && |
364 | if (unlikely(IS_GEN6(dev) && |
339 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && |
365 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && |
340 | !target_i915_obj->has_global_gtt_mapping)) { |
366 | !target_i915_obj->has_global_gtt_mapping)) { |
- | 367 | struct i915_vma *vma = |
|
341 | i915_gem_gtt_bind_object(target_i915_obj, |
368 | list_first_entry(&target_i915_obj->vma_list, |
- | 369 | typeof(*vma), vma_link); |
|
342 | target_i915_obj->cache_level); |
370 | vma->bind_vma(vma, target_i915_obj->cache_level, GLOBAL_BIND); |
343 | } |
371 | } |
Line 344... | Line 372... | ||
344 | 372 | ||
345 | /* Validate that the target is in a valid r/w GPU domain */ |
373 | /* Validate that the target is in a valid r/w GPU domain */ |
346 | if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { |
374 | if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { |
Line 392... | Line 420... | ||
392 | return -EINVAL; |
420 | return -EINVAL; |
393 | } |
421 | } |
Line 394... | Line 422... | ||
394 | 422 | ||
Line 395... | Line -... | ||
395 | /* We can't wait for rendering with pagefaults disabled */ |
- | |
396 | 423 | /* We can't wait for rendering with pagefaults disabled */ |
|
397 | reloc->delta += target_offset; |
424 | |
398 | if (use_cpu_reloc(obj)) |
425 | if (use_cpu_reloc(obj)) |
399 | ret = relocate_entry_cpu(obj, reloc); |
426 | ret = relocate_entry_cpu(obj, reloc, target_offset); |
Line 400... | Line 427... | ||
400 | else |
427 | else |
401 | ret = relocate_entry_gtt(obj, reloc); |
428 | ret = relocate_entry_gtt(obj, reloc, target_offset); |
Line 402... | Line 429... | ||
402 | 429 | ||
Line 432... | Line 459... | ||
432 | memcpy(r, user_relocs, count*sizeof(r[0])); |
459 | memcpy(r, user_relocs, count*sizeof(r[0])); |
Line 433... | Line 460... | ||
433 | 460 | ||
434 | do { |
461 | do { |
Line 435... | Line 462... | ||
435 | u64 offset = r->presumed_offset; |
462 | u64 offset = r->presumed_offset; |
436 | - | ||
437 | ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r, |
463 | |
438 | vma->vm); |
464 | ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r); |
Line 439... | Line 465... | ||
439 | if (ret) |
465 | if (ret) |
440 | return ret; |
466 | return ret; |
Line 462... | Line 488... | ||
462 | { |
488 | { |
463 | const struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
489 | const struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
464 | int i, ret; |
490 | int i, ret; |
Line 465... | Line 491... | ||
465 | 491 | ||
466 | for (i = 0; i < entry->relocation_count; i++) { |
492 | for (i = 0; i < entry->relocation_count; i++) { |
467 | ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i], |
- | |
468 | vma->vm); |
493 | ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i]); |
469 | if (ret) |
494 | if (ret) |
470 | return ret; |
495 | return ret; |
Line 471... | Line 496... | ||
471 | } |
496 | } |
Line 505... | Line 530... | ||
505 | i915_is_ggtt(vma->vm); |
530 | i915_is_ggtt(vma->vm); |
506 | } |
531 | } |
Line 507... | Line 532... | ||
507 | 532 | ||
508 | static int |
533 | static int |
509 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, |
534 | i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, |
510 | struct intel_ring_buffer *ring, |
535 | struct intel_engine_cs *ring, |
511 | bool *need_reloc) |
536 | bool *need_reloc) |
512 | { |
537 | { |
513 | struct drm_i915_private *dev_priv = ring->dev->dev_private; |
538 | struct drm_i915_gem_object *obj = vma->obj; |
514 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
539 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
515 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
540 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
516 | bool need_fence, need_mappable; |
541 | bool need_fence; |
517 | struct drm_i915_gem_object *obj = vma->obj; |
542 | uint64_t flags; |
Line -... | Line 543... | ||
- | 543 | int ret; |
|
- | 544 | ||
518 | int ret; |
545 | flags = 0; |
519 | 546 | ||
520 | need_fence = |
547 | need_fence = |
521 | has_fenced_gpu_access && |
548 | has_fenced_gpu_access && |
522 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
549 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
- | 550 | obj->tiling_mode != I915_TILING_NONE; |
|
- | 551 | if (need_fence || need_reloc_mappable(vma)) |
|
- | 552 | flags |= PIN_MAPPABLE; |
|
- | 553 | ||
- | 554 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT) |
|
- | 555 | flags |= PIN_GLOBAL; |
|
Line 523... | Line 556... | ||
523 | obj->tiling_mode != I915_TILING_NONE; |
556 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) |
524 | need_mappable = need_fence || need_reloc_mappable(vma); |
- | |
525 | 557 | flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; |
|
526 | ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, need_mappable, |
558 | |
Line 527... | Line 559... | ||
527 | false); |
559 | ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); |
Line 541... | Line 573... | ||
541 | 573 | ||
542 | obj->pending_fenced_gpu_access = true; |
574 | obj->pending_fenced_gpu_access = true; |
543 | } |
575 | } |
Line 544... | Line -... | ||
544 | } |
- | |
545 | - | ||
546 | /* Ensure ppgtt mapping exists if needed */ |
- | |
547 | if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) { |
- | |
548 | i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt, |
- | |
549 | obj, obj->cache_level); |
- | |
550 | - | ||
551 | obj->has_aliasing_ppgtt_mapping = 1; |
- | |
552 | } |
576 | } |
553 | 577 | ||
554 | if (entry->offset != vma->node.start) { |
578 | if (entry->offset != vma->node.start) { |
555 | entry->offset = vma->node.start; |
579 | entry->offset = vma->node.start; |
Line 556... | Line 580... | ||
556 | *need_reloc = true; |
580 | *need_reloc = true; |
557 | } |
581 | } |
558 | 582 | ||
559 | if (entry->flags & EXEC_OBJECT_WRITE) { |
583 | if (entry->flags & EXEC_OBJECT_WRITE) { |
Line 560... | Line -... | ||
560 | obj->base.pending_read_domains = I915_GEM_DOMAIN_RENDER; |
- | |
561 | obj->base.pending_write_domain = I915_GEM_DOMAIN_RENDER; |
- | |
562 | } |
- | |
563 | - | ||
564 | if (entry->flags & EXEC_OBJECT_NEEDS_GTT && |
584 | obj->base.pending_read_domains = I915_GEM_DOMAIN_RENDER; |
565 | !obj->has_global_gtt_mapping) |
585 | obj->base.pending_write_domain = I915_GEM_DOMAIN_RENDER; |
Line -... | Line 586... | ||
- | 586 | } |
|
- | 587 | ||
- | 588 | return 0; |
|
- | 589 | } |
|
- | 590 | ||
- | 591 | static bool |
|
- | 592 | eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access) |
|
- | 593 | { |
|
- | 594 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
|
- | 595 | struct drm_i915_gem_object *obj = vma->obj; |
|
- | 596 | bool need_fence, need_mappable; |
|
- | 597 | ||
- | 598 | need_fence = |
|
- | 599 | has_fenced_gpu_access && |
|
- | 600 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
|
- | 601 | obj->tiling_mode != I915_TILING_NONE; |
|
- | 602 | need_mappable = need_fence || need_reloc_mappable(vma); |
|
- | 603 | ||
- | 604 | WARN_ON((need_mappable || need_fence) && |
|
- | 605 | !i915_is_ggtt(vma->vm)); |
|
- | 606 | ||
- | 607 | if (entry->alignment && |
|
- | 608 | vma->node.start & (entry->alignment - 1)) |
|
- | 609 | return true; |
|
- | 610 | ||
- | 611 | if (need_mappable && !obj->map_and_fenceable) |
|
- | 612 | return true; |
|
- | 613 | ||
- | 614 | if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS && |
|
- | 615 | vma->node.start < BATCH_OFFSET_BIAS) |
|
566 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
616 | return true; |
567 | 617 | ||
568 | return 0; |
618 | return false; |
569 | } |
619 | } |
570 | 620 | ||
571 | static int |
621 | static int |
572 | i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, |
622 | i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, |
Line 581... | Line 631... | ||
581 | int retry; |
631 | int retry; |
Line 582... | Line 632... | ||
582 | 632 | ||
583 | if (list_empty(vmas)) |
633 | if (list_empty(vmas)) |
Line -... | Line 634... | ||
- | 634 | return 0; |
|
- | 635 | ||
584 | return 0; |
636 | i915_gem_retire_requests_ring(ring); |
Line 585... | Line 637... | ||
585 | 637 | ||
586 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; |
638 | vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; |
587 | 639 | ||
Line 627... | Line 679... | ||
627 | do { |
679 | do { |
628 | int ret = 0; |
680 | int ret = 0; |
Line 629... | Line 681... | ||
629 | 681 | ||
630 | /* Unbind any ill-fitting objects or pin. */ |
682 | /* Unbind any ill-fitting objects or pin. */ |
631 | list_for_each_entry(vma, vmas, exec_list) { |
- | |
632 | struct drm_i915_gem_exec_object2 *entry = vma->exec_entry; |
- | |
633 | bool need_fence, need_mappable; |
- | |
634 | - | ||
635 | obj = vma->obj; |
- | |
636 | 683 | list_for_each_entry(vma, vmas, exec_list) { |
|
637 | if (!drm_mm_node_allocated(&vma->node)) |
684 | if (!drm_mm_node_allocated(&vma->node)) |
Line 638... | Line -... | ||
638 | continue; |
- | |
639 | 685 | continue; |
|
640 | need_fence = |
- | |
641 | has_fenced_gpu_access && |
- | |
642 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && |
- | |
643 | obj->tiling_mode != I915_TILING_NONE; |
- | |
644 | need_mappable = need_fence || need_reloc_mappable(vma); |
- | |
645 | - | ||
646 | WARN_ON((need_mappable || need_fence) && |
- | |
647 | !i915_is_ggtt(vma->vm)); |
- | |
648 | - | ||
649 | if ((entry->alignment && |
- | |
650 | vma->node.start & (entry->alignment - 1)) || |
686 | |
651 | (need_mappable && !obj->map_and_fenceable)) |
687 | if (eb_vma_misplaced(vma, has_fenced_gpu_access)) |
652 | ret = i915_vma_unbind(vma); |
688 | ret = i915_vma_unbind(vma); |
653 | else |
689 | else |
654 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
690 | ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); |
Line 672... | Line 708... | ||
672 | 708 | ||
673 | /* Decrement pin count for bound objects */ |
709 | /* Decrement pin count for bound objects */ |
674 | list_for_each_entry(vma, vmas, exec_list) |
710 | list_for_each_entry(vma, vmas, exec_list) |
Line 675... | Line 711... | ||
675 | i915_gem_execbuffer_unreserve_vma(vma); |
711 | i915_gem_execbuffer_unreserve_vma(vma); |
676 | 712 | ||
677 | // ret = i915_gem_evict_vm(vm, true); |
713 | ret = i915_gem_evict_vm(vm, true); |
678 | if (ret) |
714 | if (ret) |
679 | return ret; |
715 | return ret; |
Line 680... | Line 716... | ||
680 | } while (1); |
716 | } while (1); |
681 | } |
717 | } |
682 | 718 | ||
683 | static int |
719 | static int |
684 | i915_gem_execbuffer_relocate_slow(struct drm_device *dev, |
720 | i915_gem_execbuffer_relocate_slow(struct drm_device *dev, |
685 | struct drm_i915_gem_execbuffer2 *args, |
721 | struct drm_i915_gem_execbuffer2 *args, |
686 | struct drm_file *file, |
722 | struct drm_file *file, |
687 | struct intel_ring_buffer *ring, |
723 | struct intel_engine_cs *ring, |
688 | struct eb_vmas *eb, |
724 | struct eb_vmas *eb, |
689 | struct drm_i915_gem_exec_object2 *exec) |
725 | struct drm_i915_gem_exec_object2 *exec) |
Line 747... | Line 783... | ||
747 | * presumed_offset before the next execbuffer - if that |
783 | * presumed_offset before the next execbuffer - if that |
748 | * happened we would make the mistake of assuming that the |
784 | * happened we would make the mistake of assuming that the |
749 | * relocations were valid. |
785 | * relocations were valid. |
750 | */ |
786 | */ |
751 | for (j = 0; j < exec[i].relocation_count; j++) { |
787 | for (j = 0; j < exec[i].relocation_count; j++) { |
752 | if (copy_to_user(&user_relocs[j].presumed_offset, |
788 | if (__copy_to_user(&user_relocs[j].presumed_offset, |
753 | &invalid_offset, |
789 | &invalid_offset, |
754 | sizeof(invalid_offset))) { |
790 | sizeof(invalid_offset))) { |
755 | ret = -EFAULT; |
791 | ret = -EFAULT; |
756 | mutex_lock(&dev->struct_mutex); |
792 | mutex_lock(&dev->struct_mutex); |
757 | goto err; |
793 | goto err; |
Line 798... | Line 834... | ||
798 | kfree(reloc_offset); |
834 | kfree(reloc_offset); |
799 | return ret; |
835 | return ret; |
800 | } |
836 | } |
Line 801... | Line 837... | ||
801 | 837 | ||
802 | static int |
838 | static int |
803 | i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, |
839 | i915_gem_execbuffer_move_to_gpu(struct intel_engine_cs *ring, |
804 | struct list_head *vmas) |
840 | struct list_head *vmas) |
805 | { |
841 | { |
806 | struct i915_vma *vma; |
842 | struct i915_vma *vma; |
807 | uint32_t flush_domains = 0; |
843 | uint32_t flush_domains = 0; |
Line 874... | Line 910... | ||
874 | } |
910 | } |
Line 875... | Line 911... | ||
875 | 911 | ||
876 | return 0; |
912 | return 0; |
Line 877... | Line 913... | ||
877 | } |
913 | } |
878 | 914 | ||
879 | static int |
915 | static struct intel_context * |
880 | i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, |
916 | i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, |
- | 917 | struct intel_engine_cs *ring, const u32 ctx_id) |
|
881 | const u32 ctx_id) |
918 | { |
Line 882... | Line 919... | ||
882 | { |
919 | struct intel_context *ctx = NULL; |
883 | struct i915_ctx_hang_stats *hs; |
- | |
884 | 920 | struct i915_ctx_hang_stats *hs; |
|
Line -... | Line 921... | ||
- | 921 | ||
- | 922 | if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE) |
|
- | 923 | return ERR_PTR(-EINVAL); |
|
- | 924 | ||
- | 925 | ctx = i915_gem_context_get(file->driver_priv, ctx_id); |
|
885 | hs = i915_gem_context_get_hang_stats(dev, file, ctx_id); |
926 | if (IS_ERR(ctx)) |
886 | if (IS_ERR(hs)) |
927 | return ctx; |
887 | return PTR_ERR(hs); |
928 | |
888 | 929 | hs = &ctx->hang_stats; |
|
Line 889... | Line 930... | ||
889 | if (hs->banned) { |
930 | if (hs->banned) { |
890 | DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id); |
931 | DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id); |
Line 891... | Line 932... | ||
891 | return -EIO; |
932 | return ERR_PTR(-EIO); |
892 | } |
933 | } |
893 | 934 | ||
894 | return 0; |
935 | return ctx; |
895 | } |
936 | } |
Line 896... | Line 937... | ||
896 | 937 | ||
897 | static void |
938 | static void |
Line 913... | Line 954... | ||
913 | 954 | ||
914 | i915_vma_move_to_active(vma, ring); |
955 | i915_vma_move_to_active(vma, ring); |
915 | if (obj->base.write_domain) { |
956 | if (obj->base.write_domain) { |
916 | obj->dirty = 1; |
957 | obj->dirty = 1; |
- | 958 | obj->last_write_seqno = intel_ring_get_seqno(ring); |
|
- | 959 | ||
- | 960 | intel_fb_obj_invalidate(obj, ring); |
|
917 | obj->last_write_seqno = intel_ring_get_seqno(ring); |
961 | |
918 | if (obj->pin_count) /* check for potential scanout */ |
962 | /* update for the implicit flush after a batch */ |
919 | intel_mark_fb_busy(obj, ring); |
963 | obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS; |
Line 920... | Line 964... | ||
920 | } |
964 | } |
921 | 965 | ||
922 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
966 | trace_i915_gem_object_change_domain(obj, old_read, old_write); |
Line 923... | Line 967... | ||
923 | } |
967 | } |
924 | } |
968 | } |
925 | 969 | ||
926 | static void |
970 | static void |
927 | i915_gem_execbuffer_retire_commands(struct drm_device *dev, |
971 | i915_gem_execbuffer_retire_commands(struct drm_device *dev, |
928 | struct drm_file *file, |
972 | struct drm_file *file, |
929 | struct intel_ring_buffer *ring, |
973 | struct intel_engine_cs *ring, |
930 | struct drm_i915_gem_object *obj) |
974 | struct drm_i915_gem_object *obj) |
Line 936... | Line 980... | ||
936 | (void)__i915_add_request(ring, file, obj, NULL); |
980 | (void)__i915_add_request(ring, file, obj, NULL); |
937 | } |
981 | } |
Line 938... | Line 982... | ||
938 | 982 | ||
939 | static int |
983 | static int |
940 | i915_reset_gen7_sol_offsets(struct drm_device *dev, |
984 | i915_reset_gen7_sol_offsets(struct drm_device *dev, |
941 | struct intel_ring_buffer *ring) |
985 | struct intel_engine_cs *ring) |
942 | { |
986 | { |
943 | drm_i915_private_t *dev_priv = dev->dev_private; |
987 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 944... | Line 988... | ||
944 | int ret, i; |
988 | int ret, i; |
- | 989 | ||
945 | 990 | if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) { |
|
- | 991 | DRM_DEBUG("sol reset is gen7/rcs only\n"); |
|
Line 946... | Line 992... | ||
946 | if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) |
992 | return -EINVAL; |
947 | return 0; |
993 | } |
948 | 994 | ||
Line 960... | Line 1006... | ||
960 | 1006 | ||
961 | return 0; |
1007 | return 0; |
Line 962... | Line 1008... | ||
962 | } |
1008 | } |
963 | 1009 | ||
964 | static int |
1010 | static int |
- | 1011 | legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, |
|
965 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
1012 | struct intel_engine_cs *ring, |
- | 1013 | struct intel_context *ctx, |
|
966 | struct drm_file *file, |
1014 | struct drm_i915_gem_execbuffer2 *args, |
967 | struct drm_i915_gem_execbuffer2 *args, |
1015 | struct list_head *vmas, |
968 | struct drm_i915_gem_exec_object2 *exec, |
1016 | struct drm_i915_gem_object *batch_obj, |
969 | struct i915_address_space *vm) |
- | |
970 | { |
- | |
971 | drm_i915_private_t *dev_priv = dev->dev_private; |
- | |
972 | struct eb_vmas *eb; |
1017 | u64 exec_start, u32 flags) |
973 | struct drm_i915_gem_object *batch_obj; |
- | |
974 | struct drm_clip_rect *cliprects = NULL; |
1018 | { |
975 | struct intel_ring_buffer *ring; |
1019 | struct drm_clip_rect *cliprects = NULL; |
976 | const u32 ctx_id = i915_execbuffer2_get_context_id(*args); |
1020 | struct drm_i915_private *dev_priv = dev->dev_private; |
977 | u32 exec_start, exec_len; |
1021 | u64 exec_len; |
978 | u32 mask, flags; |
1022 | int instp_mode; |
Line 979... | Line 1023... | ||
979 | int ret, mode, i; |
1023 | u32 instp_mask; |
- | 1024 | int i, ret = 0; |
|
- | 1025 | ||
980 | bool need_relocs; |
1026 | if (args->num_cliprects != 0) { |
- | 1027 | if (ring != &dev_priv->ring[RCS]) { |
|
Line -... | Line 1028... | ||
- | 1028 | DRM_DEBUG("clip rectangles are only valid with the render ring\n"); |
|
981 | 1029 | return -EINVAL; |
|
982 | if (!i915_gem_check_execbuffer(args)) |
- | |
983 | return -EINVAL; |
1030 | } |
984 | 1031 | ||
985 | ret = validate_exec_list(exec, args->buffer_count); |
- | |
986 | if (ret) |
- | |
Line -... | Line 1032... | ||
- | 1032 | if (INTEL_INFO(dev)->gen >= 5) { |
|
- | 1033 | DRM_DEBUG("clip rectangles are only valid on pre-gen5\n"); |
|
987 | return ret; |
1034 | return -EINVAL; |
- | 1035 | } |
|
988 | 1036 | ||
989 | flags = 0; |
- | |
990 | if (args->flags & I915_EXEC_SECURE) { |
- | |
Line 991... | Line 1037... | ||
991 | 1037 | if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) { |
|
992 | flags |= I915_DISPATCH_SECURE; |
- | |
993 | } |
- | |
994 | if (args->flags & I915_EXEC_IS_PINNED) |
1038 | DRM_DEBUG("execbuf with %u cliprects\n", |
995 | flags |= I915_DISPATCH_PINNED; |
- | |
996 | 1039 | args->num_cliprects); |
|
997 | switch (args->flags & I915_EXEC_RING_MASK) { |
- | |
998 | case I915_EXEC_DEFAULT: |
1040 | return -EINVAL; |
999 | case I915_EXEC_RENDER: |
- | |
1000 | ring = &dev_priv->ring[RCS]; |
1041 | } |
1001 | break; |
1042 | |
1002 | case I915_EXEC_BSD: |
1043 | cliprects = kcalloc(args->num_cliprects, |
1003 | ring = &dev_priv->ring[VCS]; |
1044 | sizeof(*cliprects), |
1004 | if (ctx_id != DEFAULT_CONTEXT_ID) { |
- | |
1005 | DRM_DEBUG("Ring %s doesn't support contexts\n", |
1045 | GFP_KERNEL); |
1006 | ring->name); |
1046 | if (cliprects == NULL) { |
1007 | return -EPERM; |
1047 | ret = -ENOMEM; |
1008 | } |
1048 | goto error; |
1009 | break; |
1049 | } |
1010 | case I915_EXEC_BLT: |
1050 | |
1011 | ring = &dev_priv->ring[BCS]; |
1051 | if (copy_from_user(cliprects, |
1012 | if (ctx_id != DEFAULT_CONTEXT_ID) { |
- | |
1013 | DRM_DEBUG("Ring %s doesn't support contexts\n", |
- | |
1014 | ring->name); |
1052 | to_user_ptr(args->cliprects_ptr), |
1015 | return -EPERM; |
1053 | sizeof(*cliprects)*args->num_cliprects)) { |
1016 | } |
1054 | ret = -EFAULT; |
1017 | break; |
- | |
1018 | case I915_EXEC_VEBOX: |
1055 | goto error; |
1019 | ring = &dev_priv->ring[VECS]; |
- | |
Line 1020... | Line -... | ||
1020 | if (ctx_id != DEFAULT_CONTEXT_ID) { |
- | |
1021 | DRM_DEBUG("Ring %s doesn't support contexts\n", |
1056 | } |
1022 | ring->name); |
1057 | } else { |
1023 | return -EPERM; |
1058 | if (args->DR4 == 0xffffffff) { |
1024 | } |
1059 | DRM_DEBUG("UXA submitting garbage DR4, fixing up\n"); |
1025 | break; |
- | |
1026 | - | ||
1027 | default: |
- | |
1028 | DRM_DEBUG("execbuf with unknown ring: %d\n", |
- | |
1029 | (int)(args->flags & I915_EXEC_RING_MASK)); |
1060 | args->DR4 = 0; |
Line -... | Line 1061... | ||
- | 1061 | } |
|
- | 1062 | ||
- | 1063 | if (args->DR1 || args->DR4 || args->cliprects_ptr) { |
|
- | 1064 | DRM_DEBUG("0 cliprects but dirt in cliprects fields\n"); |
|
- | 1065 | return -EINVAL; |
|
- | 1066 | } |
|
- | 1067 | } |
|
- | 1068 | ||
1030 | return -EINVAL; |
1069 | ret = i915_gem_execbuffer_move_to_gpu(ring, vmas); |
1031 | } |
1070 | if (ret) |
1032 | if (!intel_ring_initialized(ring)) { |
1071 | goto error; |
1033 | DRM_DEBUG("execbuf with invalid ring: %d\n", |
1072 | |
1034 | (int)(args->flags & I915_EXEC_RING_MASK)); |
1073 | ret = i915_switch_context(ring, ctx); |
1035 | return -EINVAL; |
1074 | if (ret) |
1036 | } |
1075 | goto error; |
- | 1076 | ||
- | 1077 | instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; |
|
- | 1078 | instp_mask = I915_EXEC_CONSTANTS_MASK; |
|
- | 1079 | switch (instp_mode) { |
|
- | 1080 | case I915_EXEC_CONSTANTS_REL_GENERAL: |
|
1037 | 1081 | case I915_EXEC_CONSTANTS_ABSOLUTE: |
|
1038 | mode = args->flags & I915_EXEC_CONSTANTS_MASK; |
1082 | case I915_EXEC_CONSTANTS_REL_SURFACE: |
- | 1083 | if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) { |
|
1039 | mask = I915_EXEC_CONSTANTS_MASK; |
1084 | DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); |
- | 1085 | ret = -EINVAL; |
|
- | 1086 | goto error; |
|
Line 1040... | Line 1087... | ||
1040 | switch (mode) { |
1087 | } |
1041 | case I915_EXEC_CONSTANTS_REL_GENERAL: |
1088 | |
- | 1089 | if (instp_mode != dev_priv->relative_constants_mode) { |
|
1042 | case I915_EXEC_CONSTANTS_ABSOLUTE: |
1090 | if (INTEL_INFO(dev)->gen < 4) { |
- | 1091 | DRM_DEBUG("no rel constants on pre-gen4\n"); |
|
- | 1092 | ret = -EINVAL; |
|
Line 1043... | Line 1093... | ||
1043 | case I915_EXEC_CONSTANTS_REL_SURFACE: |
1093 | goto error; |
1044 | if (ring == &dev_priv->ring[RCS] && |
1094 | } |
1045 | mode != dev_priv->relative_constants_mode) { |
1095 | |
1046 | if (INTEL_INFO(dev)->gen < 4) |
1096 | if (INTEL_INFO(dev)->gen > 5 && |
1047 | return -EINVAL; |
1097 | instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) { |
1048 | 1098 | DRM_DEBUG("rel surface constants mode invalid on gen5+\n"); |
|
1049 | if (INTEL_INFO(dev)->gen > 5 && |
1099 | ret = -EINVAL; |
1050 | mode == I915_EXEC_CONSTANTS_REL_SURFACE) |
1100 | goto error; |
- | 1101 | } |
|
1051 | return -EINVAL; |
1102 | |
Line 1052... | Line 1103... | ||
1052 | 1103 | /* The HW changed the meaning on this bit on gen6 */ |
|
1053 | /* The HW changed the meaning on this bit on gen6 */ |
1104 | if (INTEL_INFO(dev)->gen >= 6) |
- | 1105 | instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE; |
|
- | 1106 | } |
|
1054 | if (INTEL_INFO(dev)->gen >= 6) |
1107 | break; |
- | 1108 | default: |
|
- | 1109 | DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode); |
|
- | 1110 | ret = -EINVAL; |
|
- | 1111 | goto error; |
|
- | 1112 | } |
|
- | 1113 | ||
- | 1114 | if (ring == &dev_priv->ring[RCS] && |
|
- | 1115 | instp_mode != dev_priv->relative_constants_mode) { |
|
1055 | mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE; |
1116 | ret = intel_ring_begin(ring, 4); |
Line 1056... | Line 1117... | ||
1056 | } |
1117 | if (ret) |
1057 | break; |
1118 | goto error; |
1058 | default: |
1119 | |
1059 | DRM_DEBUG("execbuf with unknown constants: %d\n", mode); |
1120 | intel_ring_emit(ring, MI_NOOP); |
1060 | return -EINVAL; |
1121 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); |
Line -... | Line 1122... | ||
- | 1122 | intel_ring_emit(ring, INSTPM); |
|
- | 1123 | intel_ring_emit(ring, instp_mask << 16 | instp_mode); |
|
1061 | } |
1124 | intel_ring_advance(ring); |
1062 | 1125 | ||
- | 1126 | dev_priv->relative_constants_mode = instp_mode; |
|
- | 1127 | } |
|
- | 1128 | ||
- | 1129 | if (args->flags & I915_EXEC_GEN7_SOL_RESET) { |
|
- | 1130 | ret = i915_reset_gen7_sol_offsets(dev, ring); |
|
- | 1131 | if (ret) |
|
- | 1132 | goto error; |
|
- | 1133 | } |
|
- | 1134 | ||
- | 1135 | exec_len = args->batch_len; |
|
- | 1136 | if (cliprects) { |
|
- | 1137 | for (i = 0; i < args->num_cliprects; i++) { |
|
- | 1138 | ret = i915_emit_box(dev, &cliprects[i], |
|
- | 1139 | args->DR1, args->DR4); |
|
- | 1140 | if (ret) |
|
1063 | if (args->buffer_count < 1) { |
1141 | goto error; |
1064 | DRM_DEBUG("execbuf with %d buffers\n", args->buffer_count); |
1142 | |
Line 1065... | Line 1143... | ||
1065 | return -EINVAL; |
1143 | ret = ring->dispatch_execbuffer(ring, |
- | 1144 | exec_start, exec_len, |
|
1066 | } |
1145 | flags); |
- | 1146 | if (ret) |
|
- | 1147 | goto error; |
|
- | 1148 | } |
|
1067 | 1149 | } else { |
|
- | 1150 | ret = ring->dispatch_execbuffer(ring, |
|
- | 1151 | exec_start, exec_len, |
|
- | 1152 | flags); |
|
- | 1153 | if (ret) |
|
- | 1154 | return ret; |
|
- | 1155 | } |
|
- | 1156 | ||
- | 1157 | trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags); |
|
- | 1158 | ||
- | 1159 | i915_gem_execbuffer_move_to_active(vmas, ring); |
|
- | 1160 | i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); |
|
- | 1161 | ||
- | 1162 | error: |
|
- | 1163 | kfree(cliprects); |
|
- | 1164 | return ret; |
|
- | 1165 | } |
|
- | 1166 | ||
- | 1167 | /** |
|
- | 1168 | * Find one BSD ring to dispatch the corresponding BSD command. |
|
- | 1169 | * The Ring ID is returned. |
|
- | 1170 | */ |
|
- | 1171 | static int gen8_dispatch_bsd_ring(struct drm_device *dev, |
|
- | 1172 | struct drm_file *file) |
|
- | 1173 | { |
|
- | 1174 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1175 | struct drm_i915_file_private *file_priv = file->driver_priv; |
|
- | 1176 | ||
- | 1177 | /* Check whether the file_priv is using one ring */ |
|
- | 1178 | if (file_priv->bsd_ring) |
|
- | 1179 | return file_priv->bsd_ring->id; |
|
- | 1180 | else { |
|
- | 1181 | /* If no, use the ping-pong mechanism to select one ring */ |
|
- | 1182 | int ring_id; |
|
- | 1183 | ||
- | 1184 | mutex_lock(&dev->struct_mutex); |
|
- | 1185 | if (dev_priv->mm.bsd_ring_dispatch_index == 0) { |
|
- | 1186 | ring_id = VCS; |
|
- | 1187 | dev_priv->mm.bsd_ring_dispatch_index = 1; |
|
- | 1188 | } else { |
|
- | 1189 | ring_id = VCS2; |
|
- | 1190 | dev_priv->mm.bsd_ring_dispatch_index = 0; |
|
- | 1191 | } |
|
- | 1192 | file_priv->bsd_ring = &dev_priv->ring[ring_id]; |
|
- | 1193 | mutex_unlock(&dev->struct_mutex); |
|
- | 1194 | return ring_id; |
|
- | 1195 | } |
|
- | 1196 | } |
|
- | 1197 | ||
- | 1198 | static struct drm_i915_gem_object * |
|
- | 1199 | eb_get_batch(struct eb_vmas *eb) |
|
- | 1200 | { |
|
- | 1201 | struct i915_vma *vma = list_entry(eb->vmas.prev, typeof(*vma), exec_list); |
|
- | 1202 | ||
- | 1203 | /* |
|
- | 1204 | * SNA is doing fancy tricks with compressing batch buffers, which leads |
|
- | 1205 | * to negative relocation deltas. Usually that works out ok since the |
|
- | 1206 | * relocate address is still positive, except when the batch is placed |
|
- | 1207 | * very low in the GTT. Ensure this doesn't happen. |
|
- | 1208 | * |
|
- | 1209 | * Note that actual hangs have only been observed on gen7, but for |
|
- | 1210 | * paranoia do it everywhere. |
|
- | 1211 | */ |
|
- | 1212 | vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS; |
|
- | 1213 | ||
- | 1214 | return vma->obj; |
|
- | 1215 | } |
|
- | 1216 | ||
- | 1217 | static int |
|
- | 1218 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
|
- | 1219 | struct drm_file *file, |
|
- | 1220 | struct drm_i915_gem_execbuffer2 *args, |
|
- | 1221 | struct drm_i915_gem_exec_object2 *exec) |
|
1068 | if (args->num_cliprects != 0) { |
1222 | { |
- | 1223 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1224 | struct eb_vmas *eb; |
|
- | 1225 | struct drm_i915_gem_object *batch_obj; |
|
- | 1226 | struct intel_engine_cs *ring; |
|
- | 1227 | struct intel_context *ctx; |
|
- | 1228 | struct i915_address_space *vm; |
|
- | 1229 | const u32 ctx_id = i915_execbuffer2_get_context_id(*args); |
|
- | 1230 | u64 exec_start = args->batch_start_offset; |
|
- | 1231 | u32 flags; |
|
1069 | if (ring != &dev_priv->ring[RCS]) { |
1232 | int ret; |
- | 1233 | bool need_relocs; |
|
- | 1234 | ||
Line 1070... | Line 1235... | ||
1070 | DRM_DEBUG("clip rectangles are only valid with the render ring\n"); |
1235 | if (!i915_gem_check_execbuffer(args)) |
1071 | return -EINVAL; |
1236 | return -EINVAL; |
1072 | } |
1237 | |
1073 | - | ||
1074 | if (INTEL_INFO(dev)->gen >= 5) { |
1238 | ret = validate_exec_list(exec, args->buffer_count); |
1075 | DRM_DEBUG("clip rectangles are only valid on pre-gen5\n"); |
- | |
1076 | return -EINVAL; |
1239 | if (ret) |
Line -... | Line 1240... | ||
- | 1240 | return ret; |
|
- | 1241 | ||
- | 1242 | flags = 0; |
|
1077 | } |
1243 | if (args->flags & I915_EXEC_SECURE) { |
- | 1244 | ||
1078 | 1245 | flags |= I915_DISPATCH_SECURE; |
|
1079 | if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) { |
1246 | } |
- | 1247 | if (args->flags & I915_EXEC_IS_PINNED) |
|
1080 | DRM_DEBUG("execbuf with %u cliprects\n", |
1248 | flags |= I915_DISPATCH_PINNED; |
- | 1249 | ||
- | 1250 | if ((args->flags & I915_EXEC_RING_MASK) > LAST_USER_RING) { |
|
- | 1251 | DRM_DEBUG("execbuf with unknown ring: %d\n", |
|
- | 1252 | (int)(args->flags & I915_EXEC_RING_MASK)); |
|
- | 1253 | return -EINVAL; |
|
- | 1254 | } |
|
1081 | args->num_cliprects); |
1255 | |
1082 | return -EINVAL; |
1256 | if ((args->flags & I915_EXEC_RING_MASK) == I915_EXEC_DEFAULT) |
- | 1257 | ring = &dev_priv->ring[RCS]; |
|
- | 1258 | else if ((args->flags & I915_EXEC_RING_MASK) == I915_EXEC_BSD) { |
|
- | 1259 | if (HAS_BSD2(dev)) { |
|
- | 1260 | int ring_id; |
|
1083 | } |
1261 | ring_id = gen8_dispatch_bsd_ring(dev, file); |
Line 1084... | Line 1262... | ||
1084 | 1262 | ring = &dev_priv->ring[ring_id]; |
|
Line 1085... | Line 1263... | ||
1085 | cliprects = kcalloc(args->num_cliprects, |
1263 | } else |
Line 1108... | Line 1286... | ||
1108 | mutex_unlock(&dev->struct_mutex); |
1286 | mutex_unlock(&dev->struct_mutex); |
1109 | ret = -EBUSY; |
1287 | ret = -EBUSY; |
1110 | goto pre_mutex_err; |
1288 | goto pre_mutex_err; |
1111 | } |
1289 | } |
Line 1112... | Line 1290... | ||
1112 | 1290 | ||
1113 | ret = i915_gem_validate_context(dev, file, ctx_id); |
1291 | ctx = i915_gem_validate_context(dev, file, ring, ctx_id); |
1114 | if (ret) { |
1292 | if (IS_ERR(ctx)) { |
- | 1293 | mutex_unlock(&dev->struct_mutex); |
|
1115 | mutex_unlock(&dev->struct_mutex); |
1294 | ret = PTR_ERR(ctx); |
1116 | goto pre_mutex_err; |
1295 | goto pre_mutex_err; |
Line -... | Line 1296... | ||
- | 1296 | } |
|
- | 1297 | ||
- | 1298 | i915_gem_context_reference(ctx); |
|
- | 1299 | ||
- | 1300 | vm = ctx->vm; |
|
- | 1301 | if (!USES_FULL_PPGTT(dev)) |
|
1117 | } |
1302 | vm = &dev_priv->gtt.base; |
1118 | 1303 | ||
- | 1304 | eb = eb_create(args); |
|
1119 | eb = eb_create(args); |
1305 | if (eb == NULL) { |
1120 | if (eb == NULL) { |
1306 | i915_gem_context_unreference(ctx); |
1121 | mutex_unlock(&dev->struct_mutex); |
1307 | mutex_unlock(&dev->struct_mutex); |
1122 | ret = -ENOMEM; |
1308 | ret = -ENOMEM; |
Line 1127... | Line 1313... | ||
1127 | ret = eb_lookup_vmas(eb, exec, args, vm, file); |
1313 | ret = eb_lookup_vmas(eb, exec, args, vm, file); |
1128 | if (ret) |
1314 | if (ret) |
1129 | goto err; |
1315 | goto err; |
Line 1130... | Line 1316... | ||
1130 | 1316 | ||
1131 | /* take note of the batch buffer before we might reorder the lists */ |
1317 | /* take note of the batch buffer before we might reorder the lists */ |
Line 1132... | Line 1318... | ||
1132 | batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj; |
1318 | batch_obj = eb_get_batch(eb); |
1133 | 1319 | ||
1134 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
1320 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
1135 | need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; |
1321 | need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; |
Line 1155... | Line 1341... | ||
1155 | DRM_DEBUG("Attempting to use self-modifying batch buffer\n"); |
1341 | DRM_DEBUG("Attempting to use self-modifying batch buffer\n"); |
1156 | ret = -EINVAL; |
1342 | ret = -EINVAL; |
1157 | goto err; |
1343 | goto err; |
1158 | } |
1344 | } |
1159 | batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; |
1345 | batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; |
1160 | - | ||
1161 | /* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure |
- | |
1162 | * batch" bit. Hence we need to pin secure batches into the global gtt. |
- | |
1163 | * hsw should have this fixed, but bdw mucks it up again. */ |
- | |
1164 | if (flags & I915_DISPATCH_SECURE && !batch_obj->has_global_gtt_mapping) |
- | |
1165 | i915_gem_gtt_bind_object(batch_obj, batch_obj->cache_level); |
- | |
1166 | - | ||
1167 | ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas); |
- | |
1168 | if (ret) |
1346 | #if 0 |
1169 | goto err; |
1347 | if (i915_needs_cmd_parser(ring)) { |
1170 | - | ||
1171 | ret = i915_switch_context(ring, file, ctx_id); |
1348 | ret = i915_parse_cmds(ring, |
1172 | if (ret) |
- | |
1173 | goto err; |
1349 | batch_obj, |
1174 | - | ||
1175 | if (ring == &dev_priv->ring[RCS] && |
- | |
1176 | mode != dev_priv->relative_constants_mode) { |
1350 | args->batch_start_offset, |
1177 | ret = intel_ring_begin(ring, 4); |
1351 | file->is_master); |
1178 | if (ret) |
1352 | if (ret) |
1179 | goto err; |
1353 | goto err; |
Line -... | Line 1354... | ||
- | 1354 | ||
1180 | 1355 | /* |
|
- | 1356 | * XXX: Actually do this when enabling batch copy... |
|
1181 | intel_ring_emit(ring, MI_NOOP); |
1357 | * |
1182 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); |
1358 | * Set the DISPATCH_SECURE bit to remove the NON_SECURE bit |
1183 | intel_ring_emit(ring, INSTPM); |
1359 | * from MI_BATCH_BUFFER_START commands issued in the |
1184 | intel_ring_emit(ring, mask << 16 | mode); |
1360 | * dispatch_execbuffer implementations. We specifically don't |
1185 | intel_ring_advance(ring); |
1361 | * want that set when the command parser is enabled. |
1186 | - | ||
1187 | dev_priv->relative_constants_mode = mode; |
1362 | */ |
1188 | } |
1363 | } |
- | 1364 | #endif |
|
- | 1365 | /* 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. |
|
1189 | 1367 | * hsw should have this fixed, but bdw mucks it up again. */ |
|
1190 | if (args->flags & I915_EXEC_GEN7_SOL_RESET) { |
1368 | if (flags & I915_DISPATCH_SECURE && |
- | 1369 | !batch_obj->has_global_gtt_mapping) { |
|
1191 | ret = i915_reset_gen7_sol_offsets(dev, ring); |
1370 | /* When we have multiple VMs, we'll need to make sure that we |
- | 1371 | * allocate space first */ |
|
1192 | if (ret) |
1372 | struct i915_vma *vma = i915_gem_obj_to_ggtt(batch_obj); |
- | 1373 | BUG_ON(!vma); |
|
1193 | goto err; |
1374 | vma->bind_vma(vma, batch_obj->cache_level, GLOBAL_BIND); |
Line 1194... | Line -... | ||
1194 | } |
- | |
1195 | 1375 | } |
|
1196 | exec_start = i915_gem_obj_offset(batch_obj, vm) + |
1376 | |
1197 | args->batch_start_offset; |
1377 | if (flags & I915_DISPATCH_SECURE) |
1198 | exec_len = args->batch_len; |
- | |
1199 | if (cliprects) { |
1378 | exec_start += i915_gem_obj_ggtt_offset(batch_obj); |
1200 | for (i = 0; i < args->num_cliprects; i++) { |
- | |
1201 | ret = i915_emit_box(dev, &cliprects[i], |
- | |
1202 | args->DR1, args->DR4); |
- | |
Line 1203... | Line 1379... | ||
1203 | if (ret) |
1379 | else |
1204 | goto err; |
1380 | exec_start += i915_gem_obj_offset(batch_obj, vm); |
1205 | - | ||
1206 | ret = ring->dispatch_execbuffer(ring, |
1381 | |
1207 | exec_start, exec_len, |
1382 | ret = legacy_ringbuffer_submission(dev, file, ring, ctx, |
1208 | flags); |
- | |
1209 | if (ret) |
- | |
1210 | goto err; |
- | |
1211 | } |
- | |
1212 | } else { |
- | |
1213 | ret = ring->dispatch_execbuffer(ring, |
- | |
1214 | exec_start, exec_len, |
- | |
1215 | flags); |
- | |
1216 | if (ret) |
- | |
1217 | goto err; |
- | |
1218 | } |
- | |
1219 | - | ||
1220 | trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags); |
- | |
Line 1221... | Line 1383... | ||
1221 | 1383 | args, &eb->vmas, batch_obj, exec_start, flags); |
|
- | 1384 | if (ret) |
|
- | 1385 | goto err; |
|
1222 | i915_gem_execbuffer_move_to_active(&eb->vmas, ring); |
1386 | |
Line 1223... | Line 1387... | ||
1223 | i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); |
1387 | err: |
Line 1224... | Line 1388... | ||
1224 | 1388 | /* the request owns the ref now */ |
|
1225 | err: |
- | |
1226 | eb_destroy(eb); |
- | |
1227 | 1389 | i915_gem_context_unreference(ctx); |
|
1228 | mutex_unlock(&dev->struct_mutex); |
1390 | eb_destroy(eb); |
1229 | 1391 | ||
1230 | pre_mutex_err: |
1392 | mutex_unlock(&dev->struct_mutex); |
1231 | kfree(cliprects); |
1393 | |
Line 1243... | Line 1405... | ||
1243 | */ |
1405 | */ |
1244 | int |
1406 | int |
1245 | i915_gem_execbuffer(struct drm_device *dev, void *data, |
1407 | i915_gem_execbuffer(struct drm_device *dev, void *data, |
1246 | struct drm_file *file) |
1408 | struct drm_file *file) |
1247 | { |
1409 | { |
1248 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
1249 | struct drm_i915_gem_execbuffer *args = data; |
1410 | struct drm_i915_gem_execbuffer *args = data; |
1250 | struct drm_i915_gem_execbuffer2 exec2; |
1411 | struct drm_i915_gem_execbuffer2 exec2; |
1251 | struct drm_i915_gem_exec_object *exec_list = NULL; |
1412 | struct drm_i915_gem_exec_object *exec_list = NULL; |
1252 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
1413 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
1253 | int ret, i; |
1414 | int ret, i; |
Line 1299... | Line 1460... | ||
1299 | exec2.num_cliprects = args->num_cliprects; |
1460 | exec2.num_cliprects = args->num_cliprects; |
1300 | exec2.cliprects_ptr = args->cliprects_ptr; |
1461 | exec2.cliprects_ptr = args->cliprects_ptr; |
1301 | exec2.flags = I915_EXEC_RENDER; |
1462 | exec2.flags = I915_EXEC_RENDER; |
1302 | i915_execbuffer2_set_context_id(exec2, 0); |
1463 | i915_execbuffer2_set_context_id(exec2, 0); |
Line 1303... | Line 1464... | ||
1303 | 1464 | ||
1304 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list, |
- | |
1305 | &dev_priv->gtt.base); |
1465 | ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); |
- | 1466 | if (!ret) { |
|
- | 1467 | struct drm_i915_gem_exec_object __user *user_exec_list = |
|
- | 1468 | to_user_ptr(args->buffers_ptr); |
|
1306 | if (!ret) { |
1469 | |
1307 | /* Copy the new buffer offsets back to the user's exec list. */ |
1470 | /* Copy the new buffer offsets back to the user's exec list. */ |
1308 | for (i = 0; i < args->buffer_count; i++) |
- | |
1309 | exec_list[i].offset = exec2_list[i].offset; |
- | |
1310 | /* ... and back out to userspace */ |
1471 | for (i = 0; i < args->buffer_count; i++) { |
1311 | ret = copy_to_user(to_user_ptr(args->buffers_ptr), |
1472 | ret = __copy_to_user(&user_exec_list[i].offset, |
1312 | exec_list, |
1473 | &exec2_list[i].offset, |
1313 | sizeof(*exec_list) * args->buffer_count); |
1474 | sizeof(user_exec_list[i].offset)); |
1314 | if (ret) { |
1475 | if (ret) { |
1315 | ret = -EFAULT; |
1476 | ret = -EFAULT; |
1316 | DRM_DEBUG("failed to copy %d exec entries " |
1477 | DRM_DEBUG("failed to copy %d exec entries " |
1317 | "back to user (%d)\n", |
1478 | "back to user (%d)\n", |
- | 1479 | args->buffer_count, ret); |
|
- | 1480 | break; |
|
1318 | args->buffer_count, ret); |
1481 | } |
1319 | } |
1482 | } |
Line 1320... | Line 1483... | ||
1320 | } |
1483 | } |
1321 | 1484 | ||
Line 1327... | Line 1490... | ||
1327 | 1490 | ||
1328 | int |
1491 | int |
1329 | i915_gem_execbuffer2(struct drm_device *dev, void *data, |
1492 | i915_gem_execbuffer2(struct drm_device *dev, void *data, |
1330 | struct drm_file *file) |
1493 | struct drm_file *file) |
1331 | { |
- | |
1332 | struct drm_i915_private *dev_priv = dev->dev_private; |
1494 | { |
1333 | struct drm_i915_gem_execbuffer2 *args = data; |
1495 | struct drm_i915_gem_execbuffer2 *args = data; |
1334 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
1496 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; |
Line 1335... | Line 1497... | ||
1335 | int ret; |
1497 | int ret; |
1336 | 1498 | ||
1337 | if (args->buffer_count < 1 || |
1499 | if (args->buffer_count < 1 || |
1338 | args->buffer_count > UINT_MAX / sizeof(*exec2_list)) { |
1500 | args->buffer_count > UINT_MAX / sizeof(*exec2_list)) { |
1339 | DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count); |
1501 | DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count); |
Line -... | Line 1502... | ||
- | 1502 | return -EINVAL; |
|
- | 1503 | } |
|
- | 1504 | ||
- | 1505 | if (args->rsvd2 != 0) { |
|
- | 1506 | DRM_DEBUG("dirty rvsd2 field\n"); |
|
1340 | return -EINVAL; |
1507 | return -EINVAL; |
1341 | } |
1508 | } |
1342 | 1509 | ||
1343 | exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, |
1510 | exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, |
1344 | GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); |
1511 | GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); |
Line 1356... | Line 1523... | ||
1356 | kfree(exec2_list); |
1523 | kfree(exec2_list); |
1357 | FAIL(); |
1524 | FAIL(); |
1358 | return -EFAULT; |
1525 | return -EFAULT; |
1359 | } |
1526 | } |
Line 1360... | Line 1527... | ||
1360 | 1527 | ||
1361 | ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list, |
- | |
1362 | &dev_priv->gtt.base); |
1528 | ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); |
1363 | if (!ret) { |
1529 | if (!ret) { |
- | 1530 | /* Copy the new buffer offsets back to the user's exec list. */ |
|
1364 | /* Copy the new buffer offsets back to the user's exec list. */ |
1531 | struct drm_i915_gem_exec_object2 __user *user_exec_list = |
- | 1532 | to_user_ptr(args->buffers_ptr); |
|
- | 1533 | int i; |
|
- | 1534 | ||
- | 1535 | for (i = 0; i < args->buffer_count; i++) { |
|
1365 | ret = copy_to_user(to_user_ptr(args->buffers_ptr), |
1536 | ret = __copy_to_user(&user_exec_list[i].offset, |
1366 | exec2_list, |
1537 | &exec2_list[i].offset, |
1367 | sizeof(*exec2_list) * args->buffer_count); |
1538 | sizeof(user_exec_list[i].offset)); |
1368 | if (ret) { |
1539 | if (ret) { |
1369 | ret = -EFAULT; |
1540 | ret = -EFAULT; |
1370 | DRM_DEBUG("failed to copy %d exec entries " |
1541 | DRM_DEBUG("failed to copy %d exec entries " |
1371 | "back to user (%d)\n", |
1542 | "back to user\n", |
- | 1543 | args->buffer_count); |
|
- | 1544 | break; |
|
1372 | args->buffer_count, ret); |
1545 | } |
1373 | } |
1546 | } |
Line 1374... | Line 1547... | ||
1374 | } |
1547 | } |
1375 | 1548 |