| @@ -36,24 +36,40 @@ · 35 unmodified lines |
| 36 | struct eb_objects { | 36 | struct eb_objects { |
| 37 | struct list_head objects; | 37 | struct list_head objects; |
| 38 | int and; | 38 | int and; |
| 39 | struct hlist_head buckets[0]; | 39 | union { |
| | 40 | struct drm_i915_gem_object *lut[0]; |
| | 41 | struct hlist_head buckets[0]; |
| | 42 | }; |
| 40 | }; | 43 | }; |
| 41 | | 44 | |
| 42 | static struct eb_objects * | 45 | static struct eb_objects * |
| 43 | eb_create(int size) | 46 | eb_create(struct drm_i915_gem_execbuffer2 *args) |
| 44 | { | 47 | { |
| 45 | struct eb_objects *eb; | 48 | struct eb_objects *eb = NULL; |
| 46 | int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; | 49 | |
| 47 | BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head))); | 50 | if (args->flags & I915_EXEC_HANDLE_LUT) { |
| 48 | while (count > size) | 51 | int size = args->buffer_count; |
| 49 | count >>= 1; | 52 | size *= sizeof(struct drm_i915_gem_object *); |
| 50 | eb = kzalloc(count*sizeof(struct hlist_head) + | 53 | size += sizeof(struct eb_objects); |
| 51 | sizeof(struct eb_objects), | 54 | eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); |
| 52 | GFP_KERNEL); | 55 | } |
| 53 | if (eb == NULL) | 56 | |
| 54 | return eb; | 57 | if (eb == NULL) { |
| 55 | | 58 | int size = args->buffer_count; |
| 56 | eb->and = count - 1; | 59 | int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; |
| | 60 | BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head))); |
| | 61 | while (count > 2*size) |
| | 62 | count >>= 1; |
| | 63 | eb = kzalloc(count*sizeof(struct hlist_head) + |
| | 64 | sizeof(struct eb_objects), |
| | 65 | GFP_TEMPORARY); |
| | 66 | if (eb == NULL) |
| | 67 | return eb; |
| | 68 | |
| | 69 | eb->and = count - 1; |
| | 70 | } else |
| | 71 | eb->and = -args->buffer_count; |
| | 72 | |
| 57 | INIT_LIST_HEAD(&eb->objects); | 73 | INIT_LIST_HEAD(&eb->objects); |
| 58 | return eb; | 74 | return eb; |
| 59 | } | 75 | } |
| @@ -61,26 +77,20 @@ eb_create(int size) · 1 unmodified line |
| 61 | static void | 77 | static void |
| 62 | eb_reset(struct eb_objects *eb) | 78 | eb_reset(struct eb_objects *eb) |
| 63 | { | 79 | { |
| 64 | memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); | 80 | if (eb->and >= 0) |
| 65 | } | 81 | memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); |
| 66 | | | |
| 67 | static void | | |
| 68 | eb_add_object(struct eb_objects *eb, struct drm_i915_gem_object *obj) | | |
| 69 | { | | |
| 70 | hlist_add_head(&obj->exec_node, | | |
| 71 | &eb->buckets[obj->exec_handle & eb->and]); | | |
| 72 | } | 82 | } |
| 73 | | 83 | |
| 74 | static int | 84 | static int |
| 75 | eb_lookup_objects(struct eb_objects *eb, | 85 | eb_lookup_objects(struct eb_objects *eb, |
| 76 | struct drm_i915_gem_exec_object2 *exec, | 86 | struct drm_i915_gem_exec_object2 *exec, |
| 77 | int count, | 87 | const struct drm_i915_gem_execbuffer2 *args, |
| 78 | struct drm_file *file) | 88 | struct drm_file *file) |
| 79 | { | 89 | { |
| 80 | int i; | 90 | int i; |
| 81 | | 91 | |
| 82 | spin_lock(&file->table_lock); | 92 | spin_lock(&file->table_lock); |
| 83 | for (i = 0; i < count; i++) { | 93 | for (i = 0; i < args->buffer_count; i++) { |
| 84 | struct drm_i915_gem_object *obj; | 94 | struct drm_i915_gem_object *obj; |
| 85 | | 95 | |
| 86 | obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle)); | 96 | obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle)); |
| @@ -101,9 +111,15 @@ eb_lookup_objects(struct eb_objects *eb, · 14 unmodified lines |
| 101 | drm_gem_object_reference(&obj->base); | 111 | drm_gem_object_reference(&obj->base); |
| 102 | list_add_tail(&obj->exec_list, &eb->objects); | 112 | list_add_tail(&obj->exec_list, &eb->objects); |
| 103 | | 113 | |
| 104 | obj->exec_handle = exec[i].handle; | | |
| 105 | obj->exec_entry = &exec[i]; | 114 | obj->exec_entry = &exec[i]; |
| 106 | eb_add_object(eb, obj); | 115 | if (eb->and < 0) { |
| | 116 | eb->lut[i] = obj; |
| | 117 | } else { |
| | 118 | uint32_t handle = args->flags & I915_EXEC_HANDLE_LUT ? i : exec[i].handle; |
| | 119 | obj->exec_handle = handle; |
| | 120 | hlist_add_head(&obj->exec_node, |
| | 121 | &eb->buckets[handle & eb->and]); |
| | 122 | } |
| 107 | } | 123 | } |
| 108 | spin_unlock(&file->table_lock); | 124 | spin_unlock(&file->table_lock); |
| 109 | | 125 | |
| @@ -113,18 +129,24 @@ eb_lookup_objects(struct eb_objects *eb, · 3 unmodified lines |
| 113 | static struct drm_i915_gem_object * | 129 | static struct drm_i915_gem_object * |
| 114 | eb_get_object(struct eb_objects *eb, unsigned long handle) | 130 | eb_get_object(struct eb_objects *eb, unsigned long handle) |
| 115 | { | 131 | { |
| 116 | struct hlist_head *head; | 132 | if (eb->and < 0) { |
| 117 | struct hlist_node *node; | 133 | if (handle >= -eb->and) |
| 118 | struct drm_i915_gem_object *obj; | 134 | return NULL; |
| | 135 | return eb->lut[handle]; |
| | 136 | } else { |
| | 137 | struct hlist_head *head; |
| | 138 | struct hlist_node *node; |
| 119 | | 139 | |
| 120 | head = &eb->buckets[handle & eb->and]; | 140 | head = &eb->buckets[handle & eb->and]; |
| 121 | hlist_for_each(node, head) { | 141 | hlist_for_each(node, head) { |
| 122 | obj = hlist_entry(node, struct drm_i915_gem_object, exec_node); | 142 | struct drm_i915_gem_object *obj; |
| 123 | if (obj->exec_handle == handle) | | |
| 124 | return obj; | | |
| 125 | } | | |
| 126 | | 143 | |
| 127 | return NULL; | 144 | obj = hlist_entry(node, struct drm_i915_gem_object, exec_node); |
| | 145 | if (obj->exec_handle == handle) |
| | 146 | return obj; |
| | 147 | } |
| | 148 | return NULL; |
| | 149 | } |
| 128 | } | 150 | } |
| 129 | | 151 | |
| 130 | static void | 152 | static void |
| @@ -615,7 +637,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, · 484 unmodified lines |
| 615 | | 637 | |
| 616 | /* reacquire the objects */ | 638 | /* reacquire the objects */ |
| 617 | eb_reset(eb); | 639 | eb_reset(eb); |
| 618 | ret = eb_lookup_objects(eb, exec, count, file); | 640 | ret = eb_lookup_objects(eb, exec, args, file); |
| 619 | if (ret) | 641 | if (ret) |
| 620 | goto err; | 642 | goto err; |
| 621 | | 643 | |
| @@ -919,7 +941,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, · 297 unmodified lines |
| 919 | goto pre_mutex_err; | 941 | goto pre_mutex_err; |
| 920 | } | 942 | } |
| 921 | | 943 | |
| 922 | eb = eb_create(args->buffer_count); | 944 | eb = eb_create(args); |
| 923 | if (eb == NULL) { | 945 | if (eb == NULL) { |
| 924 | mutex_unlock(&dev->struct_mutex); | 946 | mutex_unlock(&dev->struct_mutex); |
| 925 | ret = -ENOMEM; | 947 | ret = -ENOMEM; |
| @@ -927,7 +949,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, · 1 unmodified line |
| 927 | } | 949 | } |
| 928 | | 950 | |
| 929 | /* Look up object handles */ | 951 | /* Look up object handles */ |
| 930 | ret = eb_lookup_objects(eb, exec, args->buffer_count, file); | 952 | ret = eb_lookup_objects(eb, exec, args, file); |
| 931 | if (ret) | 953 | if (ret) |
| 932 | goto err; | 954 | goto err; |
| 933 | | 955 | |