drivers/gpu/drm/hyperv/hyperv_drm_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/hyperv/hyperv_drm_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/hyperv/hyperv_drm_drv.c
Extension
.c
Size
5968 bytes
Lines
269
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static struct pci_driver hyperv_pci_driver = {
	.name =		KBUILD_MODNAME,
	.id_table =	hyperv_pci_tbl,
	.probe =	hyperv_pci_probe,
	.remove =	hyperv_pci_remove,
};

static int hyperv_setup_vram(struct hyperv_drm_device *hv,
			     struct hv_device *hdev)
{
	struct drm_device *dev = &hv->dev;
	int ret;

	hv->fb_size = (unsigned long)hv->mmio_megabytes * 1024 * 1024;

	ret = vmbus_allocate_mmio(&hv->mem, hdev, 0, -1, hv->fb_size, 0x100000,
				  true);
	if (ret) {
		drm_err(dev, "Failed to allocate mmio\n");
		return -ENOMEM;
	}

	/*
	 * Map the VRAM cacheable for performance. This is also required for VM
	 * connect to display properly for ARM64 Linux VM, as the host also maps
	 * the VRAM cacheable.
	 */
	hv->vram = ioremap_cache(hv->mem->start, hv->fb_size);
	if (!hv->vram) {
		drm_err(dev, "Failed to map vram\n");
		ret = -ENOMEM;
		goto error;
	}

	hv->fb_base = hv->mem->start;
	return 0;

error:
	vmbus_free_mmio(hv->mem->start, hv->fb_size);
	return ret;
}

static int hyperv_vmbus_probe(struct hv_device *hdev,
			      const struct hv_vmbus_device_id *dev_id)
{
	struct hyperv_drm_device *hv;
	struct drm_device *dev;
	int ret;

	hv = devm_drm_dev_alloc(&hdev->device, &hyperv_driver,
				struct hyperv_drm_device, dev);
	if (IS_ERR(hv))
		return PTR_ERR(hv);

	dev = &hv->dev;
	init_completion(&hv->wait);
	hv_set_drvdata(hdev, hv);
	hv->hdev = hdev;

	ret = hyperv_connect_vsp(hdev);
	if (ret) {
		drm_err(dev, "Failed to connect to vmbus.\n");
		goto err_hv_set_drv_data;
	}

	aperture_remove_all_conflicting_devices(hyperv_driver.name);

	ret = hyperv_setup_vram(hv, hdev);
	if (ret)
		goto err_vmbus_close;

	/*
	 * Should be done only once during init and resume. Failing to update
	 * vram location is not fatal. Device will update dirty area till
	 * preferred resolution only.
	 */
	ret = hyperv_update_vram_location(hdev, hv->fb_base);
	if (ret)
		drm_warn(dev, "Failed to update vram location.\n");

	ret = hyperv_mode_config_init(hv);
	if (ret)
		goto err_free_mmio;

	ret = drm_dev_register(dev, 0);
	if (ret) {
		drm_err(dev, "Failed to register drm driver.\n");
		goto err_free_mmio;
	}

Annotation

Implementation Notes