drivers/media/mc/mc-request.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/mc/mc-request.c
Extension
.c
Size
13913 bytes
Lines
540
Domain
Driver Families
Bucket
drivers/media
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 request_fops = {
	.owner = THIS_MODULE,
	.poll = media_request_poll,
	.unlocked_ioctl = media_request_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = media_request_ioctl,
#endif /* CONFIG_COMPAT */
	.release = media_request_close,
};

struct media_request *
media_request_get_by_fd(struct media_device *mdev, int request_fd)
{
	struct media_request *req;

	if (!mdev || !mdev->ops ||
	    !mdev->ops->req_validate || !mdev->ops->req_queue)
		return ERR_PTR(-EBADR);

	CLASS(fd, f)(request_fd);
	if (fd_empty(f))
		goto err;

	if (fd_file(f)->f_op != &request_fops)
		goto err;
	req = fd_file(f)->private_data;
	if (req->mdev != mdev)
		goto err;

	/*
	 * Note: as long as someone has an open filehandle of the request,
	 * the request can never be released. The fdget() above ensures that
	 * even if userspace closes the request filehandle, the release()
	 * fop won't be called, so the media_request_get() always succeeds
	 * and there is no race condition where the request was released
	 * before media_request_get() is called.
	 */
	media_request_get(req);
	return req;

err:
	dev_dbg(mdev->dev, "cannot find request_fd %d\n", request_fd);
	return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL_GPL(media_request_get_by_fd);

int media_request_alloc(struct media_device *mdev, int *alloc_fd)
{
	struct media_request *req;
	int ret;

	/* Either both are NULL or both are non-NULL */
	if (WARN_ON(!mdev->ops->req_alloc ^ !mdev->ops->req_free))
		return -ENOMEM;

	if (mdev->ops->req_alloc)
		req = mdev->ops->req_alloc(mdev);
	else
		req = kzalloc_obj(*req);
	if (!req)
		return -ENOMEM;

	req->mdev = mdev;
	req->state = MEDIA_REQUEST_STATE_IDLE;
	req->num_incomplete_objects = 0;
	req->manual_completion = false;
	kref_init(&req->kref);
	INIT_LIST_HEAD(&req->objects);
	spin_lock_init(&req->lock);
	init_waitqueue_head(&req->poll_wait);
	req->updating_count = 0;
	req->access_count = 0;

	FD_PREPARE(fdf, O_CLOEXEC,
		   anon_inode_getfile("request", &request_fops, NULL,
				      O_CLOEXEC));
	if (fdf.err) {
		ret = fdf.err;
		goto err_free_req;
	}

	fd_prepare_file(fdf)->private_data = req;

	snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
		 atomic_inc_return(&mdev->request_id), fd_prepare_fd(fdf));
	atomic_inc(&mdev->num_requests);
	dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);

	*alloc_fd = fd_publish(fdf);

Annotation

Implementation Notes