drivers/staging/greybus/authentication.c

Source file repositories/reference/linux-study-clean/drivers/staging/greybus/authentication.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/greybus/authentication.c
Extension
.c
Size
10174 bytes
Lines
430
Domain
Driver Families
Bucket
drivers/staging
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 cap_fops = {
	.owner		= THIS_MODULE,
	.open		= cap_open,
	.release	= cap_release,
	.unlocked_ioctl	= cap_ioctl_unlocked,
};

int gb_cap_connection_init(struct gb_connection *connection)
{
	struct gb_cap *cap;
	int ret, minor;

	if (!connection)
		return 0;

	cap = kzalloc_obj(*cap);
	if (!cap)
		return -ENOMEM;

	cap->parent = &connection->bundle->dev;
	cap->connection = connection;
	mutex_init(&cap->mutex);
	gb_connection_set_data(connection, cap);
	kref_init(&cap->kref);

	mutex_lock(&list_mutex);
	list_add(&cap->node, &cap_list);
	mutex_unlock(&list_mutex);

	ret = gb_connection_enable(connection);
	if (ret)
		goto err_list_del;

	minor = ida_alloc_max(&cap_minors_map, NUM_MINORS - 1, GFP_KERNEL);
	if (minor < 0) {
		ret = minor;
		goto err_connection_disable;
	}

	/* Add a char device to allow userspace to interact with cap */
	cap->dev_num = MKDEV(MAJOR(cap_dev_num), minor);
	cdev_init(&cap->cdev, &cap_fops);

	ret = cdev_add(&cap->cdev, cap->dev_num, 1);
	if (ret)
		goto err_remove_ida;

	/* Add a soft link to the previously added char-dev within the bundle */
	cap->class_device = device_create(&cap_class, cap->parent, cap->dev_num,
					  NULL, "gb-authenticate-%d", minor);
	if (IS_ERR(cap->class_device)) {
		ret = PTR_ERR(cap->class_device);
		goto err_del_cdev;
	}

	return 0;

err_del_cdev:
	cdev_del(&cap->cdev);
err_remove_ida:
	ida_free(&cap_minors_map, minor);
err_connection_disable:
	gb_connection_disable(connection);
err_list_del:
	mutex_lock(&list_mutex);
	list_del(&cap->node);
	mutex_unlock(&list_mutex);

	put_cap(cap);

	return ret;
}

void gb_cap_connection_exit(struct gb_connection *connection)
{
	struct gb_cap *cap;

	if (!connection)
		return;

	cap = gb_connection_get_data(connection);

	device_destroy(&cap_class, cap->dev_num);
	cdev_del(&cap->cdev);
	ida_free(&cap_minors_map, MINOR(cap->dev_num));

	/*
	 * Disallow any new ioctl operations on the char device and wait for
	 * existing ones to finish.
	 */

Annotation

Implementation Notes