drivers/misc/open-dice.c

Source file repositories/reference/linux-study-clean/drivers/misc/open-dice.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/open-dice.c
Extension
.c
Size
5548 bytes
Lines
210
Domain
Driver Families
Bucket
drivers/misc
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 open_dice_fops = {
	.owner = THIS_MODULE,
	.read = open_dice_read,
	.write = open_dice_write,
	.mmap_prepare = open_dice_mmap_prepare,
};

static int __init open_dice_probe(struct platform_device *pdev)
{
	static unsigned int dev_idx;
	struct device *dev = &pdev->dev;
	struct reserved_mem *rmem;
	struct open_dice_drvdata *drvdata;
	int ret;

	rmem = of_reserved_mem_lookup(dev->of_node);
	if (!rmem) {
		dev_err(dev, "failed to lookup reserved memory\n");
		return -EINVAL;
	}

	if (!rmem->size || (rmem->size > ULONG_MAX)) {
		dev_err(dev, "invalid memory region size\n");
		return -EINVAL;
	}

	if (!PAGE_ALIGNED(rmem->base) || !PAGE_ALIGNED(rmem->size)) {
		dev_err(dev, "memory region must be page-aligned\n");
		return -EINVAL;
	}

	drvdata = devm_kmalloc(dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
		return -ENOMEM;

	*drvdata = (struct open_dice_drvdata){
		.rmem = rmem,
		.misc = (struct miscdevice){
			.parent	= dev,
			.name	= drvdata->name,
			.minor	= MISC_DYNAMIC_MINOR,
			.fops	= &open_dice_fops,
			.mode	= 0600,
		},
	};
	mutex_init(&drvdata->lock);

	/* Index overflow check not needed, misc_register() will fail. */
	snprintf(drvdata->name, sizeof(drvdata->name), DRIVER_NAME"%u", dev_idx++);

	ret = misc_register(&drvdata->misc);
	if (ret) {
		dev_err(dev, "failed to register misc device '%s': %d\n",
			drvdata->name, ret);
		return ret;
	}

	platform_set_drvdata(pdev, drvdata);
	return 0;
}

static void open_dice_remove(struct platform_device *pdev)
{
	struct open_dice_drvdata *drvdata = platform_get_drvdata(pdev);

	misc_deregister(&drvdata->misc);
}

static const struct of_device_id open_dice_of_match[] = {
	{ .compatible = "google,open-dice" },
	{},
};

static struct platform_driver open_dice_driver = {
	.remove = open_dice_remove,
	.driver = {
		.name = DRIVER_NAME,
		.of_match_table = open_dice_of_match,
	},
};

static int __init open_dice_init(void)
{
	int ret = platform_driver_probe(&open_dice_driver, open_dice_probe);

	/* DICE regions are optional. Succeed even with zero instances. */
	return (ret == -ENODEV) ? 0 : ret;
}

static void __exit open_dice_exit(void)

Annotation

Implementation Notes