diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 72 |
2 files changed, 47 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6130f77c26bf..385fc7ec39d3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -796,6 +796,7 @@ struct drm_i915_gem_object { | |||
| 796 | */ | 796 | */ |
| 797 | struct hlist_node exec_node; | 797 | struct hlist_node exec_node; |
| 798 | unsigned long exec_handle; | 798 | unsigned long exec_handle; |
| 799 | struct drm_i915_gem_exec_object2 *exec_entry; | ||
| 799 | 800 | ||
| 800 | /** | 801 | /** |
| 801 | * Current offset of the object in GTT space. | 802 | * Current offset of the object in GTT space. |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 0445770cc23c..e69834341ef0 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -268,7 +268,6 @@ eb_destroy(struct eb_objects *eb) | |||
| 268 | static int | 268 | static int |
| 269 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | 269 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
| 270 | struct eb_objects *eb, | 270 | struct eb_objects *eb, |
| 271 | struct drm_i915_gem_exec_object2 *entry, | ||
| 272 | struct drm_i915_gem_relocation_entry *reloc) | 271 | struct drm_i915_gem_relocation_entry *reloc) |
| 273 | { | 272 | { |
| 274 | struct drm_device *dev = obj->base.dev; | 273 | struct drm_device *dev = obj->base.dev; |
| @@ -411,10 +410,10 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
| 411 | 410 | ||
| 412 | static int | 411 | static int |
| 413 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, | 412 | i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, |
| 414 | struct eb_objects *eb, | 413 | struct eb_objects *eb) |
| 415 | struct drm_i915_gem_exec_object2 *entry) | ||
| 416 | { | 414 | { |
| 417 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 415 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
| 416 | struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; | ||
| 418 | int i, ret; | 417 | int i, ret; |
| 419 | 418 | ||
| 420 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; | 419 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; |
| @@ -426,7 +425,7 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, | |||
| 426 | sizeof(reloc))) | 425 | sizeof(reloc))) |
| 427 | return -EFAULT; | 426 | return -EFAULT; |
| 428 | 427 | ||
| 429 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &reloc); | 428 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc); |
| 430 | if (ret) | 429 | if (ret) |
| 431 | return ret; | 430 | return ret; |
| 432 | 431 | ||
| @@ -442,13 +441,13 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, | |||
| 442 | static int | 441 | static int |
| 443 | i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, | 442 | i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, |
| 444 | struct eb_objects *eb, | 443 | struct eb_objects *eb, |
| 445 | struct drm_i915_gem_exec_object2 *entry, | ||
| 446 | struct drm_i915_gem_relocation_entry *relocs) | 444 | struct drm_i915_gem_relocation_entry *relocs) |
| 447 | { | 445 | { |
| 446 | const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; | ||
| 448 | int i, ret; | 447 | int i, ret; |
| 449 | 448 | ||
| 450 | for (i = 0; i < entry->relocation_count; i++) { | 449 | for (i = 0; i < entry->relocation_count; i++) { |
| 451 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &relocs[i]); | 450 | ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i]); |
| 452 | if (ret) | 451 | if (ret) |
| 453 | return ret; | 452 | return ret; |
| 454 | } | 453 | } |
| @@ -459,8 +458,7 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, | |||
| 459 | static int | 458 | static int |
| 460 | i915_gem_execbuffer_relocate(struct drm_device *dev, | 459 | i915_gem_execbuffer_relocate(struct drm_device *dev, |
| 461 | struct eb_objects *eb, | 460 | struct eb_objects *eb, |
| 462 | struct list_head *objects, | 461 | struct list_head *objects) |
| 463 | struct drm_i915_gem_exec_object2 *exec) | ||
| 464 | { | 462 | { |
| 465 | struct drm_i915_gem_object *obj; | 463 | struct drm_i915_gem_object *obj; |
| 466 | int ret; | 464 | int ret; |
| @@ -468,7 +466,7 @@ i915_gem_execbuffer_relocate(struct drm_device *dev, | |||
| 468 | list_for_each_entry(obj, objects, exec_list) { | 466 | list_for_each_entry(obj, objects, exec_list) { |
| 469 | obj->base.pending_read_domains = 0; | 467 | obj->base.pending_read_domains = 0; |
| 470 | obj->base.pending_write_domain = 0; | 468 | obj->base.pending_write_domain = 0; |
| 471 | ret = i915_gem_execbuffer_relocate_object(obj, eb, exec++); | 469 | ret = i915_gem_execbuffer_relocate_object(obj, eb); |
| 472 | if (ret) | 470 | if (ret) |
| 473 | return ret; | 471 | return ret; |
| 474 | } | 472 | } |
| @@ -479,13 +477,36 @@ i915_gem_execbuffer_relocate(struct drm_device *dev, | |||
| 479 | static int | 477 | static int |
| 480 | i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | 478 | i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, |
| 481 | struct drm_file *file, | 479 | struct drm_file *file, |
| 482 | struct list_head *objects, | 480 | struct list_head *objects) |
| 483 | struct drm_i915_gem_exec_object2 *exec) | ||
| 484 | { | 481 | { |
| 485 | struct drm_i915_gem_object *obj; | 482 | struct drm_i915_gem_object *obj; |
| 486 | struct drm_i915_gem_exec_object2 *entry; | ||
| 487 | int ret, retry; | 483 | int ret, retry; |
| 488 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; | 484 | bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; |
| 485 | struct list_head ordered_objects; | ||
| 486 | |||
| 487 | INIT_LIST_HEAD(&ordered_objects); | ||
| 488 | while (!list_empty(objects)) { | ||
| 489 | struct drm_i915_gem_exec_object2 *entry; | ||
| 490 | bool need_fence, need_mappable; | ||
| 491 | |||
| 492 | obj = list_first_entry(objects, | ||
| 493 | struct drm_i915_gem_object, | ||
| 494 | exec_list); | ||
| 495 | entry = obj->exec_entry; | ||
| 496 | |||
| 497 | need_fence = | ||
| 498 | has_fenced_gpu_access && | ||
| 499 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
| 500 | obj->tiling_mode != I915_TILING_NONE; | ||
| 501 | need_mappable = | ||
| 502 | entry->relocation_count ? true : need_fence; | ||
| 503 | |||
| 504 | if (need_mappable) | ||
| 505 | list_move(&obj->exec_list, &ordered_objects); | ||
| 506 | else | ||
| 507 | list_move_tail(&obj->exec_list, &ordered_objects); | ||
| 508 | } | ||
| 509 | list_splice(&ordered_objects, objects); | ||
| 489 | 510 | ||
| 490 | /* Attempt to pin all of the buffers into the GTT. | 511 | /* Attempt to pin all of the buffers into the GTT. |
| 491 | * This is done in 3 phases: | 512 | * This is done in 3 phases: |
| @@ -504,14 +525,11 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | |||
| 504 | ret = 0; | 525 | ret = 0; |
| 505 | 526 | ||
| 506 | /* Unbind any ill-fitting objects or pin. */ | 527 | /* Unbind any ill-fitting objects or pin. */ |
| 507 | entry = exec; | ||
| 508 | list_for_each_entry(obj, objects, exec_list) { | 528 | list_for_each_entry(obj, objects, exec_list) { |
| 529 | struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; | ||
| 509 | bool need_fence, need_mappable; | 530 | bool need_fence, need_mappable; |
| 510 | 531 | if (!obj->gtt_space) | |
| 511 | if (!obj->gtt_space) { | ||
| 512 | entry++; | ||
| 513 | continue; | 532 | continue; |
| 514 | } | ||
| 515 | 533 | ||
| 516 | need_fence = | 534 | need_fence = |
| 517 | has_fenced_gpu_access && | 535 | has_fenced_gpu_access && |
| @@ -534,8 +552,8 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | |||
| 534 | } | 552 | } |
| 535 | 553 | ||
| 536 | /* Bind fresh objects */ | 554 | /* Bind fresh objects */ |
| 537 | entry = exec; | ||
| 538 | list_for_each_entry(obj, objects, exec_list) { | 555 | list_for_each_entry(obj, objects, exec_list) { |
| 556 | struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; | ||
| 539 | bool need_fence; | 557 | bool need_fence; |
| 540 | 558 | ||
| 541 | need_fence = | 559 | need_fence = |
| @@ -570,7 +588,6 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, | |||
| 570 | } | 588 | } |
| 571 | 589 | ||
| 572 | entry->offset = obj->gtt_offset; | 590 | entry->offset = obj->gtt_offset; |
| 573 | entry++; | ||
| 574 | } | 591 | } |
| 575 | 592 | ||
| 576 | /* Decrement pin count for bound objects */ | 593 | /* Decrement pin count for bound objects */ |
| @@ -680,10 +697,11 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
| 680 | 697 | ||
| 681 | list_add_tail(&obj->exec_list, objects); | 698 | list_add_tail(&obj->exec_list, objects); |
| 682 | obj->exec_handle = exec[i].handle; | 699 | obj->exec_handle = exec[i].handle; |
| 700 | obj->exec_entry = &exec[i]; | ||
| 683 | eb_add_object(eb, obj); | 701 | eb_add_object(eb, obj); |
| 684 | } | 702 | } |
| 685 | 703 | ||
| 686 | ret = i915_gem_execbuffer_reserve(ring, file, objects, exec); | 704 | ret = i915_gem_execbuffer_reserve(ring, file, objects); |
| 687 | if (ret) | 705 | if (ret) |
| 688 | goto err; | 706 | goto err; |
| 689 | 707 | ||
| @@ -692,7 +710,6 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
| 692 | obj->base.pending_read_domains = 0; | 710 | obj->base.pending_read_domains = 0; |
| 693 | obj->base.pending_write_domain = 0; | 711 | obj->base.pending_write_domain = 0; |
| 694 | ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, | 712 | ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, |
| 695 | exec, | ||
| 696 | reloc + total); | 713 | reloc + total); |
| 697 | if (ret) | 714 | if (ret) |
| 698 | goto err; | 715 | goto err; |
| @@ -1110,16 +1127,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1110 | 1127 | ||
| 1111 | list_add_tail(&obj->exec_list, &objects); | 1128 | list_add_tail(&obj->exec_list, &objects); |
| 1112 | obj->exec_handle = exec[i].handle; | 1129 | obj->exec_handle = exec[i].handle; |
| 1130 | obj->exec_entry = &exec[i]; | ||
| 1113 | eb_add_object(eb, obj); | 1131 | eb_add_object(eb, obj); |
| 1114 | } | 1132 | } |
| 1115 | 1133 | ||
| 1134 | /* take note of the batch buffer before we might reorder the lists */ | ||
| 1135 | batch_obj = list_entry(objects.prev, | ||
| 1136 | struct drm_i915_gem_object, | ||
| 1137 | exec_list); | ||
| 1138 | |||
| 1116 | /* Move the objects en-masse into the GTT, evicting if necessary. */ | 1139 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
| 1117 | ret = i915_gem_execbuffer_reserve(ring, file, &objects, exec); | 1140 | ret = i915_gem_execbuffer_reserve(ring, file, &objects); |
| 1118 | if (ret) | 1141 | if (ret) |
| 1119 | goto err; | 1142 | goto err; |
| 1120 | 1143 | ||
| 1121 | /* The objects are in their final locations, apply the relocations. */ | 1144 | /* The objects are in their final locations, apply the relocations. */ |
| 1122 | ret = i915_gem_execbuffer_relocate(dev, eb, &objects, exec); | 1145 | ret = i915_gem_execbuffer_relocate(dev, eb, &objects); |
| 1123 | if (ret) { | 1146 | if (ret) { |
| 1124 | if (ret == -EFAULT) { | 1147 | if (ret == -EFAULT) { |
| 1125 | ret = i915_gem_execbuffer_relocate_slow(dev, file, ring, | 1148 | ret = i915_gem_execbuffer_relocate_slow(dev, file, ring, |
| @@ -1133,9 +1156,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 1133 | } | 1156 | } |
| 1134 | 1157 | ||
| 1135 | /* Set the pending read domains for the batch buffer to COMMAND */ | 1158 | /* Set the pending read domains for the batch buffer to COMMAND */ |
| 1136 | batch_obj = list_entry(objects.prev, | ||
| 1137 | struct drm_i915_gem_object, | ||
| 1138 | exec_list); | ||
| 1139 | if (batch_obj->base.pending_write_domain) { | 1159 | if (batch_obj->base.pending_write_domain) { |
| 1140 | DRM_ERROR("Attempting to use self-modifying batch buffer\n"); | 1160 | DRM_ERROR("Attempting to use self-modifying batch buffer\n"); |
| 1141 | ret = -EINVAL; | 1161 | ret = -EINVAL; |
