drm/i915: Start passing around i915_vma from execbuffer
During execbuffer we look up the i915_vma in order to reserve them in the VM. However, we then do a double lookup of the vma in order to then pin them, all because we lack the necessary interfaces to operate on i915_vma - so introduce i915_vma_pin()! v2: Tidy parameter lists to remove one level of redirection in the hot path. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1470324762-2545-15-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
20dfbde463
commit
59bfa1248e
@ -3018,23 +3018,6 @@ struct drm_i915_gem_object *i915_gem_object_create_from_data(
|
|||||||
void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
|
void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
|
||||||
void i915_gem_free_object(struct drm_gem_object *obj);
|
void i915_gem_free_object(struct drm_gem_object *obj);
|
||||||
|
|
||||||
/* Flags used by pin/bind&friends. */
|
|
||||||
#define PIN_MAPPABLE (1<<0)
|
|
||||||
#define PIN_NONBLOCK (1<<1)
|
|
||||||
#define PIN_GLOBAL (1<<2)
|
|
||||||
#define PIN_OFFSET_BIAS (1<<3)
|
|
||||||
#define PIN_USER (1<<4)
|
|
||||||
#define PIN_UPDATE (1<<5)
|
|
||||||
#define PIN_ZONE_4G (1<<6)
|
|
||||||
#define PIN_HIGH (1<<7)
|
|
||||||
#define PIN_OFFSET_FIXED (1<<8)
|
|
||||||
#define PIN_OFFSET_MASK (~4095)
|
|
||||||
int __must_check
|
|
||||||
i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
|
||||||
struct i915_address_space *vm,
|
|
||||||
u64 size,
|
|
||||||
u64 alignment,
|
|
||||||
u64 flags);
|
|
||||||
int __must_check
|
int __must_check
|
||||||
i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
||||||
const struct i915_ggtt_view *view,
|
const struct i915_ggtt_view *view,
|
||||||
@ -3311,11 +3294,8 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
|
|||||||
uint32_t alignment,
|
uint32_t alignment,
|
||||||
unsigned flags)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
return i915_gem_object_ggtt_pin(obj, &i915_ggtt_view_normal,
|
||||||
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
0, alignment, flags);
|
||||||
|
|
||||||
return i915_gem_object_pin(obj, &ggtt->base, 0, alignment,
|
|
||||||
flags | PIN_GLOBAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
|
void i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
|
||||||
|
@ -2963,34 +2963,30 @@ static bool i915_gem_valid_gtt_space(struct i915_vma *vma,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds free space in the GTT aperture and binds the object or a view of it
|
* i915_vma_insert - finds a slot for the vma in its address space
|
||||||
* there.
|
* @vma: the vma
|
||||||
* @obj: object to bind
|
|
||||||
* @vm: address space to bind into
|
|
||||||
* @ggtt_view: global gtt view if applicable
|
|
||||||
* @size: requested size in bytes (can be larger than the VMA)
|
* @size: requested size in bytes (can be larger than the VMA)
|
||||||
* @alignment: requested alignment
|
* @alignment: required alignment
|
||||||
* @flags: mask of PIN_* flags to use
|
* @flags: mask of PIN_* flags to use
|
||||||
|
*
|
||||||
|
* First we try to allocate some free space that meets the requirements for
|
||||||
|
* the VMA. Failiing that, if the flags permit, it will evict an old VMA,
|
||||||
|
* preferrably the oldest idle entry to make room for the new VMA.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, negative error code otherwise.
|
||||||
*/
|
*/
|
||||||
static struct i915_vma *
|
static int
|
||||||
i915_gem_object_insert_into_vm(struct drm_i915_gem_object *obj,
|
i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
|
||||||
struct i915_address_space *vm,
|
|
||||||
const struct i915_ggtt_view *ggtt_view,
|
|
||||||
u64 size,
|
|
||||||
u64 alignment,
|
|
||||||
u64 flags)
|
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
|
||||||
struct i915_vma *vma;
|
struct drm_i915_gem_object *obj = vma->obj;
|
||||||
u64 start, end;
|
u64 start, end;
|
||||||
u64 min_alignment;
|
u64 min_alignment;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
vma = ggtt_view ?
|
GEM_BUG_ON(vma->bound);
|
||||||
i915_gem_obj_lookup_or_create_ggtt_vma(obj, ggtt_view) :
|
GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
|
||||||
i915_gem_obj_lookup_or_create_vma(obj, vm);
|
|
||||||
if (IS_ERR(vma))
|
|
||||||
return vma;
|
|
||||||
|
|
||||||
size = max(size, vma->size);
|
size = max(size, vma->size);
|
||||||
if (flags & PIN_MAPPABLE)
|
if (flags & PIN_MAPPABLE)
|
||||||
@ -3004,7 +3000,7 @@ i915_gem_object_insert_into_vm(struct drm_i915_gem_object *obj,
|
|||||||
if (alignment & (min_alignment - 1)) {
|
if (alignment & (min_alignment - 1)) {
|
||||||
DRM_DEBUG("Invalid object alignment requested %llu, minimum %llu\n",
|
DRM_DEBUG("Invalid object alignment requested %llu, minimum %llu\n",
|
||||||
alignment, min_alignment);
|
alignment, min_alignment);
|
||||||
return ERR_PTR(-EINVAL);
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
|
start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
|
||||||
@ -3024,17 +3020,17 @@ i915_gem_object_insert_into_vm(struct drm_i915_gem_object *obj,
|
|||||||
size, obj->base.size,
|
size, obj->base.size,
|
||||||
flags & PIN_MAPPABLE ? "mappable" : "total",
|
flags & PIN_MAPPABLE ? "mappable" : "total",
|
||||||
end);
|
end);
|
||||||
return ERR_PTR(-E2BIG);
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = i915_gem_object_get_pages(obj);
|
ret = i915_gem_object_get_pages(obj);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ERR_PTR(ret);
|
return ret;
|
||||||
|
|
||||||
i915_gem_object_pin_pages(obj);
|
i915_gem_object_pin_pages(obj);
|
||||||
|
|
||||||
if (flags & PIN_OFFSET_FIXED) {
|
if (flags & PIN_OFFSET_FIXED) {
|
||||||
uint64_t offset = flags & PIN_OFFSET_MASK;
|
u64 offset = flags & PIN_OFFSET_MASK;
|
||||||
if (offset & (alignment - 1) || offset > end - size) {
|
if (offset & (alignment - 1) || offset > end - size) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_unpin;
|
goto err_unpin;
|
||||||
@ -3096,11 +3092,11 @@ search_free:
|
|||||||
list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
|
list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
|
||||||
obj->bind_count++;
|
obj->bind_count++;
|
||||||
|
|
||||||
return vma;
|
return 0;
|
||||||
|
|
||||||
err_unpin:
|
err_unpin:
|
||||||
i915_gem_object_unpin_pages(obj);
|
i915_gem_object_unpin_pages(obj);
|
||||||
return ERR_PTR(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -3661,6 +3657,9 @@ i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
|
|||||||
{
|
{
|
||||||
struct drm_i915_gem_object *obj = vma->obj;
|
struct drm_i915_gem_object *obj = vma->obj;
|
||||||
|
|
||||||
|
if (!drm_mm_node_allocated(&vma->node))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (vma->node.size < size)
|
if (vma->node.size < size)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -3705,91 +3704,42 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
|
|||||||
obj->map_and_fenceable = mappable && fenceable;
|
obj->map_and_fenceable = mappable && fenceable;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
|
i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
|
||||||
struct i915_address_space *vm,
|
|
||||||
const struct i915_ggtt_view *ggtt_view,
|
|
||||||
u64 size,
|
|
||||||
u64 alignment,
|
|
||||||
u64 flags)
|
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
unsigned int bound = vma->bound;
|
||||||
struct i915_vma *vma;
|
|
||||||
unsigned bound;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base))
|
GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
|
||||||
return -ENODEV;
|
GEM_BUG_ON((flags & PIN_GLOBAL) && !vma->is_ggtt);
|
||||||
|
|
||||||
if (WARN_ON(flags & (PIN_GLOBAL | PIN_MAPPABLE) && !i915_is_ggtt(vm)))
|
if (WARN_ON(i915_vma_pin_count(vma) == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
|
||||||
return -EINVAL;
|
return -EBUSY;
|
||||||
|
|
||||||
if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE))
|
/* Pin early to prevent the shrinker/eviction logic from destroying
|
||||||
return -EINVAL;
|
* our vma as we insert and bind.
|
||||||
|
*/
|
||||||
|
__i915_vma_pin(vma);
|
||||||
|
|
||||||
if (WARN_ON(i915_is_ggtt(vm) != !!ggtt_view))
|
if (!bound) {
|
||||||
return -EINVAL;
|
ret = i915_vma_insert(vma, size, alignment, flags);
|
||||||
|
if (ret)
|
||||||
vma = ggtt_view ? i915_gem_obj_to_ggtt_view(obj, ggtt_view) :
|
goto err;
|
||||||
i915_gem_obj_to_vma(obj, vm);
|
|
||||||
|
|
||||||
if (vma) {
|
|
||||||
if (WARN_ON(i915_vma_pin_count(vma) == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
if (i915_vma_misplaced(vma, size, alignment, flags)) {
|
|
||||||
WARN(i915_vma_is_pinned(vma),
|
|
||||||
"bo is already pinned in %s with incorrect alignment:"
|
|
||||||
" offset=%08x %08x, req.alignment=%llx, req.map_and_fenceable=%d,"
|
|
||||||
" obj->map_and_fenceable=%d\n",
|
|
||||||
ggtt_view ? "ggtt" : "ppgtt",
|
|
||||||
upper_32_bits(vma->node.start),
|
|
||||||
lower_32_bits(vma->node.start),
|
|
||||||
alignment,
|
|
||||||
!!(flags & PIN_MAPPABLE),
|
|
||||||
obj->map_and_fenceable);
|
|
||||||
ret = i915_vma_unbind(vma);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
vma = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
|
ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
|
||||||
vma = i915_gem_object_insert_into_vm(obj, vm, ggtt_view,
|
|
||||||
size, alignment, flags);
|
|
||||||
if (IS_ERR(vma))
|
|
||||||
return PTR_ERR(vma);
|
|
||||||
}
|
|
||||||
|
|
||||||
bound = vma->bound;
|
|
||||||
ret = i915_vma_bind(vma, obj->cache_level, flags);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto err;
|
||||||
|
|
||||||
if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL &&
|
if ((bound ^ vma->bound) & GLOBAL_BIND)
|
||||||
(bound ^ vma->bound) & GLOBAL_BIND) {
|
|
||||||
__i915_vma_set_map_and_fenceable(vma);
|
__i915_vma_set_map_and_fenceable(vma);
|
||||||
WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
|
|
||||||
}
|
|
||||||
|
|
||||||
GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
|
GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
|
||||||
|
|
||||||
__i915_vma_pin(vma);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
int
|
err:
|
||||||
i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
__i915_vma_unpin(vma);
|
||||||
struct i915_address_space *vm,
|
return ret;
|
||||||
u64 size,
|
|
||||||
u64 alignment,
|
|
||||||
u64 flags)
|
|
||||||
{
|
|
||||||
return i915_gem_object_do_pin(obj, vm,
|
|
||||||
i915_is_ggtt(vm) ? &i915_ggtt_view_normal : NULL,
|
|
||||||
size, alignment, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -3799,14 +3749,35 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
|||||||
u64 alignment,
|
u64 alignment,
|
||||||
u64 flags)
|
u64 flags)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = obj->base.dev;
|
struct i915_vma *vma;
|
||||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
int ret;
|
||||||
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
|
||||||
|
|
||||||
BUG_ON(!view);
|
BUG_ON(!view);
|
||||||
|
|
||||||
return i915_gem_object_do_pin(obj, &ggtt->base, view,
|
vma = i915_gem_obj_lookup_or_create_ggtt_vma(obj, view);
|
||||||
size, alignment, flags | PIN_GLOBAL);
|
if (IS_ERR(vma))
|
||||||
|
return PTR_ERR(vma);
|
||||||
|
|
||||||
|
if (i915_vma_misplaced(vma, size, alignment, flags)) {
|
||||||
|
if (flags & PIN_NONBLOCK &&
|
||||||
|
(i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
WARN(i915_vma_is_pinned(vma),
|
||||||
|
"bo is already pinned in ggtt with incorrect alignment:"
|
||||||
|
" offset=%08x %08x, req.alignment=%llx, req.map_and_fenceable=%d,"
|
||||||
|
" obj->map_and_fenceable=%d\n",
|
||||||
|
upper_32_bits(vma->node.start),
|
||||||
|
lower_32_bits(vma->node.start),
|
||||||
|
alignment,
|
||||||
|
!!(flags & PIN_MAPPABLE),
|
||||||
|
obj->map_and_fenceable);
|
||||||
|
ret = i915_vma_unbind(vma);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -45,11 +45,10 @@
|
|||||||
struct i915_execbuffer_params {
|
struct i915_execbuffer_params {
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
struct drm_file *file;
|
struct drm_file *file;
|
||||||
u32 dispatch_flags;
|
struct i915_vma *batch;
|
||||||
u32 args_batch_start_offset;
|
u32 dispatch_flags;
|
||||||
u32 batch_obj_vm_offset;
|
u32 args_batch_start_offset;
|
||||||
struct intel_engine_cs *engine;
|
struct intel_engine_cs *engine;
|
||||||
struct drm_i915_gem_object *batch_obj;
|
|
||||||
struct i915_gem_context *ctx;
|
struct i915_gem_context *ctx;
|
||||||
struct drm_i915_gem_request *request;
|
struct drm_i915_gem_request *request;
|
||||||
};
|
};
|
||||||
@ -102,6 +101,26 @@ eb_reset(struct eb_vmas *eb)
|
|||||||
memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
|
memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct i915_vma *
|
||||||
|
eb_get_batch(struct eb_vmas *eb)
|
||||||
|
{
|
||||||
|
struct i915_vma *vma = list_entry(eb->vmas.prev, typeof(*vma), exec_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SNA is doing fancy tricks with compressing batch buffers, which leads
|
||||||
|
* to negative relocation deltas. Usually that works out ok since the
|
||||||
|
* relocate address is still positive, except when the batch is placed
|
||||||
|
* very low in the GTT. Ensure this doesn't happen.
|
||||||
|
*
|
||||||
|
* Note that actual hangs have only been observed on gen7, but for
|
||||||
|
* paranoia do it everywhere.
|
||||||
|
*/
|
||||||
|
if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0)
|
||||||
|
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
||||||
|
|
||||||
|
return vma;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eb_lookup_vmas(struct eb_vmas *eb,
|
eb_lookup_vmas(struct eb_vmas *eb,
|
||||||
struct drm_i915_gem_exec_object2 *exec,
|
struct drm_i915_gem_exec_object2 *exec,
|
||||||
@ -198,35 +217,6 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct i915_vma *
|
|
||||||
eb_get_batch_vma(struct eb_vmas *eb)
|
|
||||||
{
|
|
||||||
/* The batch is always the LAST item in the VMA list */
|
|
||||||
struct i915_vma *vma = list_last_entry(&eb->vmas, typeof(*vma), exec_list);
|
|
||||||
|
|
||||||
return vma;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct drm_i915_gem_object *
|
|
||||||
eb_get_batch(struct eb_vmas *eb)
|
|
||||||
{
|
|
||||||
struct i915_vma *vma = eb_get_batch_vma(eb);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SNA is doing fancy tricks with compressing batch buffers, which leads
|
|
||||||
* to negative relocation deltas. Usually that works out ok since the
|
|
||||||
* relocate address is still positive, except when the batch is placed
|
|
||||||
* very low in the GTT. Ensure this doesn't happen.
|
|
||||||
*
|
|
||||||
* Note that actual hangs have only been observed on gen7, but for
|
|
||||||
* paranoia do it everywhere.
|
|
||||||
*/
|
|
||||||
if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0)
|
|
||||||
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
|
||||||
|
|
||||||
return vma->obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
|
static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
|
||||||
{
|
{
|
||||||
if (eb->and < 0) {
|
if (eb->and < 0) {
|
||||||
@ -682,16 +672,16 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
|
|||||||
flags |= PIN_HIGH;
|
flags |= PIN_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = i915_gem_object_pin(obj, vma->vm,
|
ret = i915_vma_pin(vma,
|
||||||
entry->pad_to_size,
|
entry->pad_to_size,
|
||||||
entry->alignment,
|
entry->alignment,
|
||||||
flags);
|
flags);
|
||||||
if ((ret == -ENOSPC || ret == -E2BIG) &&
|
if ((ret == -ENOSPC || ret == -E2BIG) &&
|
||||||
only_mappable_for_reloc(entry->flags))
|
only_mappable_for_reloc(entry->flags))
|
||||||
ret = i915_gem_object_pin(obj, vma->vm,
|
ret = i915_vma_pin(vma,
|
||||||
entry->pad_to_size,
|
entry->pad_to_size,
|
||||||
entry->alignment,
|
entry->alignment,
|
||||||
flags & ~PIN_MAPPABLE);
|
flags & ~PIN_MAPPABLE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1252,11 +1242,11 @@ i915_reset_gen7_sol_offsets(struct drm_i915_gem_request *req)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drm_i915_gem_object*
|
static struct i915_vma*
|
||||||
i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
|
i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
|
||||||
struct drm_i915_gem_exec_object2 *shadow_exec_entry,
|
struct drm_i915_gem_exec_object2 *shadow_exec_entry,
|
||||||
struct eb_vmas *eb,
|
|
||||||
struct drm_i915_gem_object *batch_obj,
|
struct drm_i915_gem_object *batch_obj,
|
||||||
|
struct eb_vmas *eb,
|
||||||
u32 batch_start_offset,
|
u32 batch_start_offset,
|
||||||
u32 batch_len,
|
u32 batch_len,
|
||||||
bool is_master)
|
bool is_master)
|
||||||
@ -1268,7 +1258,7 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
|
|||||||
shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool,
|
shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool,
|
||||||
PAGE_ALIGN(batch_len));
|
PAGE_ALIGN(batch_len));
|
||||||
if (IS_ERR(shadow_batch_obj))
|
if (IS_ERR(shadow_batch_obj))
|
||||||
return shadow_batch_obj;
|
return ERR_CAST(shadow_batch_obj);
|
||||||
|
|
||||||
ret = intel_engine_cmd_parser(engine,
|
ret = intel_engine_cmd_parser(engine,
|
||||||
batch_obj,
|
batch_obj,
|
||||||
@ -1293,14 +1283,12 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
|
|||||||
i915_gem_object_get(shadow_batch_obj);
|
i915_gem_object_get(shadow_batch_obj);
|
||||||
list_add_tail(&vma->exec_list, &eb->vmas);
|
list_add_tail(&vma->exec_list, &eb->vmas);
|
||||||
|
|
||||||
shadow_batch_obj->base.pending_read_domains = I915_GEM_DOMAIN_COMMAND;
|
return vma;
|
||||||
|
|
||||||
return shadow_batch_obj;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
i915_gem_object_unpin_pages(shadow_batch_obj);
|
i915_gem_object_unpin_pages(shadow_batch_obj);
|
||||||
if (ret == -EACCES) /* unhandled chained batch */
|
if (ret == -EACCES) /* unhandled chained batch */
|
||||||
return batch_obj;
|
return NULL;
|
||||||
else
|
else
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
@ -1381,11 +1369,11 @@ execbuf_submit(struct i915_execbuffer_params *params,
|
|||||||
}
|
}
|
||||||
|
|
||||||
exec_len = args->batch_len;
|
exec_len = args->batch_len;
|
||||||
exec_start = params->batch_obj_vm_offset +
|
exec_start = params->batch->node.start +
|
||||||
params->args_batch_start_offset;
|
params->args_batch_start_offset;
|
||||||
|
|
||||||
if (exec_len == 0)
|
if (exec_len == 0)
|
||||||
exec_len = params->batch_obj->base.size;
|
exec_len = params->batch->size;
|
||||||
|
|
||||||
ret = params->engine->emit_bb_start(params->request,
|
ret = params->engine->emit_bb_start(params->request,
|
||||||
exec_start, exec_len,
|
exec_start, exec_len,
|
||||||
@ -1489,7 +1477,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||||
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
||||||
struct eb_vmas *eb;
|
struct eb_vmas *eb;
|
||||||
struct drm_i915_gem_object *batch_obj;
|
|
||||||
struct drm_i915_gem_exec_object2 shadow_exec_entry;
|
struct drm_i915_gem_exec_object2 shadow_exec_entry;
|
||||||
struct intel_engine_cs *engine;
|
struct intel_engine_cs *engine;
|
||||||
struct i915_gem_context *ctx;
|
struct i915_gem_context *ctx;
|
||||||
@ -1583,7 +1570,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* take note of the batch buffer before we might reorder the lists */
|
/* take note of the batch buffer before we might reorder the lists */
|
||||||
batch_obj = eb_get_batch(eb);
|
params->batch = eb_get_batch(eb);
|
||||||
|
|
||||||
/* Move the objects en-masse into the GTT, evicting if necessary. */
|
/* Move the objects en-masse into the GTT, evicting if necessary. */
|
||||||
need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
|
need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
|
||||||
@ -1607,7 +1594,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set the pending read domains for the batch buffer to COMMAND */
|
/* Set the pending read domains for the batch buffer to COMMAND */
|
||||||
if (batch_obj->base.pending_write_domain) {
|
if (params->batch->obj->base.pending_write_domain) {
|
||||||
DRM_DEBUG("Attempting to use self-modifying batch buffer\n");
|
DRM_DEBUG("Attempting to use self-modifying batch buffer\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
@ -1615,26 +1602,20 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
params->args_batch_start_offset = args->batch_start_offset;
|
params->args_batch_start_offset = args->batch_start_offset;
|
||||||
if (intel_engine_needs_cmd_parser(engine) && args->batch_len) {
|
if (intel_engine_needs_cmd_parser(engine) && args->batch_len) {
|
||||||
struct drm_i915_gem_object *parsed_batch_obj;
|
struct i915_vma *vma;
|
||||||
|
|
||||||
parsed_batch_obj = i915_gem_execbuffer_parse(engine,
|
vma = i915_gem_execbuffer_parse(engine, &shadow_exec_entry,
|
||||||
&shadow_exec_entry,
|
params->batch->obj,
|
||||||
eb,
|
eb,
|
||||||
batch_obj,
|
args->batch_start_offset,
|
||||||
args->batch_start_offset,
|
args->batch_len,
|
||||||
args->batch_len,
|
drm_is_current_master(file));
|
||||||
drm_is_current_master(file));
|
if (IS_ERR(vma)) {
|
||||||
if (IS_ERR(parsed_batch_obj)) {
|
ret = PTR_ERR(vma);
|
||||||
ret = PTR_ERR(parsed_batch_obj);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (vma) {
|
||||||
* parsed_batch_obj == batch_obj means batch not fully parsed:
|
|
||||||
* Accept, but don't promote to secure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (parsed_batch_obj != batch_obj) {
|
|
||||||
/*
|
/*
|
||||||
* Batch parsed and accepted:
|
* Batch parsed and accepted:
|
||||||
*
|
*
|
||||||
@ -1646,16 +1627,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
*/
|
*/
|
||||||
dispatch_flags |= I915_DISPATCH_SECURE;
|
dispatch_flags |= I915_DISPATCH_SECURE;
|
||||||
params->args_batch_start_offset = 0;
|
params->args_batch_start_offset = 0;
|
||||||
batch_obj = parsed_batch_obj;
|
params->batch = vma;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
|
params->batch->obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
|
||||||
|
|
||||||
/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
|
/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
|
||||||
* batch" bit. Hence we need to pin secure batches into the global gtt.
|
* batch" bit. Hence we need to pin secure batches into the global gtt.
|
||||||
* hsw should have this fixed, but bdw mucks it up again. */
|
* hsw should have this fixed, but bdw mucks it up again. */
|
||||||
if (dispatch_flags & I915_DISPATCH_SECURE) {
|
if (dispatch_flags & I915_DISPATCH_SECURE) {
|
||||||
|
struct drm_i915_gem_object *obj = params->batch->obj;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* So on first glance it looks freaky that we pin the batch here
|
* So on first glance it looks freaky that we pin the batch here
|
||||||
* outside of the reservation loop. But:
|
* outside of the reservation loop. But:
|
||||||
@ -1666,13 +1649,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
* fitting due to fragmentation.
|
* fitting due to fragmentation.
|
||||||
* So this is actually safe.
|
* So this is actually safe.
|
||||||
*/
|
*/
|
||||||
ret = i915_gem_obj_ggtt_pin(batch_obj, 0, 0);
|
ret = i915_gem_obj_ggtt_pin(obj, 0, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
params->batch_obj_vm_offset = i915_gem_obj_ggtt_offset(batch_obj);
|
params->batch = i915_gem_obj_to_ggtt(obj);
|
||||||
} else
|
}
|
||||||
params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm);
|
|
||||||
|
|
||||||
/* Allocate a request for this batch buffer nice and early. */
|
/* Allocate a request for this batch buffer nice and early. */
|
||||||
params->request = i915_gem_request_alloc(engine, ctx);
|
params->request = i915_gem_request_alloc(engine, ctx);
|
||||||
@ -1695,12 +1677,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|||||||
params->file = file;
|
params->file = file;
|
||||||
params->engine = engine;
|
params->engine = engine;
|
||||||
params->dispatch_flags = dispatch_flags;
|
params->dispatch_flags = dispatch_flags;
|
||||||
params->batch_obj = batch_obj;
|
|
||||||
params->ctx = ctx;
|
params->ctx = ctx;
|
||||||
|
|
||||||
ret = execbuf_submit(params, args, &eb->vmas);
|
ret = execbuf_submit(params, args, &eb->vmas);
|
||||||
err_request:
|
err_request:
|
||||||
__i915_add_request(params->request, params->batch_obj, ret == 0);
|
__i915_add_request(params->request, params->batch->obj, ret == 0);
|
||||||
|
|
||||||
err_batch_unpin:
|
err_batch_unpin:
|
||||||
/*
|
/*
|
||||||
@ -1710,8 +1691,7 @@ err_batch_unpin:
|
|||||||
* active.
|
* active.
|
||||||
*/
|
*/
|
||||||
if (dispatch_flags & I915_DISPATCH_SECURE)
|
if (dispatch_flags & I915_DISPATCH_SECURE)
|
||||||
i915_gem_object_ggtt_unpin(batch_obj);
|
i915_vma_unpin(params->batch);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
/* the request owns the ref now */
|
/* the request owns the ref now */
|
||||||
i915_gem_context_put(ctx);
|
i915_gem_context_put(ctx);
|
||||||
|
@ -3665,13 +3665,10 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (vma->bound == 0 && vma->vm->allocate_va_range) {
|
if (vma->bound == 0 && vma->vm->allocate_va_range) {
|
||||||
/* XXX: i915_vma_pin() will fix this +- hack */
|
|
||||||
__i915_vma_pin(vma);
|
|
||||||
trace_i915_va_alloc(vma);
|
trace_i915_va_alloc(vma);
|
||||||
ret = vma->vm->allocate_va_range(vma->vm,
|
ret = vma->vm->allocate_va_range(vma->vm,
|
||||||
vma->node.start,
|
vma->node.start,
|
||||||
vma->node.size);
|
vma->node.size);
|
||||||
__i915_vma_unpin(vma);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -609,6 +609,20 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __must_check
|
||||||
|
i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags);
|
||||||
|
/* Flags used by pin/bind&friends. */
|
||||||
|
#define PIN_MAPPABLE BIT(0)
|
||||||
|
#define PIN_NONBLOCK BIT(1)
|
||||||
|
#define PIN_GLOBAL BIT(2)
|
||||||
|
#define PIN_OFFSET_BIAS BIT(3)
|
||||||
|
#define PIN_USER BIT(4)
|
||||||
|
#define PIN_UPDATE BIT(5)
|
||||||
|
#define PIN_ZONE_4G BIT(6)
|
||||||
|
#define PIN_HIGH BIT(7)
|
||||||
|
#define PIN_OFFSET_FIXED BIT(8)
|
||||||
|
#define PIN_OFFSET_MASK (~4095)
|
||||||
|
|
||||||
static inline int i915_vma_pin_count(const struct i915_vma *vma)
|
static inline int i915_vma_pin_count(const struct i915_vma *vma)
|
||||||
{
|
{
|
||||||
return vma->pin_count;
|
return vma->pin_count;
|
||||||
|
Loading…
Reference in New Issue
Block a user