Skip to content

Commit

Permalink
drm/i915: Move fence tracking from object to vma
Browse files Browse the repository at this point in the history
In order to handle tiled partial GTT mmappings, we need to associate the
fence with an individual vma.

v2: A couple of silly drops replaced spotted by Joonas

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160818161718.27187-21-chris@chris-wilson.co.uk
  • Loading branch information
ickle committed Aug 18, 2016
1 parent a1e5afb commit 49ef529
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 388 deletions.
16 changes: 8 additions & 8 deletions drivers/gpu/drm/i915/i915_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
seq_printf(m, "%x ",
i915_gem_active_get_seqno(&obj->last_read[id],
&obj->base.dev->struct_mutex));
seq_printf(m, "] %x %x%s%s%s",
seq_printf(m, "] %x %s%s%s",
i915_gem_active_get_seqno(&obj->last_write,
&obj->base.dev->struct_mutex),
i915_gem_active_get_seqno(&obj->last_fence,
&obj->base.dev->struct_mutex),
i915_cache_level_str(to_i915(obj->base.dev), obj->cache_level),
obj->dirty ? " dirty" : "",
obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
Expand All @@ -169,8 +167,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
seq_printf(m, " (pinned x %d)", pin_count);
if (obj->pin_display)
seq_printf(m, " (display)");
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;
Expand All @@ -180,6 +176,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
vma->node.start, vma->node.size);
if (i915_vma_is_ggtt(vma))
seq_printf(m, ", type: %u", vma->ggtt_view.type);
if (vma->fence)
seq_printf(m, " , fence: %d%s",
vma->fence->id,
i915_gem_active_isset(&vma->last_fence) ? "*" : "");
seq_puts(m, ")");
}
if (obj->stolen)
Expand Down Expand Up @@ -938,14 +938,14 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)

seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
for (i = 0; i < dev_priv->num_fence_regs; i++) {
struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj;
struct i915_vma *vma = dev_priv->fence_regs[i].vma;

seq_printf(m, "Fence %d, pin count = %d, object = ",
i, dev_priv->fence_regs[i].pin_count);
if (obj == NULL)
if (!vma)
seq_puts(m, "unused");
else
describe_obj(m, obj);
describe_obj(m, vma->obj);
seq_putc(m, '\n');
}

Expand Down
82 changes: 55 additions & 27 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,21 @@ struct intel_opregion {
struct intel_overlay;
struct intel_overlay_error_state;

#define I915_FENCE_REG_NONE -1
#define I915_MAX_NUM_FENCES 32
/* 32 fences + sign bit for FENCE_REG_NONE */
#define I915_MAX_NUM_FENCE_BITS 6

struct drm_i915_fence_reg {
struct list_head link;
struct drm_i915_gem_object *obj;
struct drm_i915_private *i915;
struct i915_vma *vma;
int pin_count;
int id;
/**
* Whether the tiling parameters for the currently
* associated fence register have changed. Note that
* for the purposes of tracking tiling changes we also
* treat the unfenced register, the register slot that
* the object occupies whilst it executes a fenced
* command (such as BLT on gen2/3), as a "fence".
*/
bool dirty;
};

struct sdvo_device_mapping {
Expand Down Expand Up @@ -2171,27 +2177,11 @@ struct drm_i915_gem_object {
*/
unsigned int dirty:1;

/**
* Fence register bits (if any) for this object. Will be set
* as needed when mapped into the GTT.
* Protected by dev->struct_mutex.
*/
signed int fence_reg:I915_MAX_NUM_FENCE_BITS;

/**
* Advice: are the backing pages purgeable?
*/
unsigned int madv:2;

/**
* Whether the tiling parameters for the currently associated fence
* register have changed. Note that for the purposes of tracking
* tiling changes we also treat the unfenced register, the register
* slot that the object occupies whilst it executes a fenced
* command (such as BLT on gen2/3), as a "fence".
*/
unsigned int fence_dirty:1;

/**
* Whether the current gtt mapping needs to be mappable (and isn't just
* mappable by accident). Track pin and fault separate for a more
Expand Down Expand Up @@ -2240,7 +2230,6 @@ struct drm_i915_gem_object {
*/
struct i915_gem_active last_read[I915_NUM_ENGINES];
struct i915_gem_active last_write;
struct i915_gem_active last_fence;

/** References from framebuffers, locks out tiling changes. */
unsigned long framebuffer_references;
Expand Down Expand Up @@ -3343,11 +3332,50 @@ i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
}

/* i915_gem_fence.c */
int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);
int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
int __must_check i915_vma_get_fence(struct i915_vma *vma);
int __must_check i915_vma_put_fence(struct i915_vma *vma);

/**
* i915_vma_pin_fence - pin fencing state
* @vma: vma to pin fencing for
*
* This pins the fencing state (whether tiled or untiled) to make sure the
* vma (and its object) is ready to be used as a scanout target. Fencing
* status must be synchronize first by calling i915_vma_get_fence():
*
* The resulting fence pin reference must be released again with
* i915_vma_unpin_fence().
*
* Returns:
*
* True if the vma has a fence, false otherwise.
*/
static inline bool
i915_vma_pin_fence(struct i915_vma *vma)
{
if (vma->fence) {
vma->fence->pin_count++;
return true;
} else
return false;
}

bool i915_gem_object_pin_fence(struct drm_i915_gem_object *obj);
void i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj);
/**
* i915_vma_unpin_fence - unpin fencing state
* @vma: vma to unpin fencing for
*
* This releases the fence pin reference acquired through
* i915_vma_pin_fence. It will handle both objects with and without an
* attached fence correctly, callers do not need to distinguish this.
*/
static inline void
i915_vma_unpin_fence(struct i915_vma *vma)
{
if (vma->fence) {
GEM_BUG_ON(vma->fence->pin_count <= 0);
vma->fence->pin_count--;
}
}

void i915_gem_restore_fences(struct drm_device *dev);

Expand Down
30 changes: 17 additions & 13 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ i915_gem_gtt_pread(struct drm_device *dev,
if (!IS_ERR(vma)) {
node.start = i915_ggtt_offset(vma);
node.allocated = false;
ret = i915_gem_object_put_fence(obj);
ret = i915_vma_put_fence(vma);
if (ret) {
i915_vma_unpin(vma);
vma = ERR_PTR(ret);
Expand Down Expand Up @@ -1131,7 +1131,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
if (!IS_ERR(vma)) {
node.start = i915_ggtt_offset(vma);
node.allocated = false;
ret = i915_gem_object_put_fence(obj);
ret = i915_vma_put_fence(vma);
if (ret) {
i915_vma_unpin(vma);
vma = ERR_PTR(ret);
Expand Down Expand Up @@ -1751,7 +1751,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
if (ret)
goto err_unpin;

ret = i915_gem_object_get_fence(obj);
ret = i915_vma_get_fence(vma);
if (ret)
goto err_unpin;

Expand Down Expand Up @@ -2903,7 +2903,7 @@ int i915_vma_unbind(struct i915_vma *vma)
i915_gem_object_finish_gtt(obj);

/* release the fence reg _after_ flushing */
ret = i915_gem_object_put_fence(obj);
ret = i915_vma_put_fence(vma);
if (ret)
return ret;

Expand Down Expand Up @@ -3385,9 +3385,11 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
* dropped the fence as all snoopable access is
* supposed to be linear.
*/
ret = i915_gem_object_put_fence(obj);
if (ret)
return ret;
list_for_each_entry(vma, &obj->vma_list, obj_link) {
ret = i915_vma_put_fence(vma);
if (ret)
return ret;
}
} else {
/* We either have incoherent backing store and
* so no GTT access or the architecture is fully
Expand Down Expand Up @@ -4065,14 +4067,12 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
i915_gem_object_retire__read);
init_request_active(&obj->last_write,
i915_gem_object_retire__write);
init_request_active(&obj->last_fence, NULL);
INIT_LIST_HEAD(&obj->obj_exec_link);
INIT_LIST_HEAD(&obj->vma_list);
INIT_LIST_HEAD(&obj->batch_pool_link);

obj->ops = ops;

obj->fence_reg = I915_FENCE_REG_NONE;
obj->madv = I915_MADV_WILLNEED;

i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size);
Expand Down Expand Up @@ -4502,6 +4502,7 @@ void
i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = &dev_priv->drm;
int i;

if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
!IS_CHERRYVIEW(dev_priv))
Expand All @@ -4517,6 +4518,13 @@ i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
I915_READ(vgtif_reg(avail_rs.fence_num));

/* Initialize fence registers to zero */
for (i = 0; i < dev_priv->num_fence_regs; i++) {
struct drm_i915_fence_reg *fence = &dev_priv->fence_regs[i];

fence->i915 = dev_priv;
fence->id = i;
list_add_tail(&fence->link, &dev_priv->mm.fence_list);
}
i915_gem_restore_fences(dev);

i915_gem_detect_bit_6_swizzle(dev);
Expand Down Expand Up @@ -4552,8 +4560,6 @@ i915_gem_load_init(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
for (i = 0; i < I915_NUM_ENGINES; i++)
init_engine_lists(&dev_priv->engine[i]);
for (i = 0; i < I915_MAX_NUM_FENCES; i++)
INIT_LIST_HEAD(&dev_priv->fence_regs[i].link);
INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
i915_gem_retire_work_handler);
INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
Expand All @@ -4563,8 +4569,6 @@ i915_gem_load_init(struct drm_device *dev)

dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;

INIT_LIST_HEAD(&dev_priv->mm.fence_list);

init_waitqueue_head(&dev_priv->pending_flip_queue);

dev_priv->mm.interruptible = true;
Expand Down
20 changes: 6 additions & 14 deletions drivers/gpu/drm/i915/i915_gem_execbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,14 @@ static void
i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
{
struct drm_i915_gem_exec_object2 *entry;
struct drm_i915_gem_object *obj = vma->obj;

if (!drm_mm_node_allocated(&vma->node))
return;

entry = vma->exec_entry;

if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
i915_gem_object_unpin_fence(obj);
i915_vma_unpin_fence(vma);

if (entry->flags & __EXEC_OBJECT_HAS_PIN)
__i915_vma_unpin(vma);
Expand Down Expand Up @@ -455,7 +454,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
if (ret)
return ERR_PTR(ret);
} else {
ret = i915_gem_object_put_fence(obj);
ret = i915_vma_put_fence(vma);
if (ret) {
i915_vma_unpin(vma);
return ERR_PTR(ret);
Expand Down Expand Up @@ -811,11 +810,11 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
entry->flags |= __EXEC_OBJECT_HAS_PIN;

if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
ret = i915_gem_object_get_fence(obj);
ret = i915_vma_get_fence(vma);
if (ret)
return ret;

if (i915_gem_object_pin_fence(obj))
if (i915_vma_pin_fence(vma))
entry->flags |= __EXEC_OBJECT_HAS_FENCE;
}

Expand Down Expand Up @@ -1305,15 +1304,8 @@ void i915_vma_move_to_active(struct i915_vma *vma,
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
}

if (flags & EXEC_OBJECT_NEEDS_FENCE) {
i915_gem_active_set(&obj->last_fence, req);
if (flags & __EXEC_OBJECT_HAS_FENCE) {
struct drm_i915_private *dev_priv = req->i915;

list_move_tail(&dev_priv->fence_regs[obj->fence_reg].link,
&dev_priv->mm.fence_list);
}
}
if (flags & EXEC_OBJECT_NEEDS_FENCE)
i915_gem_active_set(&vma->last_fence, req);

i915_vma_set_active(vma, idx);
i915_gem_active_set(&vma->last_read[idx], req);
Expand Down
Loading

0 comments on commit 49ef529

Please sign in to comment.