drivers/gpu/drm/tegra/gem.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/tegra/gem.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/tegra/gem.c
Extension
.c
Size
16996 bytes
Lines
800
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 (sg_dma_address(s) != next) {
			next = sg_dma_address(s) + sg_dma_len(s);
			count++;
		}
	}

	return count;
}

static inline unsigned int sgt_dma_count_chunks(struct sg_table *sgt)
{
	return sg_dma_count_chunks(sgt->sgl, sgt->nents);
}

static void tegra_bo_put(struct host1x_bo *bo)
{
	struct tegra_bo *obj = host1x_to_tegra_bo(bo);

	drm_gem_object_put(&obj->gem);
}

static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_bo *bo,
					      enum dma_data_direction direction)
{
	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
	struct drm_gem_object *gem = &obj->gem;
	struct host1x_bo_mapping *map;
	int err;

	map = kzalloc_obj(*map);
	if (!map)
		return ERR_PTR(-ENOMEM);

	kref_init(&map->ref);
	map->bo = bo;
	map->direction = direction;
	map->dev = dev;

	/*
	 * Imported buffers need special treatment to satisfy the semantics of DMA-BUF.
	 */
	if (obj->dma_buf) {
		struct dma_buf *buf = obj->dma_buf;

		map->attach = dma_buf_attach(buf, dev);
		if (IS_ERR(map->attach)) {
			err = PTR_ERR(map->attach);
			goto free;
		}

		map->sgt = dma_buf_map_attachment_unlocked(map->attach, direction);
		if (IS_ERR(map->sgt)) {
			dma_buf_detach(buf, map->attach);
			err = PTR_ERR(map->sgt);
			map->sgt = NULL;
			goto free;
		}

		err = sgt_dma_count_chunks(map->sgt);
		map->size = gem->size;

		goto out;
	}

	/*
	 * If we don't have a mapping for this buffer yet, return an SG table
	 * so that host1x can do the mapping for us via the DMA API.
	 */
	map->sgt = kzalloc_obj(*map->sgt);
	if (!map->sgt) {
		err = -ENOMEM;
		goto free;
	}

	if (obj->pages) {
		/*
		 * If the buffer object was allocated from the explicit IOMMU
		 * API code paths, construct an SG table from the pages.
		 */
		err = sg_alloc_table_from_pages(map->sgt, obj->pages, obj->num_pages, 0, gem->size,
						GFP_KERNEL);
		if (err < 0)
			goto free;
	} else {
		/*
		 * If the buffer object had no pages allocated and if it was
		 * not imported, it had to be allocated with the DMA API, so
		 * the DMA API helper can be used.
		 */
		err = dma_get_sgtable(dev, map->sgt, obj->vaddr, obj->iova, gem->size);

Annotation

Implementation Notes