diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_vma.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_vma.c | 90 |
1 files changed, 89 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index fe93ed1e012f..87273b0137ec 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -146,6 +146,59 @@ __i915_vma_create(struct drm_i915_gem_object *obj, return vma; } +/** + * i915_vma_lookup - finds a matching VMA + * @obj: parent &struct drm_i915_gem_object to be mapped + * @vm: address space in which the mapping is located + * @view: additional mapping requirements + * + * i915_vma_lookup() looks up an existing VMA of the @obj in the @vm with + * the same @view characteristics. + * + * Must be called with struct_mutex held. + * + * Returns the vma if found, or NULL. + */ +struct i915_vma * +i915_vma_lookup(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view) +{ + struct rb_node *rb; + + lockdep_assert_held(&obj->base.dev->struct_mutex); + + rb = obj->vma_tree.rb_node; + while (rb) { + struct i915_vma *vma = rb_entry(rb, struct i915_vma, obj_node); + long cmp; + + cmp = i915_vma_compare(vma, vm, view); + if (cmp == 0) + return vma; + + if (cmp < 0) + rb = rb->rb_right; + else + rb = rb->rb_left; + } + + return NULL; +} + +/** + * i915_vma_create - creates a VMA + * @obj: parent &struct drm_i915_gem_object to be mapped + * @vm: address space in which the mapping is located + * @view: additional mapping requirements + * + * i915_vma_create() allocates a new VMA of the @obj in the @vm with + * @view characteristics. + * + * Must be called with struct_mutex held. + * + * Returns the vma if found, or an error pointer. + */ struct i915_vma * i915_vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, @@ -153,12 +206,47 @@ i915_vma_create(struct drm_i915_gem_object *obj, { lockdep_assert_held(&obj->base.dev->struct_mutex); GEM_BUG_ON(view && !i915_is_ggtt(vm)); - GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view)); + GEM_BUG_ON(i915_vma_lookup(obj, vm, view)); return __i915_vma_create(obj, vm, view); } /** + * i915_vma_instance - return the singleton instance of the VMA + * @obj: parent &struct drm_i915_gem_object to be mapped + * @vm: address space in which the mapping is located + * @view: additional mapping requirements + * + * i915_vma_instance() looks up an existing VMA of the @obj in the @vm with + * the same @view characteristics. If a match is not found, one is created. + * Once created, the VMA is kept until either the object is freed, or the + * address space is closed. + * + * Must be called with struct_mutex held. + * + * Returns the vma, or an error pointer. + */ +struct i915_vma * +i915_vma_instance(struct drm_i915_gem_object *obj, + struct i915_address_space *vm, + const struct i915_ggtt_view *view) +{ + struct i915_vma *vma; + + lockdep_assert_held(&obj->base.dev->struct_mutex); + GEM_BUG_ON(view && !i915_is_ggtt(vm)); + GEM_BUG_ON(vm->closed); + + vma = i915_vma_lookup(obj, vm, view); + if (!vma) + vma = i915_vma_create(obj, vm, view); + + GEM_BUG_ON(!IS_ERR(vma) && i915_vma_is_closed(vma)); + GEM_BUG_ON(!IS_ERR(vma) && i915_vma_lookup(obj, vm, view) != vma); + return vma; +} + +/** * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space. * @vma: VMA to map * @cache_level: mapping cache level |