drivers/misc/mei/main.c

Source file repositories/reference/linux-study-clean/drivers/misc/mei/main.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/mei/main.c
Extension
.c
Size
30550 bytes
Lines
1385
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 mei_fops = {
	.owner = THIS_MODULE,
	.read = mei_read,
	.unlocked_ioctl = mei_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.open = mei_open,
	.release = mei_release,
	.write = mei_write,
	.poll = mei_poll,
	.fsync = mei_fsync,
	.fasync = mei_fasync,
};

/**
 * mei_minor_get - obtain next free device minor number
 *
 * @dev:  device pointer
 *
 * Return: allocated minor, or -ENOSPC if no free minor left
 */
static int mei_minor_get(struct mei_device *dev)
{
	int ret;

	mutex_lock(&mei_minor_lock);
	ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL);
	if (ret >= 0)
		dev->minor = ret;
	else if (ret == -ENOSPC)
		dev_err(&dev->dev, "too many mei devices\n");

	mutex_unlock(&mei_minor_lock);
	return ret;
}

/**
 * mei_minor_free - mark device minor number as free
 *
 * @minor: minor number to free
 */
static void mei_minor_free(int minor)
{
	mutex_lock(&mei_minor_lock);
	idr_remove(&mei_idr, minor);
	mutex_unlock(&mei_minor_lock);
}

static void mei_device_release(struct device *dev)
{
	kfree(dev_get_drvdata(dev));
}

int mei_register(struct mei_device *dev, struct device *parent)
{
	int ret, devno;
	int minor;

	ret = mei_minor_get(dev);
	if (ret < 0)
		return ret;

	minor = dev->minor;

	/* Fill in the data structures */
	devno = MKDEV(MAJOR(mei_devt), dev->minor);

	device_initialize(&dev->dev);
	dev->dev.devt = devno;
	dev->dev.class = &mei_class;
	dev->dev.parent = parent;
	dev->dev.groups = mei_groups;
	dev->dev.release = mei_device_release;
	dev_set_drvdata(&dev->dev, dev);

	dev->cdev = cdev_alloc();
	if (!dev->cdev) {
		ret = -ENOMEM;
		goto err;
	}
	dev->cdev->ops = &mei_fops;
	dev->cdev->owner = parent->driver->owner;
	cdev_set_parent(dev->cdev, &dev->dev.kobj);

	/* Add the device */
	ret = cdev_add(dev->cdev, devno, 1);
	if (ret) {
		dev_err(parent, "unable to add cdev for device %d:%d\n",
			MAJOR(mei_devt), dev->minor);
		goto err_del_cdev;
	}

Annotation

Implementation Notes