Skip to content

Commit

Permalink
drm/i915: Count how many VMA are bound for an object
Browse files Browse the repository at this point in the history
Since we may have VMA allocated for an object, but we interrupted their
binding, there is a disparity between have elements on the obj->vma_list
and being bound. i915_gem_obj_bound_any() does this check, but this is
not rigorously observed - add an explicit count to make it easier.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470293567-10811-7-git-send-email-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed Aug 4, 2016
1 parent 2bfa996 commit 15717de
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 37 deletions.
12 changes: 5 additions & 7 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
if (obj->fence_reg != I915_FENCE_REG_NONE)
seq_printf(m, " (fence: %d)", obj->fence_reg);
list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (!drm_mm_node_allocated(&vma->node))
continue;

seq_printf(m, " (%sgtt offset: %08llx, size: %08llx",
vma->is_ggtt ? "g" : "pp",
vma->node.start, vma->node.size);
Expand Down Expand Up @@ -335,20 +338,18 @@ static int per_file_stats(int id, void *ptr, void *data)
struct drm_i915_gem_object *obj = ptr;
struct file_stats *stats = data;
struct i915_vma *vma;
int bound = 0;

stats->count++;
stats->total += obj->base.size;

if (!obj->bind_count)
stats->unbound += obj->base.size;
if (obj->base.name || obj->base.dma_buf)
stats->shared += obj->base.size;

list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (!drm_mm_node_allocated(&vma->node))
continue;

bound++;

if (vma->is_ggtt) {
stats->global += vma->node.size;
} else {
Expand All @@ -364,9 +365,6 @@ static int per_file_stats(int id, void *ptr, void *data)
stats->inactive += vma->node.size;
}

if (!bound)
stats->unbound += obj->base.size;

return 0;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,8 @@ struct drm_i915_gem_object {
unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;

unsigned int has_wc_mmap;
/** Count of VMA actually bound by this object */
unsigned int bind_count;
unsigned int pin_display;

struct sg_table *pages;
Expand Down Expand Up @@ -3266,7 +3268,6 @@ i915_gem_obj_ggtt_offset(struct drm_i915_gem_object *o)
return i915_gem_obj_ggtt_offset_view(o, &i915_ggtt_view_normal);
}

bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o);
bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
const struct i915_ggtt_view *view);
bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
Expand Down
30 changes: 10 additions & 20 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2107,7 +2107,7 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
if (obj->pages_pin_count)
return -EBUSY;

BUG_ON(i915_gem_obj_bound_any(obj));
GEM_BUG_ON(obj->bind_count);

/* ->put_pages might need to allocate memory for the bit17 swizzle
* array, hence protect them from being reaped by removing them from gtt
Expand Down Expand Up @@ -2965,7 +2965,6 @@ static void __i915_vma_iounmap(struct i915_vma *vma)
static int __i915_vma_unbind(struct i915_vma *vma, bool wait)
{
struct drm_i915_gem_object *obj = vma->obj;
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
int ret;

if (list_empty(&vma->obj_link))
Expand All @@ -2979,7 +2978,8 @@ static int __i915_vma_unbind(struct i915_vma *vma, bool wait)
if (vma->pin_count)
return -EBUSY;

BUG_ON(obj->pages == NULL);
GEM_BUG_ON(obj->bind_count == 0);
GEM_BUG_ON(!obj->pages);

if (wait) {
ret = i915_gem_object_wait_rendering(obj, false);
Expand Down Expand Up @@ -3019,8 +3019,9 @@ static int __i915_vma_unbind(struct i915_vma *vma, bool wait)

/* Since the unbound list is global, only move to that list if
* no more VMAs exist. */
if (list_empty(&obj->vma_list))
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
if (--obj->bind_count == 0)
list_move_tail(&obj->global_list,
&to_i915(obj->base.dev)->mm.unbound_list);

/* And finally now the object is completely decoupled from this vma,
* we can drop its hold on the backing storage and allow it to be
Expand Down Expand Up @@ -3255,6 +3256,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,

list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
list_add_tail(&vma->vm_link, &vm->inactive_list);
obj->bind_count++;

return vma;

Expand Down Expand Up @@ -3450,7 +3452,6 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
{
struct drm_device *dev = obj->base.dev;
struct i915_vma *vma, *next;
bool bound = false;
int ret = 0;

if (obj->cache_level == cache_level)
Expand All @@ -3474,8 +3475,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
ret = i915_vma_unbind(vma);
if (ret)
return ret;
} else
bound = true;
}
}

/* We can reuse the existing drm_mm nodes but need to change the
Expand All @@ -3485,7 +3485,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
* rewrite the PTE in the belief that doing so tramples upon less
* state and so involves less work.
*/
if (bound) {
if (obj->bind_count) {
/* Before we change the PTE, the GPU must not be accessing it.
* If we wait upon the object, we know that all the bound
* VMA are no longer active.
Expand Down Expand Up @@ -4223,6 +4223,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
dev_priv->mm.interruptible = was_interruptible;
}
}
GEM_BUG_ON(obj->bind_count);

/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
* before progressing. */
Expand Down Expand Up @@ -4840,17 +4841,6 @@ bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
return false;
}

bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o)
{
struct i915_vma *vma;

list_for_each_entry(vma, &o->vma_list, obj_link)
if (drm_mm_node_allocated(&vma->node))
return true;

return false;
}

unsigned long i915_gem_obj_ggtt_size(struct drm_i915_gem_object *o)
{
struct i915_vma *vma;
Expand Down
17 changes: 8 additions & 9 deletions drivers/gpu/drm/i915/i915_gem_shrinker.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,15 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
#endif
}

static int num_vma_bound(struct drm_i915_gem_object *obj)
static bool any_vma_pinned(struct drm_i915_gem_object *obj)
{
struct i915_vma *vma;
int count = 0;

list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (drm_mm_node_allocated(&vma->node))
count++;
list_for_each_entry(vma, &obj->vma_list, obj_link)
if (vma->pin_count)
count++;
}
return true;

return count;
return false;
}

static bool swap_available(void)
Expand All @@ -82,7 +78,10 @@ static bool can_release_pages(struct drm_i915_gem_object *obj)
* to the GPU, simply unbinding from the GPU is not going to succeed
* in releasing our pin count on the pages themselves.
*/
if (obj->pages_pin_count != num_vma_bound(obj))
if (obj->pages_pin_count > obj->bind_count)
return false;

if (any_vma_pinned(obj))
return false;

/* We can only return physical pages to the system if we can either
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_gem_stolen.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
vma->bound |= GLOBAL_BIND;
__i915_vma_set_map_and_fenceable(vma);
list_add_tail(&vma->vm_link, &ggtt->base.inactive_list);
obj->bind_count++;

list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
i915_gem_object_pin_pages(obj);
Expand Down

0 comments on commit 15717de

Please sign in to comment.