drivers/media/mc/mc-dev-allocator.c

Source file repositories/reference/linux-study-clean/drivers/media/mc/mc-dev-allocator.c

File Facts

System
Linux kernel
Corpus path
drivers/media/mc/mc-dev-allocator.c
Extension
.c
Size
3553 bytes
Lines
136
Domain
Driver Families
Bucket
drivers/media
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

struct media_device_instance {
	struct media_device mdev;
	struct module *owner;
	struct list_head list;
	struct kref refcount;
};

static inline struct media_device_instance *
to_media_device_instance(struct media_device *mdev)
{
	return container_of(mdev, struct media_device_instance, mdev);
}

static void media_device_instance_release(struct kref *kref)
{
	struct media_device_instance *mdi =
		container_of(kref, struct media_device_instance, refcount);

	dev_dbg(mdi->mdev.dev, "%s: releasing Media Device\n", __func__);

	mutex_lock(&media_device_lock);

	media_device_unregister(&mdi->mdev);
	media_device_cleanup(&mdi->mdev);

	list_del(&mdi->list);
	mutex_unlock(&media_device_lock);

	kfree(mdi);
}

/* Callers should hold media_device_lock when calling this function */
static struct media_device *__media_device_get(struct device *dev,
						const char *module_name,
						struct module *owner)
{
	struct media_device_instance *mdi;

	list_for_each_entry(mdi, &media_device_list, list) {
		if (mdi->mdev.dev != dev)
			continue;

		kref_get(&mdi->refcount);

		/* get module reference for the media_device owner */
		if (owner != mdi->owner && !try_module_get(mdi->owner))
			dev_err(dev,
				"%s: module %s get owner reference error\n",
					__func__, module_name);
		else
			dev_dbg(dev, "%s: module %s got owner reference\n",
					__func__, module_name);
		return &mdi->mdev;
	}

	mdi = kzalloc_obj(*mdi);
	if (!mdi)
		return NULL;

	mdi->owner = owner;
	kref_init(&mdi->refcount);
	list_add_tail(&mdi->list, &media_device_list);

	dev_dbg(dev, "%s: Allocated media device for owner %s\n",
			__func__, module_name);
	return &mdi->mdev;
}

struct media_device *media_device_usb_allocate(struct usb_device *udev,
					       const char *module_name,
					       struct module *owner)
{
	struct media_device *mdev;

	mutex_lock(&media_device_lock);
	mdev = __media_device_get(&udev->dev, module_name, owner);
	if (!mdev) {
		mutex_unlock(&media_device_lock);
		return ERR_PTR(-ENOMEM);
	}

	/* check if media device is already initialized */
	if (!mdev->dev)
		__media_device_usb_init(mdev, udev, udev->product,
					module_name);
	mutex_unlock(&media_device_lock);
	return mdev;
}
EXPORT_SYMBOL_GPL(media_device_usb_allocate);

Annotation

Implementation Notes