drivers/gpu/drm/ttm/ttm_bo.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/ttm/ttm_bo.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/ttm/ttm_bo.c
Extension
.c
Size
35021 bytes
Lines
1301
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ttm_bo_evict_walk {
	/** @walk: The walk base parameters. */
	struct ttm_lru_walk walk;
	/** @place: The place passed to the resource allocation. */
	const struct 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. */
	unsigned long 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;
};

static s64 ttm_bo_evict_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
{
	struct ttm_bo_evict_walk *evict_walk =
		container_of(walk, typeof(*evict_walk), walk);
	s64 lret;

	if (!dmem_cgroup_state_evict_valuable(evict_walk->limit_pool, bo->resource->css,
					      evict_walk->try_low, &evict_walk->hit_low))
		return 0;

	if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, evict_walk->place))
		return 0;

	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)
		return 1;
out:
	/* Errors that should terminate the walk. */
	if (lret == -ENOSPC)
		return -EBUSY;

	return lret;
}

static const struct ttm_lru_walk_ops ttm_evict_walk_ops = {
	.process_bo = ttm_bo_evict_cb,
};

static int ttm_bo_evict_alloc(struct ttm_device *bdev,
			      struct ttm_resource_manager *man,
			      const struct ttm_place *place,
			      struct ttm_buffer_object *evictor,
			      struct ttm_operation_ctx *ctx,
			      struct ww_acquire_ctx *ticket,
			      struct ttm_resource **res,
			      struct dmem_cgroup_pool_state *limit_pool)
{
	struct ttm_bo_evict_walk evict_walk = {
		.walk = {
			.ops = &ttm_evict_walk_ops,
			.arg = {
				.ctx = ctx,
				.ticket = ticket,
			}
		},
		.place = place,
		.evictor = evictor,
		.res = res,
		.limit_pool = limit_pool,
	};
	s64 lret;

	evict_walk.walk.arg.trylock_only = true;
	lret = ttm_lru_walk_for_evict(&evict_walk.walk, bdev, man, 1);

	/* One more attempt if we hit low limit? */

Annotation

Implementation Notes