aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c46
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c9
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c76
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c4
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)
2192int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, 2194int __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);
2196int __must_check i915_vma_unbind(struct i915_vma *vma); 2198int __must_check i915_vma_unbind(struct i915_vma *vma);
2197int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); 2199int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
2198void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); 2200void 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);
2449int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle); 2453int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
2450int i915_gem_evict_everything(struct drm_device *dev); 2454int 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 *
3326i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, 3326i915_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,
3381search_free: 3383search_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
3954static bool
3955i915_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
3949int 3973int
3950i915_gem_object_pin(struct drm_i915_gem_object *obj, 3974i915_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)
68int 68int
69i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, 69i915_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));