|
|
|
|
@@ -440,7 +440,7 @@ eb_pin_vma(struct i915_execbuffer *eb,
|
|
|
|
|
else
|
|
|
|
|
pin_flags = entry->offset & PIN_OFFSET_MASK;
|
|
|
|
|
|
|
|
|
|
pin_flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED;
|
|
|
|
|
pin_flags |= PIN_USER | PIN_NOEVICT | PIN_OFFSET_FIXED | PIN_VALIDATE;
|
|
|
|
|
if (unlikely(ev->flags & EXEC_OBJECT_NEEDS_GTT))
|
|
|
|
|
pin_flags |= PIN_GLOBAL;
|
|
|
|
|
|
|
|
|
|
@@ -458,17 +458,15 @@ eb_pin_vma(struct i915_execbuffer *eb,
|
|
|
|
|
entry->pad_to_size,
|
|
|
|
|
entry->alignment,
|
|
|
|
|
eb_pin_flags(entry, ev->flags) |
|
|
|
|
|
PIN_USER | PIN_NOEVICT);
|
|
|
|
|
PIN_USER | PIN_NOEVICT | PIN_VALIDATE);
|
|
|
|
|
if (unlikely(err))
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unlikely(ev->flags & EXEC_OBJECT_NEEDS_FENCE)) {
|
|
|
|
|
err = i915_vma_pin_fence(vma);
|
|
|
|
|
if (unlikely(err)) {
|
|
|
|
|
i915_vma_unpin(vma);
|
|
|
|
|
if (unlikely(err))
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vma->fence)
|
|
|
|
|
ev->flags |= __EXEC_OBJECT_HAS_FENCE;
|
|
|
|
|
@@ -484,13 +482,9 @@ eb_pin_vma(struct i915_execbuffer *eb,
|
|
|
|
|
static inline void
|
|
|
|
|
eb_unreserve_vma(struct eb_vma *ev)
|
|
|
|
|
{
|
|
|
|
|
if (!(ev->flags & __EXEC_OBJECT_HAS_PIN))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (unlikely(ev->flags & __EXEC_OBJECT_HAS_FENCE))
|
|
|
|
|
__i915_vma_unpin_fence(ev->vma);
|
|
|
|
|
|
|
|
|
|
__i915_vma_unpin(ev->vma);
|
|
|
|
|
ev->flags &= ~__EXEC_OBJECT_RESERVED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -672,10 +666,8 @@ static int eb_reserve_vma(struct i915_execbuffer *eb,
|
|
|
|
|
|
|
|
|
|
if (unlikely(ev->flags & EXEC_OBJECT_NEEDS_FENCE)) {
|
|
|
|
|
err = i915_vma_pin_fence(vma);
|
|
|
|
|
if (unlikely(err)) {
|
|
|
|
|
i915_vma_unpin(vma);
|
|
|
|
|
if (unlikely(err))
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vma->fence)
|
|
|
|
|
ev->flags |= __EXEC_OBJECT_HAS_FENCE;
|
|
|
|
|
@@ -687,85 +679,95 @@ static int eb_reserve_vma(struct i915_execbuffer *eb,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_reserve(struct i915_execbuffer *eb)
|
|
|
|
|
static bool eb_unbind(struct i915_execbuffer *eb, bool force)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int count = eb->buffer_count;
|
|
|
|
|
unsigned int pin_flags = PIN_USER | PIN_NONBLOCK;
|
|
|
|
|
unsigned int i;
|
|
|
|
|
struct list_head last;
|
|
|
|
|
bool unpinned = false;
|
|
|
|
|
|
|
|
|
|
/* Resort *all* the objects into priority order */
|
|
|
|
|
INIT_LIST_HEAD(&eb->unbound);
|
|
|
|
|
INIT_LIST_HEAD(&last);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
struct eb_vma *ev = &eb->vma[i];
|
|
|
|
|
unsigned int flags = ev->flags;
|
|
|
|
|
|
|
|
|
|
if (!force && flags & EXEC_OBJECT_PINNED &&
|
|
|
|
|
flags & __EXEC_OBJECT_HAS_PIN)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
unpinned = true;
|
|
|
|
|
eb_unreserve_vma(ev);
|
|
|
|
|
|
|
|
|
|
if (flags & EXEC_OBJECT_PINNED)
|
|
|
|
|
/* Pinned must have their slot */
|
|
|
|
|
list_add(&ev->bind_link, &eb->unbound);
|
|
|
|
|
else if (flags & __EXEC_OBJECT_NEEDS_MAP)
|
|
|
|
|
/* Map require the lowest 256MiB (aperture) */
|
|
|
|
|
list_add_tail(&ev->bind_link, &eb->unbound);
|
|
|
|
|
else if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
|
|
|
|
|
/* Prioritise 4GiB region for restricted bo */
|
|
|
|
|
list_add(&ev->bind_link, &last);
|
|
|
|
|
else
|
|
|
|
|
list_add_tail(&ev->bind_link, &last);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_splice_tail(&last, &eb->unbound);
|
|
|
|
|
return unpinned;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_reserve(struct i915_execbuffer *eb)
|
|
|
|
|
{
|
|
|
|
|
struct eb_vma *ev;
|
|
|
|
|
unsigned int i, pass;
|
|
|
|
|
unsigned int pass;
|
|
|
|
|
int err = 0;
|
|
|
|
|
bool unpinned;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Attempt to pin all of the buffers into the GTT.
|
|
|
|
|
* This is done in 3 phases:
|
|
|
|
|
* This is done in 2 phases:
|
|
|
|
|
*
|
|
|
|
|
* 1a. Unbind all objects that do not match the GTT constraints for
|
|
|
|
|
* the execbuffer (fenceable, mappable, alignment etc).
|
|
|
|
|
* 1b. Increment pin count for already bound objects.
|
|
|
|
|
* 2. Bind new objects.
|
|
|
|
|
* 3. Decrement pin count.
|
|
|
|
|
* 1. Unbind all objects that do not match the GTT constraints for
|
|
|
|
|
* the execbuffer (fenceable, mappable, alignment etc).
|
|
|
|
|
* 2. Bind new objects.
|
|
|
|
|
*
|
|
|
|
|
* This avoid unnecessary unbinding of later objects in order to make
|
|
|
|
|
* room for the earlier objects *unless* we need to defragment.
|
|
|
|
|
*
|
|
|
|
|
* Defragmenting is skipped if all objects are pinned at a fixed location.
|
|
|
|
|
*/
|
|
|
|
|
pass = 0;
|
|
|
|
|
do {
|
|
|
|
|
for (pass = 0; pass <= 2; pass++) {
|
|
|
|
|
int pin_flags = PIN_USER | PIN_VALIDATE;
|
|
|
|
|
|
|
|
|
|
if (pass == 0)
|
|
|
|
|
pin_flags |= PIN_NONBLOCK;
|
|
|
|
|
|
|
|
|
|
if (pass >= 1)
|
|
|
|
|
unpinned = eb_unbind(eb, pass == 2);
|
|
|
|
|
|
|
|
|
|
if (pass == 2) {
|
|
|
|
|
err = mutex_lock_interruptible(&eb->context->vm->mutex);
|
|
|
|
|
if (!err) {
|
|
|
|
|
err = i915_gem_evict_vm(eb->context->vm, &eb->ww);
|
|
|
|
|
mutex_unlock(&eb->context->vm->mutex);
|
|
|
|
|
}
|
|
|
|
|
if (err)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_for_each_entry(ev, &eb->unbound, bind_link) {
|
|
|
|
|
err = eb_reserve_vma(eb, ev, pin_flags);
|
|
|
|
|
if (err)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (err != -ENOSPC)
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
/* Resort *all* the objects into priority order */
|
|
|
|
|
INIT_LIST_HEAD(&eb->unbound);
|
|
|
|
|
INIT_LIST_HEAD(&last);
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
|
unsigned int flags;
|
|
|
|
|
|
|
|
|
|
ev = &eb->vma[i];
|
|
|
|
|
flags = ev->flags;
|
|
|
|
|
if (flags & EXEC_OBJECT_PINNED &&
|
|
|
|
|
flags & __EXEC_OBJECT_HAS_PIN)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
eb_unreserve_vma(ev);
|
|
|
|
|
|
|
|
|
|
if (flags & EXEC_OBJECT_PINNED)
|
|
|
|
|
/* Pinned must have their slot */
|
|
|
|
|
list_add(&ev->bind_link, &eb->unbound);
|
|
|
|
|
else if (flags & __EXEC_OBJECT_NEEDS_MAP)
|
|
|
|
|
/* Map require the lowest 256MiB (aperture) */
|
|
|
|
|
list_add_tail(&ev->bind_link, &eb->unbound);
|
|
|
|
|
else if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
|
|
|
|
|
/* Prioritise 4GiB region for restricted bo */
|
|
|
|
|
list_add(&ev->bind_link, &last);
|
|
|
|
|
else
|
|
|
|
|
list_add_tail(&ev->bind_link, &last);
|
|
|
|
|
}
|
|
|
|
|
list_splice_tail(&last, &eb->unbound);
|
|
|
|
|
|
|
|
|
|
switch (pass++) {
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
/* Too fragmented, unbind everything and retry */
|
|
|
|
|
mutex_lock(&eb->context->vm->mutex);
|
|
|
|
|
err = i915_gem_evict_vm(eb->context->vm, &eb->ww);
|
|
|
|
|
mutex_unlock(&eb->context->vm->mutex);
|
|
|
|
|
if (err)
|
|
|
|
|
return err;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return -ENOSPC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pin_flags = PIN_USER;
|
|
|
|
|
} while (1);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_select_context(struct i915_execbuffer *eb)
|
|
|
|
|
@@ -1213,10 +1215,11 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj,
|
|
|
|
|
return vaddr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *reloc_iomap(struct drm_i915_gem_object *obj,
|
|
|
|
|
static void *reloc_iomap(struct i915_vma *batch,
|
|
|
|
|
struct i915_execbuffer *eb,
|
|
|
|
|
unsigned long page)
|
|
|
|
|
{
|
|
|
|
|
struct drm_i915_gem_object *obj = batch->obj;
|
|
|
|
|
struct reloc_cache *cache = &eb->reloc_cache;
|
|
|
|
|
struct i915_ggtt *ggtt = cache_to_ggtt(cache);
|
|
|
|
|
unsigned long offset;
|
|
|
|
|
@@ -1226,7 +1229,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
|
|
|
|
|
intel_gt_flush_ggtt_writes(ggtt->vm.gt);
|
|
|
|
|
io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr));
|
|
|
|
|
} else {
|
|
|
|
|
struct i915_vma *vma;
|
|
|
|
|
struct i915_vma *vma = ERR_PTR(-ENODEV);
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
if (i915_gem_object_is_tiled(obj))
|
|
|
|
|
@@ -1239,10 +1242,23 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
|
|
|
|
|
if (err)
|
|
|
|
|
return ERR_PTR(err);
|
|
|
|
|
|
|
|
|
|
vma = i915_gem_object_ggtt_pin_ww(obj, &eb->ww, NULL, 0, 0,
|
|
|
|
|
PIN_MAPPABLE |
|
|
|
|
|
PIN_NONBLOCK /* NOWARN */ |
|
|
|
|
|
PIN_NOEVICT);
|
|
|
|
|
/*
|
|
|
|
|
* i915_gem_object_ggtt_pin_ww may attempt to remove the batch
|
|
|
|
|
* VMA from the object list because we no longer pin.
|
|
|
|
|
*
|
|
|
|
|
* Only attempt to pin the batch buffer to ggtt if the current batch
|
|
|
|
|
* is not inside ggtt, or the batch buffer is not misplaced.
|
|
|
|
|
*/
|
|
|
|
|
if (!i915_is_ggtt(batch->vm)) {
|
|
|
|
|
vma = i915_gem_object_ggtt_pin_ww(obj, &eb->ww, NULL, 0, 0,
|
|
|
|
|
PIN_MAPPABLE |
|
|
|
|
|
PIN_NONBLOCK /* NOWARN */ |
|
|
|
|
|
PIN_NOEVICT);
|
|
|
|
|
} else if (i915_vma_is_map_and_fenceable(batch)) {
|
|
|
|
|
__i915_vma_pin(batch);
|
|
|
|
|
vma = batch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (vma == ERR_PTR(-EDEADLK))
|
|
|
|
|
return vma;
|
|
|
|
|
|
|
|
|
|
@@ -1280,7 +1296,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
|
|
|
|
|
return vaddr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *reloc_vaddr(struct drm_i915_gem_object *obj,
|
|
|
|
|
static void *reloc_vaddr(struct i915_vma *vma,
|
|
|
|
|
struct i915_execbuffer *eb,
|
|
|
|
|
unsigned long page)
|
|
|
|
|
{
|
|
|
|
|
@@ -1292,9 +1308,9 @@ static void *reloc_vaddr(struct drm_i915_gem_object *obj,
|
|
|
|
|
} else {
|
|
|
|
|
vaddr = NULL;
|
|
|
|
|
if ((cache->vaddr & KMAP) == 0)
|
|
|
|
|
vaddr = reloc_iomap(obj, eb, page);
|
|
|
|
|
vaddr = reloc_iomap(vma, eb, page);
|
|
|
|
|
if (!vaddr)
|
|
|
|
|
vaddr = reloc_kmap(obj, cache, page);
|
|
|
|
|
vaddr = reloc_kmap(vma->obj, cache, page);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return vaddr;
|
|
|
|
|
@@ -1335,7 +1351,7 @@ relocate_entry(struct i915_vma *vma,
|
|
|
|
|
void *vaddr;
|
|
|
|
|
|
|
|
|
|
repeat:
|
|
|
|
|
vaddr = reloc_vaddr(vma->obj, eb,
|
|
|
|
|
vaddr = reloc_vaddr(vma, eb,
|
|
|
|
|
offset >> PAGE_SHIFT);
|
|
|
|
|
if (IS_ERR(vaddr))
|
|
|
|
|
return PTR_ERR(vaddr);
|
|
|
|
|
@@ -2190,7 +2206,7 @@ shadow_batch_pin(struct i915_execbuffer *eb,
|
|
|
|
|
if (IS_ERR(vma))
|
|
|
|
|
return vma;
|
|
|
|
|
|
|
|
|
|
err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, flags);
|
|
|
|
|
err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, flags | PIN_VALIDATE);
|
|
|
|
|
if (err)
|
|
|
|
|
return ERR_PTR(err);
|
|
|
|
|
|
|
|
|
|
@@ -2204,7 +2220,7 @@ static struct i915_vma *eb_dispatch_secure(struct i915_execbuffer *eb, struct i9
|
|
|
|
|
* batch" bit. Hence we need to pin secure batches into the global gtt.
|
|
|
|
|
* hsw should have this fixed, but bdw mucks it up again. */
|
|
|
|
|
if (eb->batch_flags & I915_DISPATCH_SECURE)
|
|
|
|
|
return i915_gem_object_ggtt_pin_ww(vma->obj, &eb->ww, NULL, 0, 0, 0);
|
|
|
|
|
return i915_gem_object_ggtt_pin_ww(vma->obj, &eb->ww, NULL, 0, 0, PIN_VALIDATE);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
@@ -2255,13 +2271,12 @@ static int eb_parse(struct i915_execbuffer *eb)
|
|
|
|
|
|
|
|
|
|
err = i915_gem_object_lock(pool->obj, &eb->ww);
|
|
|
|
|
if (err)
|
|
|
|
|
goto err;
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
shadow = shadow_batch_pin(eb, pool->obj, eb->context->vm, PIN_USER);
|
|
|
|
|
if (IS_ERR(shadow)) {
|
|
|
|
|
err = PTR_ERR(shadow);
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
if (IS_ERR(shadow))
|
|
|
|
|
return PTR_ERR(shadow);
|
|
|
|
|
|
|
|
|
|
intel_gt_buffer_pool_mark_used(pool);
|
|
|
|
|
i915_gem_object_set_readonly(shadow->obj);
|
|
|
|
|
shadow->private = pool;
|
|
|
|
|
@@ -2273,25 +2288,21 @@ static int eb_parse(struct i915_execbuffer *eb)
|
|
|
|
|
shadow = shadow_batch_pin(eb, pool->obj,
|
|
|
|
|
&eb->gt->ggtt->vm,
|
|
|
|
|
PIN_GLOBAL);
|
|
|
|
|
if (IS_ERR(shadow)) {
|
|
|
|
|
err = PTR_ERR(shadow);
|
|
|
|
|
shadow = trampoline;
|
|
|
|
|
goto err_shadow;
|
|
|
|
|
}
|
|
|
|
|
if (IS_ERR(shadow))
|
|
|
|
|
return PTR_ERR(shadow);
|
|
|
|
|
|
|
|
|
|
shadow->private = pool;
|
|
|
|
|
|
|
|
|
|
eb->batch_flags |= I915_DISPATCH_SECURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
batch = eb_dispatch_secure(eb, shadow);
|
|
|
|
|
if (IS_ERR(batch)) {
|
|
|
|
|
err = PTR_ERR(batch);
|
|
|
|
|
goto err_trampoline;
|
|
|
|
|
}
|
|
|
|
|
if (IS_ERR(batch))
|
|
|
|
|
return PTR_ERR(batch);
|
|
|
|
|
|
|
|
|
|
err = dma_resv_reserve_shared(shadow->obj->base.resv, 1);
|
|
|
|
|
if (err)
|
|
|
|
|
goto err_trampoline;
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
err = intel_engine_cmd_parser(eb->context->engine,
|
|
|
|
|
eb->batches[0]->vma,
|
|
|
|
|
@@ -2299,7 +2310,7 @@ static int eb_parse(struct i915_execbuffer *eb)
|
|
|
|
|
eb->batch_len[0],
|
|
|
|
|
shadow, trampoline);
|
|
|
|
|
if (err)
|
|
|
|
|
goto err_unpin_batch;
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
eb->batches[0] = &eb->vma[eb->buffer_count++];
|
|
|
|
|
eb->batches[0]->vma = i915_vma_get(shadow);
|
|
|
|
|
@@ -2318,17 +2329,6 @@ secure_batch:
|
|
|
|
|
eb->batches[0]->vma = i915_vma_get(batch);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_unpin_batch:
|
|
|
|
|
if (batch)
|
|
|
|
|
i915_vma_unpin(batch);
|
|
|
|
|
err_trampoline:
|
|
|
|
|
if (trampoline)
|
|
|
|
|
i915_vma_unpin(trampoline);
|
|
|
|
|
err_shadow:
|
|
|
|
|
i915_vma_unpin(shadow);
|
|
|
|
|
err:
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int eb_request_submit(struct i915_execbuffer *eb,
|
|
|
|
|
@@ -3448,8 +3448,6 @@ err_request:
|
|
|
|
|
|
|
|
|
|
err_vma:
|
|
|
|
|
eb_release_vmas(&eb, true);
|
|
|
|
|
if (eb.trampoline)
|
|
|
|
|
i915_vma_unpin(eb.trampoline);
|
|
|
|
|
WARN_ON(err == -EDEADLK);
|
|
|
|
|
i915_gem_ww_ctx_fini(&eb.ww);
|
|
|
|
|
|
|
|
|
|
|