drivers/gpu/drm/virtio/virtgpu_prime.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/virtio/virtgpu_prime.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/virtio/virtgpu_prime.c
Extension
.c
Size
9008 bytes
Lines
348
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 (vgdev->has_resource_assign_uuid) {
			ret = virtio_gpu_resource_assign_uuid(vgdev, bo);
			if (ret)
				return ERR_PTR(ret);

			virtio_gpu_notify(vgdev);
		} else {
			bo->uuid_state = STATE_ERR;
		}
	} else if (!(bo->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)) {
		bo->uuid_state = STATE_ERR;
	}

	exp_info.ops = &virtgpu_dmabuf_ops.ops;
	exp_info.size = obj->size;
	exp_info.flags = flags;
	exp_info.priv = obj;
	exp_info.resv = obj->resv;

	buf = virtio_dma_buf_export(&exp_info);
	if (IS_ERR(buf))
		return buf;

	drm_dev_get(dev);
	drm_gem_object_get(obj);

	return buf;
}

int virtgpu_dma_buf_import_sgt(struct virtio_gpu_mem_entry **ents,
			       unsigned int *nents,
			       struct virtio_gpu_object *bo,
			       struct dma_buf_attachment *attach)
{
	struct scatterlist *sl;
	struct sg_table *sgt;
	long i, ret;

	dma_resv_assert_held(attach->dmabuf->resv);

	ret = dma_resv_wait_timeout(attach->dmabuf->resv,
				    DMA_RESV_USAGE_KERNEL,
				    false, MAX_SCHEDULE_TIMEOUT);
	if (ret <= 0)
		return ret < 0 ? ret : -ETIMEDOUT;

	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
	if (IS_ERR(sgt))
		return PTR_ERR(sgt);

	*ents = kvmalloc_objs(struct virtio_gpu_mem_entry, sgt->nents);
	if (!(*ents)) {
		dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
		return -ENOMEM;
	}

	*nents = sgt->nents;
	for_each_sgtable_dma_sg(sgt, sl, i) {
		(*ents)[i].addr = cpu_to_le64(sg_dma_address(sl));
		(*ents)[i].length = cpu_to_le32(sg_dma_len(sl));
		(*ents)[i].padding = 0;
	}

	bo->sgt = sgt;
	return 0;
}

static void virtgpu_dma_buf_unmap(struct virtio_gpu_object *bo)
{
	struct dma_buf_attachment *attach = bo->base.base.import_attach;

	dma_resv_assert_held(attach->dmabuf->resv);

	if (bo->created) {
		virtio_gpu_detach_object_fenced(bo);

		if (bo->sgt)
			dma_buf_unmap_attachment(attach, bo->sgt,
						 DMA_BIDIRECTIONAL);

		bo->sgt = NULL;
	}
}

static void virtgpu_dma_buf_free_obj(struct drm_gem_object *obj)
{
	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
	struct virtio_gpu_device *vgdev = obj->dev->dev_private;
	struct dma_buf_attachment *attach = obj->import_attach;

Annotation

Implementation Notes