All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] v4l2-ctrls: add v4l2_ctrl_del_handler()
@ 2018-08-10 11:48 Hans Verkuil
  0 siblings, 0 replies; only message in thread
From: Hans Verkuil @ 2018-08-10 11:48 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Sakari Ailus, Laurent Pinchart

If a sub-device is unbound, then it should also remove its controls from
other control handlers that it was added to using v4l2_ctrl_add_handler().

So create a v4l2_ctrl_del_handler() function that removes the controls that
were earlier added with v4l2_ctrl_add_handler().

Signed-off-by: Hans Verkuil <hansverk@cisco.com>
---
I'm not sure if this should be merged. It is necessary to safely unbind
subdevs, but since we don't do that yet anyway it is debatable if this
should be merged without anyone using it. But at least it will be archived
in patchwork so it isn't lost.

This function is used in our out-of-tree driver when we unconfigure an
FPGA where we do exactly this type of unbinding.

Regards,

	Hans
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 39 ++++++++++++++++++++++++++++
 include/media/v4l2-ctrls.h           | 12 +++++++++
 2 files changed, 51 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 599c1cbff3b9..b40cea8ec436 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -2421,6 +2421,45 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_add_handler);

+void v4l2_ctrl_del_handler(struct v4l2_ctrl_handler *hdl,
+			  struct v4l2_ctrl_handler *del)
+{
+	struct v4l2_ctrl_ref *ref, *ref_safe;
+
+	/* Do nothing if either handler is NULL or if they are the same */
+	if (!hdl || !del || hdl == del)
+		return;
+
+	mutex_lock(hdl->lock);
+	list_for_each_entry_safe(ref, ref_safe, &hdl->ctrl_refs, node) {
+		struct v4l2_ctrl *ctrl = ref->ctrl;
+		struct v4l2_ctrl_ref *bucket_ref;
+		int bucket;
+
+		if (ctrl->handler != del)
+			continue;
+
+		bucket = ctrl->id % hdl->nr_of_buckets;	/* which bucket to use */
+		bucket_ref = hdl->buckets[bucket];
+
+		list_del(&ref->node);
+		if (bucket_ref == ref)
+			hdl->buckets[bucket] = ref->next;
+		else {
+			while (bucket_ref->next && bucket_ref->next != ref)
+				bucket_ref = bucket_ref->next;
+			if (bucket_ref)
+				bucket_ref->next = ref->next;
+			else
+				pr_err("could not find ctrl '%s'\n", ctrl->name);
+		}
+		kfree(ref);
+	}
+	hdl->cached = NULL;
+	mutex_unlock(hdl->lock);
+}
+EXPORT_SYMBOL(v4l2_ctrl_del_handler);
+
 bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl)
 {
 	if (V4L2_CTRL_ID2WHICH(ctrl->id) == V4L2_CTRL_CLASS_FM_TX)
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index f615ba1b29dd..c32d3500db54 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -644,6 +644,18 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
 			  struct v4l2_ctrl_handler *add,
 			  v4l2_ctrl_filter filter);

+/**
+ * v4l2_ctrl_del_handler() - Remove all controls in handler @del from
+ * handler @hdl.
+ * @hdl:	The control handler.
+ * @del:	The control handler whose controls you want to delete from
+ *		the @hdl control handler.
+ *
+ * Does nothing if either of the two handlers is a NULL pointer.
+ */
+void v4l2_ctrl_del_handler(struct v4l2_ctrl_handler *hdl,
+			   struct v4l2_ctrl_handler *del);
+
 /**
  * v4l2_ctrl_radio_filter() - Standard filter for radio controls.
  *
-- 
2.18.0

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-08-10 14:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-10 11:48 [PATCH] v4l2-ctrls: add v4l2_ctrl_del_handler() Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.