drivers/gpu/drm/xe/xe_shrinker.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_shrinker.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_shrinker.c
Extension
.c
Size
8215 bytes
Lines
307
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source 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 xe_shrinker {
	struct xe_device *xe;
	rwlock_t lock;
	long shrinkable_pages;
	long purgeable_pages;
	struct shrinker *shrink;
	struct work_struct pm_worker;
};

static struct xe_shrinker *to_xe_shrinker(struct shrinker *shrink)
{
	return shrink->private_data;
}

/**
 * xe_shrinker_mod_pages() - Modify shrinker page accounting
 * @shrinker: Pointer to the struct xe_shrinker.
 * @shrinkable: Shrinkable pages delta. May be negative.
 * @purgeable: Purgeable page delta. May be negative.
 *
 * Modifies the shrinkable and purgeable pages accounting.
 */
void
xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgeable)
{
	write_lock(&shrinker->lock);
	shrinker->shrinkable_pages += shrinkable;
	shrinker->purgeable_pages += purgeable;
	write_unlock(&shrinker->lock);
}

static s64 __xe_shrinker_walk(struct xe_device *xe,
			      struct ttm_operation_ctx *ctx,
			      const struct xe_bo_shrink_flags flags,
			      unsigned long to_scan, unsigned long *scanned)
{
	unsigned int mem_type;
	s64 freed = 0, lret;

	for (mem_type = XE_PL_SYSTEM; mem_type <= XE_PL_TT; ++mem_type) {
		struct ttm_resource_manager *man = ttm_manager_type(&xe->ttm, mem_type);
		struct ttm_bo_lru_cursor curs;
		struct ttm_buffer_object *ttm_bo;
		struct ttm_lru_walk_arg arg = {
			.ctx = ctx,
			.trylock_only = true,
		};

		if (!man || !man->use_tt)
			continue;

		ttm_bo_lru_for_each_reserved_guarded(&curs, man, &arg, ttm_bo) {
			if (!ttm_bo_shrink_suitable(ttm_bo, ctx))
				continue;

			lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
			if (lret < 0)
				return lret;

			freed += lret;
			if (*scanned >= to_scan)
				break;
		}
		/* Trylocks should never error, just fail. */
		xe_assert(xe, !IS_ERR(ttm_bo));
	}

	return freed;
}

/*
 * Try shrinking idle objects without writeback first, then if not sufficient,
 * try also non-idle objects and finally if that's not sufficient either,
 * add writeback. This avoids stalls and explicit writebacks with light or
 * moderate memory pressure.
 */
static s64 xe_shrinker_walk(struct xe_device *xe,
			    struct ttm_operation_ctx *ctx,
			    const struct xe_bo_shrink_flags flags,
			    unsigned long to_scan, unsigned long *scanned)
{
	bool no_wait_gpu = true;
	struct xe_bo_shrink_flags save_flags = flags;
	s64 lret, freed;

	swap(no_wait_gpu, ctx->no_wait_gpu);
	save_flags.writeback = false;
	lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned);
	swap(no_wait_gpu, ctx->no_wait_gpu);
	if (lret < 0 || *scanned >= to_scan)

Annotation

Implementation Notes