drivers/accel/ivpu/ivpu_drv.c

Source file repositories/reference/linux-study-clean/drivers/accel/ivpu/ivpu_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/accel/ivpu/ivpu_drv.c
Extension
.c
Size
23534 bytes
Lines
894
Domain
Driver Families
Bucket
drivers/accel
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 const struct file_operations ivpu_fops = {
	.owner = THIS_MODULE,
	DRM_ACCEL_FOPS,
#ifdef CONFIG_PROC_FS
	.show_fdinfo = drm_show_fdinfo,
#endif
};

static int ivpu_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv,
				       u32 handle, u32 flags, int *prime_fd)
{
	struct drm_gem_object *obj;

	obj = drm_gem_object_lookup(file_priv, handle);
	if (!obj)
		return -ENOENT;

	if (drm_gem_is_imported(obj)) {
		/* Do not allow re-exporting */
		drm_gem_object_put(obj);
		return -EOPNOTSUPP;
	}

	drm_gem_object_put(obj);

	return drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
}

static const struct drm_driver driver = {
	.driver_features = DRIVER_GEM | DRIVER_COMPUTE_ACCEL,

	.open = ivpu_open,
	.postclose = ivpu_postclose,

	.gem_create_object = ivpu_gem_create_object,
	.gem_prime_import = ivpu_gem_prime_import,
	.prime_handle_to_fd = ivpu_gem_prime_handle_to_fd,

	.ioctls = ivpu_drm_ioctls,
	.num_ioctls = ARRAY_SIZE(ivpu_drm_ioctls),
	.fops = &ivpu_fops,
#ifdef CONFIG_PROC_FS
	.show_fdinfo = drm_show_memory_stats,
#endif

	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,

	.major = 1,
};

static int ivpu_irq_init(struct ivpu_device *vdev)
{
	struct pci_dev *pdev = to_pci_dev(vdev->drm.dev);
	int ret;

	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_MSIX);
	if (ret < 0) {
		ivpu_err(vdev, "Failed to allocate a MSI IRQ: %d\n", ret);
		return ret;
	}

	INIT_WORK(&vdev->irq_ipc_work, ivpu_ipc_irq_work_fn);
	INIT_WORK(&vdev->irq_dct_work, ivpu_pm_irq_dct_work_fn);
	INIT_WORK(&vdev->context_abort_work, ivpu_context_abort_work_fn);

	ivpu_irq_handlers_init(vdev);

	vdev->irq = pci_irq_vector(pdev, 0);

	ret = devm_request_irq(vdev->drm.dev, vdev->irq, ivpu_hw_irq_handler,
			       IRQF_NO_AUTOEN, DRIVER_NAME, vdev);
	if (ret)
		ivpu_err(vdev, "Failed to request an IRQ %d\n", ret);

	return ret;
}

static int ivpu_pci_init(struct ivpu_device *vdev)
{
	struct pci_dev *pdev = to_pci_dev(vdev->drm.dev);
	struct resource *bar0 = &pdev->resource[0];
	struct resource *bar4 = &pdev->resource[4];
	int ret;

	ivpu_dbg(vdev, MISC, "Mapping BAR0 (RegV) %pR\n", bar0);
	vdev->regv = devm_ioremap_resource(vdev->drm.dev, bar0);
	if (IS_ERR(vdev->regv)) {
		ivpu_err(vdev, "Failed to map bar 0: %pe\n", vdev->regv);
		return PTR_ERR(vdev->regv);

Annotation

Implementation Notes