if (new_use_tt) { /* Zero init the new TTM structure if the old location should *haveusedoneaswell.
*/
ret = ttm_tt_create(bo, old_use_tt); if (ret) goto out_err;
if (mem->mem_type != TTM_PL_SYSTEM) {
ret = ttm_bo_populate(bo, ctx); if (ret) goto out_err;
}
}
ret = dma_resv_reserve_fences(bo->base.resv, 1); if (ret) goto out_err;
ret = bdev->funcs->move(bo, evict, ctx, mem, hop); if (ret) { if (ret == -EMULTIHOP) return ret; goto out_err;
}
staticint ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
{ int r;
if (bo->base.resv == &bo->base._resv) return0;
BUG_ON(!dma_resv_trylock(&bo->base._resv));
r = dma_resv_copy_fences(&bo->base._resv, bo->base.resv);
dma_resv_unlock(&bo->base._resv); if (r) return r;
if (bo->type != ttm_bo_type_sg) { /* This works because the BO is about to be destroyed and nobody *referenceitanymore.Theonlytrickycaseisthetrylockon *theresvobjectwhileholdingthelru_lock.
*/
spin_lock(&bo->bdev->lru_lock);
bo->base.resv = &bo->base._resv;
spin_unlock(&bo->bdev->lru_lock);
}
if (!bo->deleted) {
ret = ttm_bo_individualize_resv(bo); if (ret) { /* Last resort, if we fail to allocate memory for the *fencesblockfortheBOtobecomeidle
*/
dma_resv_wait_timeout(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP, false, 30 * HZ);
}
if (bo->bdev->funcs->release_notify)
bo->bdev->funcs->release_notify(bo);
if (!dma_resv_test_signaled(&bo->base._resv,
DMA_RESV_USAGE_BOOKKEEP) ||
(want_init_on_free() && (bo->ttm != NULL)) ||
bo->type == ttm_bo_type_sg ||
!dma_resv_trylock(bo->base.resv)) { /* The BO is not idle, resurrect it for delayed destroy */
ttm_bo_flush_all_fences(bo);
bo->deleted = true;
/* Schedule the worker on the closest NUMA node. This *improvesperformancesincesystemmemorymightbe *clearedonfreeandthatisbestdoneonaCPUcore *closetoit.
*/
queue_work_node(bdev->pool.nid, bdev->wq, &bo->delayed_delete); return;
}
/* find space in the bounce domain */
ret = ttm_bo_mem_space(bo, &hop_placement, &hop_mem, ctx); if (ret) return ret; /* move to the bounce domain */
ret = ttm_bo_handle_move_mem(bo, hop_mem, false, ctx, NULL); if (ret) {
ttm_resource_free(bo, &hop_mem); return ret;
} return0;
}
ret = ttm_bo_mem_space(bo, &placement, &evict_mem, ctx); if (ret) { if (ret != -ERESTARTSYS) {
pr_err("Failed to find memory space for buffer 0x%p eviction\n",
bo);
ttm_bo_mem_space_debug(bo, &placement);
} goto out;
}
do {
ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop); if (ret != -EMULTIHOP) break;
ret = ttm_bo_bounce_temp_buffer(bo, ctx, &hop);
} while (!ret);
if (ret) {
ttm_resource_free(bo, &evict_mem); if (ret != -ERESTARTSYS && ret != -EINTR)
pr_err("Buffer eviction failed\n");
}
out: return ret;
}
dma_resv_assert_held(bo->base.resv); if (bo->resource->mem_type == TTM_PL_SYSTEM) returntrue;
/* Don't evict this BO if it's outside of the *requestedplacementrange
*/ return ttm_resource_intersects(bdev, res, place, bo->base.size);
}
EXPORT_SYMBOL(ttm_bo_eviction_valuable);
/** *structttm_bo_evict_walk-Parametersfortheevictwalk.
*/ struct ttm_bo_evict_walk { /** @walk: The walk base parameters. */ struct ttm_lru_walk walk; /** @place: The place passed to the resource allocation. */ conststruct ttm_place *place; /** @evictor: The buffer object we're trying to make room for. */ struct ttm_buffer_object *evictor; /** @res: The allocated resource if any. */ struct ttm_resource **res; /** @evicted: Number of successful evictions. */ unsignedlong evicted;
/** @limit_pool: Which pool limit we should test against */ struct dmem_cgroup_pool_state *limit_pool; /** @try_low: Whether we should attempt to evict BO's with low watermark threshold */ bool try_low; /** @hit_low: If we cannot evict a bo when @try_low is false (first pass) */ bool hit_low;
};
if (!dmem_cgroup_state_evict_valuable(evict_walk->limit_pool, bo->resource->css,
evict_walk->try_low, &evict_walk->hit_low)) return0;
if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, evict_walk->place)) return0;
if (bo->deleted) {
lret = ttm_bo_wait_ctx(bo, walk->arg.ctx); if (!lret)
ttm_bo_cleanup_memtype_use(bo);
} else {
lret = ttm_bo_evict(bo, walk->arg.ctx);
}
if (lret) goto out;
evict_walk->evicted++; if (evict_walk->res)
lret = ttm_resource_alloc(evict_walk->evictor, evict_walk->place,
evict_walk->res, NULL); if (lret == 0) return1;
out: /* Errors that should terminate the walk. */ if (lret == -ENOSPC) return -EBUSY;
/* One more attempt if we hit low limit? */ if (!lret && evict_walk.hit_low) {
evict_walk.try_low = true;
lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1);
} if (lret || !ticket) goto out;
/* Reset low limit */
evict_walk.try_low = evict_walk.hit_low = false; /* If ticket-locking, repeat while making progress. */
evict_walk.walk.arg.trylock_only = false;
retry: do { /* The walk may clear the evict_walk.walk.ticket field */
evict_walk.walk.arg.ticket = ticket;
evict_walk.evicted = 0;
lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1);
} while (!lret && evict_walk.evicted);
/* We hit the low limit? Try once more */ if (!lret && evict_walk.hit_low && !evict_walk.try_low) {
evict_walk.try_low = true; goto retry;
}
out: if (lret < 0) return lret; if (lret == 0) return -EBUSY; return0;
}
/* *Removethebackingstoreifnoplacementisgiven.
*/ if (!placement->num_placement) return ttm_bo_pipeline_gutting(bo);
force_space = false; do { /* Check whether we need to move buffer. */ if (bo->resource &&
ttm_resource_compatible(bo->resource, placement,
force_space)) return0;
/* Moving of pinned BOs is forbidden */ if (bo->pin_count) return -EINVAL;
/* *Determinewheretomovethebuffer. * *Ifdriverdeterminesmoveisgoingtoneed *anextrastepthenitwillreturn-EMULTIHOP *andthebufferwillbemovedtothetemporary *stopandthedriverwillbecalledtomake *thesecondhop.
*/
ret = ttm_bo_alloc_resource(bo, placement, ctx, force_space,
&res);
force_space = !force_space; if (ret == -ENOSPC) continue; if (ret) return ret;
bounce:
ret = ttm_bo_handle_move_mem(bo, res, false, ctx, &hop); if (ret == -EMULTIHOP) {
ret = ttm_bo_bounce_temp_buffer(bo, ctx, &hop); /* try and move to final place now. */ if (!ret) goto bounce;
} if (ret) {
ttm_resource_free(bo, &res); return ret;
}
} while (ret && force_space);
/* For backward compatibility with userspace */ if (ret == -ENOSPC) return -ENOMEM;
/* *WemightneedtoaddaTTM.
*/ if (!bo->resource || bo->resource->mem_type == TTM_PL_SYSTEM) {
ret = ttm_tt_create(bo, true); if (ret) return ret;
} return0;
}
EXPORT_SYMBOL(ttm_bo_validate);
/* *Forttm_bo_type_devicebuffers,allocate *addressspacefromthedevice.
*/ if (bo->type == ttm_bo_type_device || bo->type == ttm_bo_type_sg) {
ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node,
PFN_UP(bo->base.size)); if (ret) goto err_put;
}
/* passed reservation objects should already be locked, *sinceotherwiselockdepwillbeangeredinradeon.
*/ if (!resv)
WARN_ON(!dma_resv_trylock(bo->base.resv)); else
dma_resv_assert_held(resv);
ret = ttm_bo_validate(bo, placement, ctx); if (unlikely(ret)) goto err_unlock;
return0;
err_unlock: if (!resv)
dma_resv_unlock(bo->base.resv);
/** *ttm_bo_wait_ctx-waitforbufferidle. * *@bo:Thebufferobject. *@ctx:defineshowtowait * *Waitsforthebuffertobeidle.Usedtimeoutdependsonthecontext. *Returns-EBUSYifwaittimedoutt,-ERESTARTSYSifinterruptedbyasignalor *zeroonsuccess.
*/ int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx)
{ long ret;
if (ctx->no_wait_gpu) { if (dma_resv_test_signaled(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP)) return0; else return -EBUSY;
}
ret = dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP,
ctx->interruptible, 15 * HZ); if (unlikely(ret < 0)) return ret; if (unlikely(ret == 0)) return -EBUSY; return0;
}
EXPORT_SYMBOL(ttm_bo_wait_ctx);
/** *structttm_bo_swapout_walk-Parametersfortheswapoutwalk
*/ struct ttm_bo_swapout_walk { /** @walk: The walk base parameters. */ struct ttm_lru_walk walk; /** @gfp_flags: The gfp flags to use for ttm_tt_swapout() */
gfp_t gfp_flags; /** @hit_low: Whether we should attempt to swap BO's with low watermark threshold */ /** @evict_low: If we cannot swap a bo when @try_low is false (first pass) */ bool hit_low, evict_low;
};
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.29Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.