[PATCH 01/10] drm/i915: Move map-and-fenceable tracking to the VMA

Chris Wilson
2016-08-12T10:28:30Z

By moving map-and-fenceable tracking from the object to the VMA, we gain
fine-grained tracking and the ability to track individual fences on the VMA
(subsequent patch).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 6 -----
drivers/gpu/drm/i915/i915_gem.c | 36 +++++++++++++-----------------
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 ++--
drivers/gpu/drm/i915/i915_gem_fence.c | 7 +++---
drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +-
drivers/gpu/drm/i915/i915_gem_gtt.h | 10 +++++++--
drivers/gpu/drm/i915/i915_gem_tiling.c | 4 ++--
drivers/gpu/drm/i915/intel_display.c | 6 ++---
8 files changed, 35 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 74fd13330de9..1276ad1c791b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2196,12 +2196,6 @@ struct drm_i915_gem_object {
unsigned int fence_dirty:1;

/**
- * Is the object at the current location in the gtt mappable and
- * fenceable? Used to avoid costly recalculations.
- */
- unsigned int map_and_fenceable: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
* accurate mappable working set.
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5ad08071b931..c6ae9333b770 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2843,8 +2843,7 @@ int i915_vma_unbind(struct i915_vma *vma)
GEM_BUG_ON(obj->bind_count == 0);
GEM_BUG_ON(!obj->pages);

- if (i915_vma_is_ggtt(vma) &&
- vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
+ if (i915_vma_is_map_and_fenceable(vma)) {
i915_gem_object_finish_gtt(obj);

/* release the fence reg _after_ flushing */
@@ -2853,6 +2852,7 @@ int i915_vma_unbind(struct i915_vma *vma)
return ret;

__i915_vma_iounmap(vma);
+ vma->flags &= ~I915_VMA_CAN_FENCE;
}

if (likely(!vma->vm->closed)) {
@@ -2864,13 +2864,9 @@ int i915_vma_unbind(struct i915_vma *vma)
drm_mm_remove_node(&vma->node);
list_move_tail(&vma->vm_link, &vma->vm->unbound_list);

- if (i915_vma_is_ggtt(vma)) {
- if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL) {
- obj->map_and_fenceable = false;
- } else if (vma->pages) {
- sg_free_table(vma->pages);
- kfree(vma->pages);
- }
+ if (vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) {
+ sg_free_table(vma->pages);
+ kfree(vma->pages);
}
vma->pages = NULL;

@@ -3647,8 +3643,6 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
static bool
i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
{
- struct drm_i915_gem_object *obj = vma->obj;
-
if (!drm_mm_node_allocated(&vma->node))
return false;

@@ -3658,7 +3652,7 @@ i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
if (alignment && vma->node.start & (alignment - 1))
return true;

- if (flags & PIN_MAPPABLE && !obj->map_and_fenceable)
+ if (flags & PIN_MAPPABLE && !i915_vma_is_map_and_fenceable(vma))
return true;

if (flags & PIN_OFFSET_BIAS &&
@@ -3680,10 +3674,10 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
u32 fence_size, fence_alignment;

fence_size = i915_gem_get_ggtt_size(dev_priv,
- obj->base.size,
+ vma->size,
i915_gem_object_get_tiling(obj));
fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
- obj->base.size,
+ vma->size,
i915_gem_object_get_tiling(obj),
true);

@@ -3693,7 +3687,10 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
mappable = (vma->node.start + fence_size <=
dev_priv->ggtt.mappable_end);

- obj->map_and_fenceable = mappable && fenceable;
+ if (mappable && fenceable)
+ vma->flags |= I915_VMA_CAN_FENCE;
+ else
+ vma->flags &= ~I915_VMA_CAN_FENCE;
}

int __i915_vma_do_pin(struct i915_vma *vma,
@@ -3753,12 +3750,11 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,

WARN(i915_vma_is_pinned(vma),
"bo is already pinned in ggtt with incorrect alignment:"
- " offset=%08x, req.alignment=%llx, req.map_and_fenceable=%d,"
- " obj->map_and_fenceable=%d\n",
- i915_ggtt_offset(vma),
- alignment,
+ " offset=%08x, req.alignment=%llx,"
+ " req.map_and_fenceable=%d, vma->map_and_fenceable=%d\n",
+ i915_ggtt_offset(vma), alignment,
!!(flags & PIN_MAPPABLE),
- obj->map_and_fenceable);
+ i915_vma_is_map_and_fenceable(vma));
ret = i915_vma_unbind(vma);
if (ret)
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 98f9945c5b1d..572e6a4f9d7e 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -853,7 +853,6 @@ static bool
eb_vma_misplaced(struct i915_vma *vma)
{
struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
- struct drm_i915_gem_object *obj = vma->obj;

WARN_ON(entry->flags & __EXEC_OBJECT_NEEDS_MAP &&
!i915_vma_is_ggtt(vma));
@@ -874,7 +873,8 @@ eb_vma_misplaced(struct i915_vma *vma)
return true;

/* avoid costly ping-pong once a batch bo ended up non-mappable */
- if (entry->flags & __EXEC_OBJECT_NEEDS_MAP && !obj->map_and_fenceable)
+ if (entry->flags & __EXEC_OBJECT_NEEDS_MAP &&
+ !i915_vma_is_map_and_fenceable(vma))
return !only_mappable_for_reloc(entry->flags);

if ((entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) == 0 &&
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c
index 911cea719e79..015f9228bc87 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence.c
@@ -130,7 +130,9 @@ static void i915_write_fence_reg(struct drm_device *dev, int reg,
!is_power_of_2(vma->node.size) ||
(vma->node.start & (vma->node.size - 1)),
"object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08llx) aligned\n",
- vma->node.start, obj->map_and_fenceable, vma->node.size);
+ vma->node.start,
+ i915_vma_is_map_and_fenceable(vma),
+ vma->node.size);

if (tiling == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
tile_width = 128;
@@ -389,9 +391,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
return 0;
}
} else if (enable) {
- if (WARN_ON(!obj->map_and_fenceable))
- return -EINVAL;
-
reg = i915_find_fence_reg(dev);
if (IS_ERR(reg))
return PTR_ERR(reg);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index e173ccdebdc6..54063057eabf 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -3689,7 +3689,7 @@ void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
assert_rpm_wakelock_held(to_i915(vma->vm->dev));

lockdep_assert_held(&vma->vm->dev->struct_mutex);
- if (WARN_ON(!vma->obj->map_and_fenceable))
+ if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
return IO_ERR_PTR(-ENODEV);

GEM_BUG_ON(!i915_vma_is_ggtt(vma));
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 79a08a050487..ed0a6c7a1883 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -197,8 +197,9 @@ struct i915_vma {
#define I915_VMA_LOCAL_BIND BIT(7)
#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)

-#define I915_VMA_GGTT BIT(8)
-#define I915_VMA_CLOSED BIT(9)
+#define I915_VMA_GGTT BIT(8)
+#define I915_VMA_CAN_FENCE BIT(9)
+#define I915_VMA_CLOSED BIT(10)

unsigned int active;
struct i915_gem_active last_read[I915_NUM_ENGINES];
@@ -239,6 +240,11 @@ static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
return vma->flags & I915_VMA_GGTT;
}

+static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
+{
+ return vma->flags & I915_VMA_CAN_FENCE;
+}
+
static inline bool i915_vma_is_closed(const struct i915_vma *vma)
{
return vma->flags & I915_VMA_CLOSED;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index bfefb63a55ef..af70d4460a9e 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -134,7 +134,7 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj, int tiling_mode)
if (!vma)
return 0;

- if (!obj->map_and_fenceable)
+ if (!i915_vma_is_map_and_fenceable(vma))
return 0;

if (IS_GEN3(dev_priv)) {
@@ -145,7 +145,7 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj, int tiling_mode)
goto bad;
}

- size = i915_gem_get_ggtt_size(dev_priv, obj->base.size, tiling_mode);
+ size = i915_gem_get_ggtt_size(dev_priv, vma->size, tiling_mode);
if (vma->node.size < size)
goto bad;

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 31eaeedfad30..04a8900f68c1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2224,7 +2224,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
* framebuffer compression. For simplicity, we always install
* a fence as the cost is not that onerous.
*/
- if (view.type == I915_GGTT_VIEW_NORMAL) {
+ if (i915_vma_is_map_and_fenceable(vma)) {
ret = i915_gem_object_get_fence(obj);
if (ret == -EDEADLK) {
/*
@@ -2262,11 +2262,11 @@ void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));

intel_fill_fb_ggtt_view(&view, fb, rotation);
+ vma = i915_gem_object_to_ggtt(obj, &view);

- if (view.type == I915_GGTT_VIEW_NORMAL)
+ if (i915_vma_is_map_and_fenceable(vma))
i915_gem_object_unpin_fence(obj);

- vma = i915_gem_object_to_ggtt(obj, &view);
i915_gem_object_unpin_from_display_plane(vma);
}

--
2.8.1