drivers/gpu/drm/ttm/ttm_range_manager.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/ttm/ttm_range_manager.c
Extension
.c
Size
6785 bytes
Lines
243
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_range_manager {
	struct ttm_resource_manager manager;
	struct drm_mm mm;
	spinlock_t lock;
};

static inline struct ttm_range_manager *
to_range_manager(struct ttm_resource_manager *man)
{
	return container_of(man, struct ttm_range_manager, manager);
}

static int ttm_range_man_alloc(struct ttm_resource_manager *man,
			       struct ttm_buffer_object *bo,
			       const struct ttm_place *place,
			       struct ttm_resource **res)
{
	struct ttm_range_manager *rman = to_range_manager(man);
	struct ttm_range_mgr_node *node;
	struct drm_mm *mm = &rman->mm;
	enum drm_mm_insert_mode mode;
	unsigned long lpfn;
	int ret;

	lpfn = place->lpfn;
	if (!lpfn)
		lpfn = man->size;

	node = kzalloc_flex(*node, mm_nodes, 1);
	if (!node)
		return -ENOMEM;

	mode = DRM_MM_INSERT_BEST;
	if (place->flags & TTM_PL_FLAG_TOPDOWN)
		mode = DRM_MM_INSERT_HIGH;

	ttm_resource_init(bo, place, &node->base);

	spin_lock(&rman->lock);
	ret = drm_mm_insert_node_in_range(mm, &node->mm_nodes[0],
					  PFN_UP(node->base.size),
					  bo->page_alignment, 0,
					  place->fpfn, lpfn, mode);
	spin_unlock(&rman->lock);

	if (unlikely(ret)) {
		ttm_resource_fini(man, &node->base);
		kfree(node);
		return ret;
	}

	node->base.start = node->mm_nodes[0].start;
	*res = &node->base;
	return 0;
}

static void ttm_range_man_free(struct ttm_resource_manager *man,
			       struct ttm_resource *res)
{
	struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res);
	struct ttm_range_manager *rman = to_range_manager(man);

	spin_lock(&rman->lock);
	drm_mm_remove_node(&node->mm_nodes[0]);
	spin_unlock(&rman->lock);

	ttm_resource_fini(man, res);
	kfree(node);
}

static bool ttm_range_man_intersects(struct ttm_resource_manager *man,
				     struct ttm_resource *res,
				     const struct ttm_place *place,
				     size_t size)
{
	struct drm_mm_node *node = &to_ttm_range_mgr_node(res)->mm_nodes[0];
	u32 num_pages = PFN_UP(size);

	/* Don't evict BOs outside of the requested placement range */
	if (place->fpfn >= (node->start + num_pages) ||
	    (place->lpfn && place->lpfn <= node->start))
		return false;

	return true;
}

static bool ttm_range_man_compatible(struct ttm_resource_manager *man,
				     struct ttm_resource *res,
				     const struct ttm_place *place,
				     size_t size)

Annotation

Implementation Notes