diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 46 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_execbuffer.c | 76 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 4 |
5 files changed, 103 insertions, 38 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ec5f6fb42ab3..388c028e223c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -2189,10 +2189,12 @@ void i915_gem_vma_destroy(struct i915_vma *vma); | |||
| 2189 | #define PIN_MAPPABLE 0x1 | 2189 | #define PIN_MAPPABLE 0x1 |
| 2190 | #define PIN_NONBLOCK 0x2 | 2190 | #define PIN_NONBLOCK 0x2 |
| 2191 | #define PIN_GLOBAL 0x4 | 2191 | #define PIN_GLOBAL 0x4 |
| 2192 | #define PIN_OFFSET_BIAS 0x8 | ||
| 2193 | #define PIN_OFFSET_MASK (~4095) | ||
| 2192 | int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, | 2194 | int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, |
| 2193 | struct i915_address_space *vm, | 2195 | struct i915_address_space *vm, |
| 2194 | uint32_t alignment, | 2196 | uint32_t alignment, |
| 2195 | unsigned flags); | 2197 | uint64_t flags); |
| 2196 | int __must_check i915_vma_unbind(struct i915_vma *vma); | 2198 | int __must_check i915_vma_unbind(struct i915_vma *vma); |
| 2197 | int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); | 2199 | int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); |
| 2198 | void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); | 2200 | void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); |
| @@ -2445,6 +2447,8 @@ int __must_check i915_gem_evict_something(struct drm_device *dev, | |||
| 2445 | int min_size, | 2447 | int min_size, |
| 2446 | unsigned alignment, | 2448 | unsigned alignment, |
| 2447 | unsigned cache_level, | 2449 | unsigned cache_level, |
| 2450 | unsigned long start, | ||
| 2451 | unsigned long end, | ||
| 2448 | unsigned flags); | 2452 | unsigned flags); |
| 2449 | int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); | 2453 | int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); |
| 2450 | int i915_gem_evict_everything(struct drm_device *dev); | 2454 | int i915_gem_evict_everything(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b391f30f9985..3326770c9ed2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -3326,12 +3326,14 @@ static struct i915_vma * | |||
| 3326 | i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | 3326 | i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, |
| 3327 | struct i915_address_space *vm, | 3327 | struct i915_address_space *vm, |
| 3328 | unsigned alignment, | 3328 | unsigned alignment, |
| 3329 | unsigned flags) | 3329 | uint64_t flags) |
| 3330 | { | 3330 | { |
| 3331 | struct drm_device *dev = obj->base.dev; | 3331 | struct drm_device *dev = obj->base.dev; |
| 3332 | struct drm_i915_private *dev_priv = dev->dev_private; | 3332 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 3333 | u32 size, fence_size, fence_alignment, unfenced_alignment; | 3333 | u32 size, fence_size, fence_alignment, unfenced_alignment; |
| 3334 | size_t gtt_max = | 3334 | unsigned long start = |
| 3335 | flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; | ||
| 3336 | unsigned long end = | ||
| 3335 | flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total; | 3337 | flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total; |
| 3336 | struct i915_vma *vma; | 3338 | struct i915_vma *vma; |
| 3337 | int ret; | 3339 | int ret; |
| @@ -3360,11 +3362,11 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | |||
| 3360 | /* If the object is bigger than the entire aperture, reject it early | 3362 | /* If the object is bigger than the entire aperture, reject it early |
| 3361 | * before evicting everything in a vain attempt to find space. | 3363 | * before evicting everything in a vain attempt to find space. |
| 3362 | */ | 3364 | */ |
| 3363 | if (obj->base.size > gtt_max) { | 3365 | if (obj->base.size > end) { |
| 3364 | DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n", | 3366 | DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%lu\n", |
| 3365 | obj->base.size, | 3367 | obj->base.size, |
| 3366 | flags & PIN_MAPPABLE ? "mappable" : "total", | 3368 | flags & PIN_MAPPABLE ? "mappable" : "total", |
| 3367 | gtt_max); | 3369 | end); |
| 3368 | return ERR_PTR(-E2BIG); | 3370 | return ERR_PTR(-E2BIG); |
| 3369 | } | 3371 | } |
| 3370 | 3372 | ||
| @@ -3381,12 +3383,15 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, | |||
| 3381 | search_free: | 3383 | search_free: |
| 3382 | ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, | 3384 | ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, |
| 3383 | size, alignment, | 3385 | size, alignment, |
| 3384 | obj->cache_level, 0, gtt_max, | 3386 | obj->cache_level, |
| 3387 | start, end, | ||
| 3385 | DRM_MM_SEARCH_DEFAULT, | 3388 | DRM_MM_SEARCH_DEFAULT, |
| 3386 | DRM_MM_CREATE_DEFAULT); | 3389 | DRM_MM_CREATE_DEFAULT); |
| 3387 | if (ret) { | 3390 | if (ret) { |
| 3388 | ret = i915_gem_evict_something(dev, vm, size, alignment, | 3391 | ret = i915_gem_evict_something(dev, vm, size, alignment, |
| 3389 | obj->cache_level, flags); | 3392 | obj->cache_level, |
| 3393 | start, end, | ||
| 3394 | flags); | ||
| 3390 | if (ret == 0) | 3395 | if (ret == 0) |
| 3391 | goto search_free; | 3396 | goto search_free; |
| 3392 | 3397 | ||
| @@ -3946,11 +3951,30 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
| 3946 | return ret; | 3951 | return ret; |
| 3947 | } | 3952 | } |
| 3948 | 3953 | ||
| 3954 | static bool | ||
| 3955 | i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags) | ||
| 3956 | { | ||
| 3957 | struct drm_i915_gem_object *obj = vma->obj; | ||
| 3958 | |||
| 3959 | if (alignment && | ||
| 3960 | vma->node.start & (alignment - 1)) | ||
| 3961 | return true; | ||
| 3962 | |||
| 3963 | if (flags & PIN_MAPPABLE && !obj->map_and_fenceable) | ||
| 3964 | return true; | ||
| 3965 | |||
| 3966 | if (flags & PIN_OFFSET_BIAS && | ||
| 3967 | vma->node.start < (flags & PIN_OFFSET_MASK)) | ||
| 3968 | return true; | ||
| 3969 | |||
| 3970 | return false; | ||
| 3971 | } | ||
| 3972 | |||
| 3949 | int | 3973 | int |
| 3950 | i915_gem_object_pin(struct drm_i915_gem_object *obj, | 3974 | i915_gem_object_pin(struct drm_i915_gem_object *obj, |
| 3951 | struct i915_address_space *vm, | 3975 | struct i915_address_space *vm, |
| 3952 | uint32_t alignment, | 3976 | uint32_t alignment, |
| 3953 | unsigned flags) | 3977 | uint64_t flags) |
| 3954 | { | 3978 | { |
| 3955 | struct i915_vma *vma; | 3979 | struct i915_vma *vma; |
| 3956 | int ret; | 3980 | int ret; |
| @@ -3963,15 +3987,13 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, | |||
| 3963 | if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) | 3987 | if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) |
| 3964 | return -EBUSY; | 3988 | return -EBUSY; |
| 3965 | 3989 | ||
| 3966 | if ((alignment && | 3990 | if (i915_vma_misplaced(vma, alignment, flags)) { |
| 3967 | vma->node.start & (alignment - 1)) || | ||
| 3968 | (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) { | ||
| 3969 | WARN(vma->pin_count, | 3991 | WARN(vma->pin_count, |
| 3970 | "bo is already pinned with incorrect alignment:" | 3992 | "bo is already pinned with incorrect alignment:" |
| 3971 | " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," | 3993 | " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d," |
| 3972 | " obj->map_and_fenceable=%d\n", | 3994 | " obj->map_and_fenceable=%d\n", |
| 3973 | i915_gem_obj_offset(obj, vm), alignment, | 3995 | i915_gem_obj_offset(obj, vm), alignment, |
| 3974 | flags & PIN_MAPPABLE, | 3996 | !!(flags & PIN_MAPPABLE), |
| 3975 | obj->map_and_fenceable); | 3997 | obj->map_and_fenceable); |
| 3976 | ret = i915_vma_unbind(vma); | 3998 | ret = i915_vma_unbind(vma); |
| 3977 | if (ret) | 3999 | if (ret) |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 75fca63dc8c1..bbf4b12d842e 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -68,9 +68,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind) | |||
| 68 | int | 68 | int |
| 69 | i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, | 69 | i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, |
| 70 | int min_size, unsigned alignment, unsigned cache_level, | 70 | int min_size, unsigned alignment, unsigned cache_level, |
| 71 | unsigned long start, unsigned long end, | ||
| 71 | unsigned flags) | 72 | unsigned flags) |
| 72 | { | 73 | { |
| 73 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 74 | struct list_head eviction_list, unwind_list; | 74 | struct list_head eviction_list, unwind_list; |
| 75 | struct i915_vma *vma; | 75 | struct i915_vma *vma; |
| 76 | int ret = 0; | 76 | int ret = 0; |
| @@ -102,11 +102,10 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, | |||
| 102 | */ | 102 | */ |
| 103 | 103 | ||
| 104 | INIT_LIST_HEAD(&unwind_list); | 104 | INIT_LIST_HEAD(&unwind_list); |
| 105 | if (flags & PIN_MAPPABLE) { | 105 | if (start != 0 || end != vm->total) { |
| 106 | BUG_ON(!i915_is_ggtt(vm)); | ||
