drivers/accel/amdxdna/amdxdna_ubuf.c

Source file repositories/reference/linux-study-clean/drivers/accel/amdxdna/amdxdna_ubuf.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/amdxdna/amdxdna_ubuf.c
Extension
.c
Size
4346 bytes
Lines
188
Domain
Driver Families
Bucket
drivers/accel
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 amdxdna_ubuf_priv {
	struct page **pages;
	u64 nr_pages;
	struct mm_struct *mm;
};

static struct sg_table *amdxdna_ubuf_map(struct dma_buf_attachment *attach,
					 enum dma_data_direction direction)
{
	struct amdxdna_ubuf_priv *ubuf = attach->dmabuf->priv;
	struct sg_table *sg;
	int ret;

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

	ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->nr_pages, 0,
					ubuf->nr_pages << PAGE_SHIFT, GFP_KERNEL);
	if (ret)
		goto err_free_sg;

	ret = dma_map_sgtable(attach->dev, sg, direction, 0);
	if (ret)
		goto err_free_table;

	return sg;

err_free_table:
	sg_free_table(sg);
err_free_sg:
	kfree(sg);
	return ERR_PTR(ret);
}

static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
			       struct sg_table *sg,
			       enum dma_data_direction direction)
{
	dma_unmap_sgtable(attach->dev, sg, direction, 0);
	sg_free_table(sg);
	kfree(sg);
}

static void amdxdna_ubuf_release(struct dma_buf *dbuf)
{
	struct amdxdna_ubuf_priv *ubuf = dbuf->priv;

	unpin_user_pages(ubuf->pages, ubuf->nr_pages);
	kvfree(ubuf->pages);
	atomic64_sub(ubuf->nr_pages, &ubuf->mm->pinned_vm);
	mmdrop(ubuf->mm);
	kfree(ubuf);
}

static const struct dma_buf_ops amdxdna_ubuf_dmabuf_ops = {
	.map_dma_buf = amdxdna_ubuf_map,
	.unmap_dma_buf = amdxdna_ubuf_unmap,
	.release = amdxdna_ubuf_release,
};

struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
				 u32 num_entries, void __user *va_entries)
{
	struct amdxdna_dev *xdna = to_xdna_dev(dev);
	unsigned long lock_limit, new_pinned;
	struct amdxdna_drm_va_entry *va_ent;
	struct amdxdna_ubuf_priv *ubuf;
	u32 npages, start = 0;
	struct dma_buf *dbuf;
	int i, ret;
	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);

	if (!can_do_mlock())
		return ERR_PTR(-EPERM);

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

	ubuf->mm = current->mm;
	mmgrab(ubuf->mm);

	va_ent = kvzalloc_objs(*va_ent, num_entries);
	if (!va_ent) {
		ret = -ENOMEM;
		goto free_ubuf;
	}

	if (copy_from_user(va_ent, va_entries, sizeof(*va_ent) * num_entries)) {

Annotation

Implementation Notes