[Intel-gfx] [PATCH 1/2] drm/i915: Infrastructure for supporting different GGTT views per object
Michel Thierry
michel.thierry at intel.com
Tue Dec 9 07:23:35 PST 2014
On 12/5/2014 12:11 PM, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
>
> Things like reliable GGTT mappings and mirrored 2d-on-3d display will need
> to map objects into the same address space multiple times.
>
> Added a GGTT view concept and linked it with the VMA to distinguish between
> multiple instances per address space.
>
> New objects and GEM functions which do not take this new view as a parameter
> assume the default of zero (I915_GGTT_VIEW_NORMAL) which preserves the
> previous behaviour.
>
> This now means that objects can have multiple VMA entries so the code which
> assumed there will only be one also had to be modified.
>
> Alternative GGTT views are supposed to borrow DMA addresses from obj->pages
> which is DMA mapped on first VMA instantiation and unmapped on the last one
> going away.
>
> v2:
> * Removed per view special casing in i915_gem_ggtt_prepare /
> finish_object in favour of creating and destroying DMA mappings
> on first VMA instantiation and last VMA destruction. (Daniel Vetter)
> * Simplified i915_vma_unbind which does not need to count the GGTT views.
> (Daniel Vetter)
> * Also moved obj->map_and_fenceable reset under the same check.
> * Checkpatch cleanups.
>
> v3:
> * Only retire objects once the last VMA is unbound.
>
> v4:
> * Keep scatter-gather table for alternative views persistent for the
> lifetime of the VMA.
> * Propagate binding errors to callers and handle appropriately.
>
> For: VIZ-4544
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> Cc: Daniel Vetter <daniel.vetter at ffwll.ch>
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 5 +-
> drivers/gpu/drm/i915/i915_drv.h | 46 +++++++++++--
> drivers/gpu/drm/i915/i915_gem.c | 101 ++++++++++++++++++-----------
> drivers/gpu/drm/i915/i915_gem_context.c | 11 +++-
> drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 ++-
> drivers/gpu/drm/i915/i915_gem_gtt.c | 70 +++++++++++++++++---
> drivers/gpu/drm/i915/i915_gem_gtt.h | 22 +++++++
> drivers/gpu/drm/i915/i915_gpu_error.c | 8 +--
> 8 files changed, 206 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 6c16939..bd08289 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -152,8 +152,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
> seq_puts(m, " (pp");
> else
> seq_puts(m, " (g");
> - seq_printf(m, "gtt offset: %08lx, size: %08lx)",
> - vma->node.start, vma->node.size);
> + seq_printf(m, "gtt offset: %08lx, size: %08lx, type: %u)",
> + vma->node.start, vma->node.size,
> + vma->ggtt_view.type);
> }
> if (obj->stolen)
> seq_printf(m, " (stolen: %08lx)", obj->stolen->start);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 049482f..b2f6f7d 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2514,10 +2514,23 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
> #define PIN_GLOBAL 0x4
> #define PIN_OFFSET_BIAS 0x8
> #define PIN_OFFSET_MASK (~4095)
> +int __must_check i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + uint32_t alignment,
> + uint64_t flags,
> + const struct i915_ggtt_view *view);
> +static inline
> int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
> struct i915_address_space *vm,
> uint32_t alignment,
> - uint64_t flags);
> + uint64_t flags)
> +{
> + return i915_gem_object_pin_view(obj, vm, alignment, flags,
> + &i915_ggtt_view_normal);
> +}
> +
> +int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
> + u32 flags);
> int __must_check i915_vma_unbind(struct i915_vma *vma);
> int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
> void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
> @@ -2679,18 +2692,43 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
>
> void i915_gem_restore_fences(struct drm_device *dev);
>
> +unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
> + struct i915_address_space *vm,
> + enum i915_ggtt_view_type view);
> +static inline
> unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
> - struct i915_address_space *vm);
> + struct i915_address_space *vm)
> +{
> + return i915_gem_obj_offset_view(o, vm, I915_GGTT_VIEW_NORMAL);
> +}
> bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o);
> bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
> struct i915_address_space *vm);
> unsigned long i915_gem_obj_size(struct drm_i915_gem_object *o,
> struct i915_address_space *vm);
> +struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + const struct i915_ggtt_view *view);
> +static inline
> struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm);
> + struct i915_address_space *vm)
> +{
> + return i915_gem_obj_to_vma_view(obj, vm, &i915_ggtt_view_normal);
> +}
> +
> +struct i915_vma *
> +i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + const struct i915_ggtt_view *view);
> +
> +static inline
> struct i915_vma *
> i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm);
> + struct i915_address_space *vm)
> +{
> + return i915_gem_obj_lookup_or_create_vma_view(obj, vm,
> + &i915_ggtt_view_normal);
> +}
Hi,
We also need a _vma_view version of i915_gem_obj_bound;
i915_gem_object_ggtt_unpin checks if the obj is ggtt_bound and it could
be that the normal view is gone but a different view is still active (it
is also used in gpu_error and debug_fs, but I don't think it's a problem
there).
>
> struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
> static inline bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj) {
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index c1c1141..9244f0b 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -2087,8 +2087,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
> /* For the unbound phase, this should be a no-op! */
> list_for_each_entry_safe(vma, v,
> &obj->vma_list, vma_link)
> - if (i915_vma_unbind(vma))
> - break;
> + i915_vma_unbind(vma);
>
> if (i915_gem_object_put_pages(obj) == 0)
> count += obj->base.size >> PAGE_SHIFT;
> @@ -2297,17 +2296,14 @@ void i915_vma_move_to_active(struct i915_vma *vma,
> static void
> i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
> {
> - struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
> - struct i915_address_space *vm;
> struct i915_vma *vma;
>
> BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
> BUG_ON(!obj->active);
>
> - list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
> - vma = i915_gem_obj_to_vma(obj, vm);
> - if (vma && !list_empty(&vma->mm_list))
> - list_move_tail(&vma->mm_list, &vm->inactive_list);
> + list_for_each_entry(vma, &obj->vma_list, vma_link) {
> + if (!list_empty(&vma->mm_list))
> + list_move_tail(&vma->mm_list, &vma->vm->inactive_list);
> }
>
> intel_fb_obj_flush(obj, true);
> @@ -3062,10 +3058,8 @@ int i915_vma_unbind(struct i915_vma *vma)
> * cause memory corruption through use-after-free.
> */
>
> - /* Throw away the active reference before moving to the unbound list */
> - i915_gem_object_retire(obj);
> -
> - if (i915_is_ggtt(vma->vm)) {
> + if (i915_is_ggtt(vma->vm) &&
> + vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
> i915_gem_object_finish_gtt(obj);
>
> /* release the fence reg _after_ flushing */
> @@ -3079,8 +3073,15 @@ int i915_vma_unbind(struct i915_vma *vma)
> vma->unbind_vma(vma);
>
> list_del_init(&vma->mm_list);
> - if (i915_is_ggtt(vma->vm))
> - obj->map_and_fenceable = false;
> + if (i915_is_ggtt(vma->vm)) {
> + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
> + obj->map_and_fenceable = false;
> + } else if (vma->ggtt_view.pages) {
> + sg_free_table(vma->ggtt_view.pages);
> + kfree(vma->ggtt_view.pages);
> + vma->ggtt_view.pages = NULL;
> + }
> + }
>
> drm_mm_remove_node(&vma->node);
> i915_gem_vma_destroy(vma);
> @@ -3088,6 +3089,10 @@ int i915_vma_unbind(struct i915_vma *vma)
> /* Since the unbound list is global, only move to that list if
> * no more VMAs exist. */
> if (list_empty(&obj->vma_list)) {
> + /* Throw away the active reference before
> + * moving to the unbound list. */
> + i915_gem_object_retire(obj);
> +
> i915_gem_gtt_finish_object(obj);
> list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
> }
> @@ -3498,7 +3503,8 @@ static struct i915_vma *
> i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
> struct i915_address_space *vm,
> unsigned alignment,
> - uint64_t flags)
> + uint64_t flags,
> + const struct i915_ggtt_view *view)
> {
> struct drm_device *dev = obj->base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3548,7 +3554,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
>
> i915_gem_object_pin_pages(obj);
>
> - vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
> + vma = i915_gem_obj_lookup_or_create_vma_view(obj, vm, view);
> if (IS_ERR(vma))
> goto err_unpin;
>
> @@ -3578,15 +3584,19 @@ search_free:
> if (ret)
> goto err_remove_node;
>
> + trace_i915_vma_bind(vma, flags);
> + ret = i915_vma_bind(vma, obj->cache_level,
> + flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
> + if (ret)
> + goto err_finish_gtt;
> +
> list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
> list_add_tail(&vma->mm_list, &vm->inactive_list);
>
> - trace_i915_vma_bind(vma, flags);
> - vma->bind_vma(vma, obj->cache_level,
> - flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
> -
> return vma;
>
> +err_finish_gtt:
> + i915_gem_gtt_finish_object(obj);
> err_remove_node:
> drm_mm_remove_node(&vma->node);
> err_free_vma:
> @@ -3789,9 +3799,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
> }
>
> list_for_each_entry(vma, &obj->vma_list, vma_link)
> - if (drm_mm_node_allocated(&vma->node))
> - vma->bind_vma(vma, cache_level,
> - vma->bound & GLOBAL_BIND);
> + if (drm_mm_node_allocated(&vma->node)) {
> + ret = i915_vma_bind(vma, cache_level,
> + vma->bound & GLOBAL_BIND);
> + if (ret);
> + return ret;
> + }
> }
>
> list_for_each_entry(vma, &obj->vma_list, vma_link)
> @@ -4144,10 +4157,11 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
> }
>
> int
> -i915_gem_object_pin(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm,
> - uint32_t alignment,
> - uint64_t flags)
> +i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + uint32_t alignment,
> + uint64_t flags,
> + const struct i915_ggtt_view *view)
> {
> struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
> struct i915_vma *vma;
> @@ -4163,7 +4177,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
> if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE))
> return -EINVAL;
>
> - vma = i915_gem_obj_to_vma(obj, vm);
> + vma = i915_gem_obj_to_vma_view(obj, vm, view);
> if (vma) {
> if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
> return -EBUSY;
> @@ -4173,7 +4187,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
> "bo is already pinned with incorrect alignment:"
> " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
> " obj->map_and_fenceable=%d\n",
> - i915_gem_obj_offset(obj, vm), alignment,
> + i915_gem_obj_offset_view(obj, vm, view->type),
> + alignment,
> !!(flags & PIN_MAPPABLE),
> obj->map_and_fenceable);
> ret = i915_vma_unbind(vma);
> @@ -4186,13 +4201,17 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
>
> bound = vma ? vma->bound : 0;
> if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
> - vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags);
> + vma = i915_gem_object_bind_to_vm(obj, vm, alignment,
> + flags, view);
> if (IS_ERR(vma))
> return PTR_ERR(vma);
> }
>
> - if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND))
> - vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
> + if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) {
> + ret = i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND);
> + if (ret)
> + return ret;
> + }
>
> if ((bound ^ vma->bound) & GLOBAL_BIND) {
> bool mappable, fenceable;
> @@ -4528,12 +4547,13 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
> intel_runtime_pm_put(dev_priv);
> }
>
> -struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm)
> +struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + const struct i915_ggtt_view *view)
> {
> struct i915_vma *vma;
> list_for_each_entry(vma, &obj->vma_list, vma_link)
> - if (vma->vm == vm)
> + if (vma->vm == vm && vma->ggtt_view.type == view->type)
> return vma;
>
> return NULL;
> @@ -5147,8 +5167,9 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
> }
>
> /* All the new VM stuff */
> -unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
> - struct i915_address_space *vm)
> +unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
> + struct i915_address_space *vm,
> + enum i915_ggtt_view_type view)
> {
> struct drm_i915_private *dev_priv = o->base.dev->dev_private;
> struct i915_vma *vma;
> @@ -5156,7 +5177,7 @@ unsigned long i915_gem_obj_offset(struct drm_i915_gem_object *o,
> WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
>
> list_for_each_entry(vma, &o->vma_list, vma_link) {
> - if (vma->vm == vm)
> + if (vma->vm == vm && vma->ggtt_view.type == view)
> return vma->node.start;
>
> }
> @@ -5307,7 +5328,9 @@ struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
> struct i915_vma *vma;
>
> list_for_each_entry(vma, &obj->vma_list, vma_link) {
> - if (vma->vm == ggtt)
> + if (vma->vm != ggtt)
> + continue;
> + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
> return vma;
> }
I'd prefer to have a single if (vma->vm == ggtt && type = normal view).
Everything else looks good to me.
-Michel
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 5cd2b97..4ef8815 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -590,9 +590,14 @@ static int do_switch(struct intel_engine_cs *ring,
> goto unpin_out;
>
> vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state);
> - if (!(vma->bound & GLOBAL_BIND))
> - vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level,
> - GLOBAL_BIND);
> + if (!(vma->bound & GLOBAL_BIND)) {
> + ret = i915_vma_bind(vma,
> + to->legacy_hw_ctx.rcs_state->cache_level,
> + GLOBAL_BIND);
> + /* This shouldn't ever fail. */
> + if (WARN_ONCE(ret, "GGTT context bind failed!"))
> + goto unpin_out;
> + }
>
> if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
> hw_flags |= MI_RESTORE_INHIBIT;
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 0c25f62..3927d93 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -360,9 +360,12 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
> * through the ppgtt for non_secure batchbuffers. */
> if (unlikely(IS_GEN6(dev) &&
> reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
> - !(target_vma->bound & GLOBAL_BIND)))
> - target_vma->bind_vma(target_vma, target_i915_obj->cache_level,
> - GLOBAL_BIND);
> + !(target_vma->bound & GLOBAL_BIND))) {
> + ret = i915_vma_bind(target_vma, target_i915_obj->cache_level,
> + GLOBAL_BIND);
> + if (WARN_ONCE(ret, "Unexpected failure to bind target VMA!"))
> + return ret;
> + }
>
> /* Validate that the target is in a valid r/w GPU domain */
> if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) {
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index ac03a38..73c1c0b 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -30,6 +30,8 @@
> #include "i915_trace.h"
> #include "intel_drv.h"
>
> +const struct i915_ggtt_view i915_ggtt_view_normal;
> +
> static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv);
> static void chv_setup_private_ppat(struct drm_i915_private *dev_priv);
>
> @@ -1341,9 +1343,12 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
> /* The bind_vma code tries to be smart about tracking mappings.
> * Unfortunately above, we've just wiped out the mappings
> * without telling our object about it. So we need to fake it.
> + *
> + * Bind is not expected to fail since this is only called on
> + * resume and assumption is all requirements exist already.
> */
> vma->bound &= ~GLOBAL_BIND;
> - vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
> + WARN_ON(i915_vma_bind(vma, obj->cache_level, GLOBAL_BIND));
> }
>
>
> @@ -1538,7 +1543,7 @@ static void i915_ggtt_bind_vma(struct i915_vma *vma,
> AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
>
> BUG_ON(!i915_is_ggtt(vma->vm));
> - intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags);
> + intel_gtt_insert_sg_entries(vma->ggtt_view.pages, entry, flags);
> vma->bound = GLOBAL_BIND;
> }
>
> @@ -1588,7 +1593,7 @@ static void ggtt_bind_vma(struct i915_vma *vma,
> if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
> if (!(vma->bound & GLOBAL_BIND) ||
> (cache_level != obj->cache_level)) {
> - vma->vm->insert_entries(vma->vm, obj->pages,
> + vma->vm->insert_entries(vma->vm, vma->ggtt_view.pages,
> vma->node.start,
> cache_level, flags);
> vma->bound |= GLOBAL_BIND;
> @@ -1600,7 +1605,7 @@ static void ggtt_bind_vma(struct i915_vma *vma,
> (cache_level != obj->cache_level))) {
> struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
> appgtt->base.insert_entries(&appgtt->base,
> - vma->obj->pages,
> + vma->ggtt_view.pages,
> vma->node.start,
> cache_level, flags);
> vma->bound |= LOCAL_BIND;
> @@ -2165,7 +2170,8 @@ int i915_gem_gtt_init(struct drm_device *dev)
> }
>
> static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm)
> + struct i915_address_space *vm,
> + const struct i915_ggtt_view *view)
> {
> struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
> if (vma == NULL)
> @@ -2176,6 +2182,7 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
> INIT_LIST_HEAD(&vma->exec_list);
> vma->vm = vm;
> vma->obj = obj;
> + vma->ggtt_view = *view;
>
> switch (INTEL_INFO(vm->dev)->gen) {
> case 9:
> @@ -2210,14 +2217,59 @@ static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
> }
>
> struct i915_vma *
> -i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
> - struct i915_address_space *vm)
> +i915_gem_obj_lookup_or_create_vma_view(struct drm_i915_gem_object *obj,
> + struct i915_address_space *vm,
> + const struct i915_ggtt_view *view)
> {
> struct i915_vma *vma;
>
> - vma = i915_gem_obj_to_vma(obj, vm);
> + vma = i915_gem_obj_to_vma_view(obj, vm, view);
> if (!vma)
> - vma = __i915_gem_vma_create(obj, vm);
> + vma = __i915_gem_vma_create(obj, vm, view);
>
> return vma;
> }
> +
> +static inline
> +int i915_get_vma_pages(struct i915_vma *vma)
> +{
> + if (vma->ggtt_view.pages)
> + return 0;
> +
> + if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
> + vma->ggtt_view.pages = vma->obj->pages;
> + else
> + WARN_ONCE(1, "GGTT view %u not implemented!\n",
> + vma->ggtt_view.type);
> +
> + if (!vma->ggtt_view.pages) {
> + DRM_ERROR("Failed to get pages for VMA view type %u!\n",
> + vma->ggtt_view.type);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
> + * @vma: VMA to map
> + * @cache_level: mapping cache level
> + * @flags: flags like global or local mapping
> + *
> + * DMA addresses are taken from the scatter-gather table of this object (or of
> + * this VMA in case of non-default GGTT views) and PTE entries set up.
> + * Note that DMA addresses are also the only part of the SG table we care about.
> + */
> +int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
> + u32 flags)
> +{
> + int ret = i915_get_vma_pages(vma);
> +
> + if (ret)
> + return ret;
> +
> + vma->bind_vma(vma, cache_level, flags);
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
> index dd849df..e377c7d 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> @@ -109,7 +109,20 @@ typedef gen8_gtt_pte_t gen8_ppgtt_pde_t;
> #define GEN8_PPAT_ELLC_OVERRIDE (0<<2)
> #define GEN8_PPAT(i, x) ((uint64_t) (x) << ((i) * 8))
>
> +enum i915_ggtt_view_type {
> + I915_GGTT_VIEW_NORMAL = 0,
> +};
> +
> +struct i915_ggtt_view {
> + enum i915_ggtt_view_type type;
> +
> + struct sg_table *pages;
> +};
> +
> +extern const struct i915_ggtt_view i915_ggtt_view_normal;
> +
> enum i915_cache_level;
> +
> /**
> * A VMA represents a GEM BO that is bound into an address space. Therefore, a
> * VMA's presence cannot be guaranteed before binding, or after unbinding the
> @@ -129,6 +142,15 @@ struct i915_vma {
> #define PTE_READ_ONLY (1<<2)
> unsigned int bound : 4;
>
> + /**
> + * Support different GGTT views into the same object.
> + * This means there can be multiple VMA mappings per object and per VM.
> + * i915_ggtt_view_type is used to distinguish between those entries.
> + * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
> + * assumed in GEM functions which take no ggtt view parameter.
> + */
> + struct i915_ggtt_view ggtt_view;
> +
> /** This object's place on the active/inactive lists */
> struct list_head mm_list;
>
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index c4536e1..f97479a 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -718,10 +718,8 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
> break;
>
> list_for_each_entry(vma, &obj->vma_list, vma_link)
> - if (vma->vm == vm && vma->pin_count > 0) {
> + if (vma->vm == vm && vma->pin_count > 0)
> capture_bo(err++, vma);
> - break;
> - }
> }
>
> return err - first;
> @@ -1096,10 +1094,8 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
>
> list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
> list_for_each_entry(vma, &obj->vma_list, vma_link)
> - if (vma->vm == vm && vma->pin_count > 0) {
> + if (vma->vm == vm && vma->pin_count > 0)
> i++;
> - break;
> - }
> }
> error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5510 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20141209/7f883c66/attachment-0001.bin>
More information about the Intel-gfx
mailing list