drivers/gpu/drm/virtio/virtgpu_kms.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/virtio/virtgpu_kms.c
Extension
.c
Size
10648 bytes
Lines
362
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->num_scanouts) {
			if (vgdev->has_edid)
				virtio_gpu_cmd_get_edids(vgdev);
			virtio_gpu_cmd_get_display_info(vgdev);
			virtio_gpu_notify(vgdev);
			drm_helper_hpd_irq_event(vgdev->ddev);
		}
		events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
	}
	virtio_cwrite_le(vgdev->vdev, struct virtio_gpu_config,
			 events_clear, &events_clear);
}

static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
			       void (*work_func)(struct work_struct *work))
{
	spin_lock_init(&vgvq->qlock);
	init_waitqueue_head(&vgvq->ack_queue);
	INIT_WORK(&vgvq->dequeue_work, work_func);
}

static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
				   int num_capsets)
{
	int i, ret;
	bool invalid_capset_id = false;
	struct drm_device *drm = vgdev->ddev;

	vgdev->capsets = drmm_kcalloc(drm, num_capsets,
				      sizeof(struct virtio_gpu_drv_capset),
				      GFP_KERNEL);
	if (!vgdev->capsets) {
		DRM_ERROR("failed to allocate cap sets\n");
		return;
	}
	for (i = 0; i < num_capsets; i++) {
		virtio_gpu_cmd_get_capset_info(vgdev, i);
		virtio_gpu_notify(vgdev);
		ret = wait_event_timeout(vgdev->resp_wq,
					 vgdev->capsets[i].id > 0, 5 * HZ);
		/*
		 * Capability ids are defined in the virtio-gpu spec and are
		 * between 1 to 63, inclusive.
		 */
		if (!vgdev->capsets[i].id ||
		    vgdev->capsets[i].id > MAX_CAPSET_ID)
			invalid_capset_id = true;

		if (ret == 0)
			DRM_ERROR("timed out waiting for cap set %d\n", i);
		else if (invalid_capset_id)
			DRM_ERROR("invalid capset id %u", vgdev->capsets[i].id);

		if (ret == 0 || invalid_capset_id) {
			spin_lock(&vgdev->display_info_lock);
			drmm_kfree(drm, vgdev->capsets);
			vgdev->capsets = NULL;
			spin_unlock(&vgdev->display_info_lock);
			return;
		}

		vgdev->capset_id_mask |= 1 << vgdev->capsets[i].id;
		DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n",
			 i, vgdev->capsets[i].id,
			 vgdev->capsets[i].max_version,
			 vgdev->capsets[i].max_size);
	}

	vgdev->num_capsets = num_capsets;
}

int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
{
	struct virtqueue_info vqs_info[] = {
		{ "control", virtio_gpu_ctrl_ack },
		{ "cursor", virtio_gpu_cursor_ack },
	};
	struct virtio_gpu_device *vgdev;
	/* this will expand later */
	struct virtqueue *vqs[2];
	u32 num_scanouts, num_capsets, blob_alignment;
	int ret = 0;

	if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
		return -ENODEV;

	vgdev = drmm_kzalloc(dev, sizeof(struct virtio_gpu_device), GFP_KERNEL);
	if (!vgdev)
		return -ENOMEM;

Annotation

Implementation Notes