drivers/gpu/host1x/context.c

Source file repositories/reference/linux-study-clean/drivers/gpu/host1x/context.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/host1x/context.c
Extension
.c
Size
4101 bytes
Lines
179
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

err = device_add(&ctx->dev);
		if (err) {
			dev_err(host1x->dev, "could not add context device %d: %d\n", i, err);
			put_device(&ctx->dev);
			goto unreg_devices;
		}

		err = of_dma_configure_id(&ctx->dev, node, true, &i);
		if (err) {
			dev_err(host1x->dev, "IOMMU configuration failed for context device %d: %d\n",
				i, err);
			device_unregister(&ctx->dev);
			goto unreg_devices;
		}

		if (!tegra_dev_iommu_get_stream_id(&ctx->dev, &ctx->stream_id) ||
		    !device_iommu_mapped(&ctx->dev)) {
			dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i);
			device_unregister(&ctx->dev);

			/*
			 * This means that if IOMMU is disabled but context devices
			 * are defined in the device tree, Host1x will fail to probe.
			 * That's probably OK in this time and age.
			 */
			err = -EINVAL;

			goto unreg_devices;
		}
	}

	return 0;

unreg_devices:
	while (i--)
		device_unregister(&cdl->devs[i].dev);

	kfree(cdl->devs);
	cdl->devs = NULL;
	cdl->len = 0;

	return err;
}

void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl)
{
	unsigned int i;

	for (i = 0; i < cdl->len; i++)
		device_unregister(&cdl->devs[i].dev);

	kfree(cdl->devs);
	cdl->len = 0;
}

struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
							  struct device *dev,
							  struct pid *pid)
{
	struct host1x_memory_context_list *cdl = &host1x->context_list;
	struct host1x_memory_context *free = NULL;
	int i;

	if (!cdl->len)
		return ERR_PTR(-EOPNOTSUPP);

	mutex_lock(&cdl->lock);

	for (i = 0; i < cdl->len; i++) {
		struct host1x_memory_context *cd = &cdl->devs[i];

		if (cd->dev.iommu->iommu_dev != dev->iommu->iommu_dev)
			continue;

		if (cd->owner == pid) {
			refcount_inc(&cd->ref);
			mutex_unlock(&cdl->lock);
			return cd;
		} else if (!cd->owner && !free) {
			free = cd;
		}
	}

	if (!free) {
		mutex_unlock(&cdl->lock);
		return ERR_PTR(-EBUSY);
	}

	refcount_set(&free->ref, 1);
	free->owner = get_pid(pid);

Annotation

Implementation Notes