drivers/gpu/drm/qxl/qxl_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/qxl/qxl_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/qxl/qxl_drv.c
Extension
.c
Size
8226 bytes
Lines
318
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 qxl_pci_driver;

static int
qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct qxl_device *qdev;
	int ret;

	if (pdev->revision < 4) {
		DRM_ERROR("qxl too old, doesn't support client_monitors_config,"
			  " use xf86-video-qxl in user mode");
		return -EINVAL; /* TODO: ENODEV ? */
	}

	qdev = devm_drm_dev_alloc(&pdev->dev, &qxl_driver,
				  struct qxl_device, ddev);
	if (IS_ERR(qdev)) {
		pr_err("Unable to init drm dev");
		return -ENOMEM;
	}

	ret = pci_enable_device(pdev);
	if (ret)
		return ret;

	ret = aperture_remove_conflicting_pci_devices(pdev, qxl_driver.name);
	if (ret)
		goto disable_pci;

	if (pci_is_vga(pdev) && pdev->revision < 5) {
		ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO);
		if (ret) {
			DRM_ERROR("can't get legacy vga ioports\n");
			goto disable_pci;
		}
	}

	ret = qxl_device_init(qdev, pdev);
	if (ret)
		goto put_vga;

	ret = qxl_modeset_init(qdev);
	if (ret)
		goto unload;

	drm_kms_helper_poll_init(&qdev->ddev);

	/* Complete initialization. */
	ret = drm_dev_register(&qdev->ddev, ent->driver_data);
	if (ret)
		goto poll_fini;

	drm_client_setup(&qdev->ddev, NULL);
	return 0;

poll_fini:
	drm_kms_helper_poll_fini(&qdev->ddev);
	qxl_modeset_fini(qdev);
unload:
	qxl_device_fini(qdev);
put_vga:
	if (pci_is_vga(pdev) && pdev->revision < 5)
		vga_put(pdev, VGA_RSRC_LEGACY_IO);
disable_pci:
	pci_disable_device(pdev);

	return ret;
}

static void qxl_drm_release(struct drm_device *dev)
{
	struct qxl_device *qdev = to_qxl(dev);

	/*
	 * TODO: qxl_device_fini() call should be in qxl_pci_remove(),
	 * reordering qxl_modeset_fini() + qxl_device_fini() calls is
	 * non-trivial though.
	 */
	qxl_modeset_fini(qdev);
	qxl_device_fini(qdev);
}

static void
qxl_pci_remove(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);

	drm_kms_helper_poll_fini(dev);
	drm_dev_unregister(dev);
	drm_atomic_helper_shutdown(dev);

Annotation

Implementation Notes