| @@ -36,24 +36,40 @@ · 35 unmodified lines |
| 36 | 36 | struct eb_objects { |
| 37 | 37 | struct list_head objects; |
| 38 | 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 | 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; |
| 46 | | − int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; |
| 47 | | − BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head))); |
| 48 | | − while (count > size) |
| 49 | | − count >>= 1; |
| 50 | | − eb = kzalloc(count*sizeof(struct hlist_head) + |
| 51 | | − sizeof(struct eb_objects), |
| 52 | | − GFP_KERNEL); |
| 53 | | − if (eb == NULL) |
| 54 | | − return eb; |
| 55 | | − |
| 56 | | − eb->and = count - 1; |
| 48 | + struct eb_objects *eb = NULL; |
| 49 | + |
| 50 | + if (args->flags & I915_EXEC_HANDLE_LUT) { |
| 51 | + int size = args->buffer_count; |
| 52 | + size *= sizeof(struct drm_i915_gem_object *); |
| 53 | + size += sizeof(struct eb_objects); |
| 54 | + eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); |
| 55 | + } |
| 56 | + |
| 57 | + if (eb == NULL) { |
| 58 | + int size = args->buffer_count; |
| 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 | 73 | INIT_LIST_HEAD(&eb->objects); |
| 58 | 74 | return eb; |
| 59 | 75 | } |
| @@ -61,26 +77,20 @@ eb_create(int size) · 1 unmodified line |
| 61 | 77 | static void |
| 62 | 78 | eb_reset(struct eb_objects *eb) |
| 63 | 79 | { |
| 64 | | − memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); |
| 65 | | −} |
| 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]); |
| 80 | + if (eb->and >= 0) |
| 81 | + memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); |
| 72 | 82 | } |
| 73 | 83 | |
| 74 | 84 | static int |
| 75 | 85 | eb_lookup_objects(struct eb_objects *eb, |
| 76 | 86 | struct drm_i915_gem_exec_object2 *exec, |
| 77 | | − int count, |
| 87 | + const struct drm_i915_gem_execbuffer2 *args, |
| 78 | 88 | struct drm_file *file) |
| 79 | 89 | { |
| 80 | 90 | int i; |
| 81 | 91 | |
| 82 | 92 | spin_lock(&file->table_lock); |
| 83 | | − for (i = 0; i < count; i++) { |
| 93 | + for (i = 0; i < args->buffer_count; i++) { |
| 84 | 94 | struct drm_i915_gem_object *obj; |
| 85 | 95 | |
| 86 | 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 | 111 | drm_gem_object_reference(&obj->base); |
| 102 | 112 | list_add_tail(&obj->exec_list, &eb->objects); |
| 103 | 113 | |
| 104 | | − obj->exec_handle = exec[i].handle; |
| 105 | 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 | 124 | spin_unlock(&file->table_lock); |
| 109 | 125 | |
| @@ -113,18 +129,24 @@ eb_lookup_objects(struct eb_objects *eb, · 3 unmodified lines |
| 113 | 129 | static struct drm_i915_gem_object * |
| 114 | 130 | eb_get_object(struct eb_objects *eb, unsigned long handle) |
| 115 | 131 | { |
| 116 | | − struct hlist_head *head; |
| 117 | | − struct hlist_node *node; |
| 118 | | − struct drm_i915_gem_object *obj; |
| 132 | + if (eb->and < 0) { |
| 133 | + if (handle >= -eb->and) |
| 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]; |
| 121 | | − hlist_for_each(node, head) { |
| 122 | | − obj = hlist_entry(node, struct drm_i915_gem_object, exec_node); |
| 123 | | − if (obj->exec_handle == handle) |
| 124 | | − return obj; |
| 125 | | − } |
| 140 | + head = &eb->buckets[handle & eb->and]; |
| 141 | + hlist_for_each(node, head) { |
| 142 | + struct drm_i915_gem_object *obj; |
| 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 | 152 | static void |
| @@ -615,7 +637,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, · 484 unmodified lines |
| 615 | 637 | |
| 616 | 638 | /* reacquire the objects */ |
| 617 | 639 | eb_reset(eb); |
| 618 | | − ret = eb_lookup_objects(eb, exec, count, file); |
| 640 | + ret = eb_lookup_objects(eb, exec, args, file); |
| 619 | 641 | if (ret) |
| 620 | 642 | goto err; |
| 621 | 643 | |
| @@ -919,7 +941,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, · 297 unmodified lines |
| 919 | 941 | goto pre_mutex_err; |
| 920 | 942 | } |
| 921 | 943 | |
| 922 | | − eb = eb_create(args->buffer_count); |
| 944 | + eb = eb_create(args); |
| 923 | 945 | if (eb == NULL) { |
| 924 | 946 | mutex_unlock(&dev->struct_mutex); |
| 925 | 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 | 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 | 953 | if (ret) |
| 932 | 954 | goto err; |
| 933 | 955 | |