drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c
Extension
.c
Size
5865 bytes
Lines
250
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

if (spin_trylock_irq(&pool->lock)) {
			struct list_head *pos;

			/* Most recent at head; oldest at tail */
			list_for_each_prev(pos, list) {
				unsigned long age;

				node = list_entry(pos, typeof(*node), link);

				age = READ_ONCE(node->age);
				if (!age || jiffies - age < keep)
					break;

				/* Check we are the first to claim this node */
				if (!xchg(&node->age, 0))
					break;

				node->free = stale;
				stale = node;
			}
			if (!list_is_last(pos, list))
				__list_del_many(pos, list);

			spin_unlock_irq(&pool->lock);
		}

		active |= !list_empty(list);
	}

	while ((node = stale)) {
		stale = stale->free;
		node_free(node);
	}

	return active;
}

static void pool_free_work(struct work_struct *wrk)
{
	struct intel_gt_buffer_pool *pool =
		container_of(wrk, typeof(*pool), work.work);
	struct intel_gt *gt = container_of(pool, struct intel_gt, buffer_pool);

	if (pool_free_older_than(pool, HZ))
		queue_delayed_work(gt->i915->unordered_wq, &pool->work,
				   round_jiffies_up_relative(HZ));
}

static void pool_retire(struct i915_active *ref)
{
	struct intel_gt_buffer_pool_node *node =
		container_of(ref, typeof(*node), active);
	struct intel_gt_buffer_pool *pool = node->pool;
	struct intel_gt *gt = container_of(pool, struct intel_gt, buffer_pool);
	struct list_head *list = bucket_for_size(pool, node->obj->base.size);
	unsigned long flags;

	if (node->pinned) {
		i915_gem_object_unpin_pages(node->obj);

		/* Return this object to the shrinker pool */
		i915_gem_object_make_purgeable(node->obj);
		node->pinned = false;
	}

	GEM_BUG_ON(node->age);
	spin_lock_irqsave(&pool->lock, flags);
	list_add_rcu(&node->link, list);
	WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */
	spin_unlock_irqrestore(&pool->lock, flags);

	queue_delayed_work(gt->i915->unordered_wq, &pool->work,
			   round_jiffies_up_relative(HZ));
}

void intel_gt_buffer_pool_mark_used(struct intel_gt_buffer_pool_node *node)
{
	assert_object_held(node->obj);

	if (node->pinned)
		return;

	__i915_gem_object_pin_pages(node->obj);
	/* Hide this pinned object from the shrinker until retired */
	i915_gem_object_make_unshrinkable(node->obj);
	node->pinned = true;
}

static struct intel_gt_buffer_pool_node *
node_create(struct intel_gt_buffer_pool *pool, size_t sz,

Annotation

Implementation Notes