Commit db6b97a4 authored by Nicolas Dufresne's avatar Nicolas Dufresne Committed by Hans Verkuil
Browse files

media: v4l2-mem2mem: Add a kref to the v4l2_m2m_dev structure



Adding a reference count to the v4l2_m2m_dev structure allow safely
sharing it across multiple hardware nodes. This can be used to prevent
running jobs concurrently on m2m cores that have some internal resource
sharing.

Signed-off-by: default avatarMing Qian <ming.qian@oss.nxp.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Signed-off-by: default avatarNicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil+cisco@kernel.org>
[hverkuil: fix typos in v4l2_m2m_put documentation]
parent 3e92d7e4
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ static const char * const m2m_entity_name[] = {
 * @job_work:		worker to run queued jobs.
 * @job_queue_flags:	flags of the queue status, %QUEUE_PAUSED.
 * @m2m_ops:		driver callbacks
 * @kref:		device reference count
 */
struct v4l2_m2m_dev {
	struct v4l2_m2m_ctx	*curr_ctx;
@@ -109,6 +110,8 @@ struct v4l2_m2m_dev {
	unsigned long		job_queue_flags;

	const struct v4l2_m2m_ops *m2m_ops;

	struct kref kref;
};

static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
@@ -1200,6 +1203,7 @@ struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops)
	INIT_LIST_HEAD(&m2m_dev->job_queue);
	spin_lock_init(&m2m_dev->job_spinlock);
	INIT_WORK(&m2m_dev->job_work, v4l2_m2m_device_run_work);
	kref_init(&m2m_dev->kref);

	return m2m_dev;
}
@@ -1211,6 +1215,25 @@ void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev)
}
EXPORT_SYMBOL_GPL(v4l2_m2m_release);

void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev)
{
	kref_get(&m2m_dev->kref);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_get);

static void v4l2_m2m_release_from_kref(struct kref *kref)
{
	struct v4l2_m2m_dev *m2m_dev = container_of(kref, struct v4l2_m2m_dev, kref);

	v4l2_m2m_release(m2m_dev);
}

void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev)
{
	kref_put(&m2m_dev->kref, v4l2_m2m_release_from_kref);
}
EXPORT_SYMBOL_GPL(v4l2_m2m_put);

struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
		void *drv_priv,
		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
+21 −0
Original line number Diff line number Diff line
@@ -547,6 +547,27 @@ v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev,
 */
void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev);

/**
 * v4l2_m2m_get() - take a reference to the m2m_dev structure
 *
 * @m2m_dev: opaque pointer to the internal data to handle M2M context
 *
 * This is used to share the M2M device across multiple devices. This
 * can be used to avoid scheduling two hardware nodes concurrently.
 */
void v4l2_m2m_get(struct v4l2_m2m_dev *m2m_dev);

/**
 * v4l2_m2m_put() - remove a reference to the m2m_dev structure
 *
 * @m2m_dev: opaque pointer to the internal data to handle M2M context
 *
 * Once the M2M device has no more references, v4l2_m2m_release() will be
 * called automatically. Users of this method should never call
 * v4l2_m2m_release() directly. See v4l2_m2m_get() for more details.
 */
void v4l2_m2m_put(struct v4l2_m2m_dev *m2m_dev);

/**
 * v4l2_m2m_ctx_init() - allocate and initialize a m2m context
 *