All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sakari Ailus <sakari.ailus@linux.intel.com>
To: linux-media@vger.kernel.org
Cc: laurent.pinchart@ideasonboard.com,
	Philipp Zabel <p.zabel@pengutronix.de>,
	hverkuil@xs4all.nl, Francesco Dolcini <francesco@dolcini.it>,
	aishwarya.kothari@toradex.com, Robert Foss <rfoss@kernel.org>,
	Todor Tomov <todor.too@gmail.com>,
	Hyun Kwon <hyun.kwon@xilinx.com>,
	bingbu.cao@intel.com
Subject: [PATCH v2 18/31] media: v4l: async: Differentiate connecting and creating sub-devices
Date: Tue, 16 May 2023 12:55:04 +0300	[thread overview]
Message-ID: <20230516095517.611711-19-sakari.ailus@linux.intel.com> (raw)
In-Reply-To: <20230516095517.611711-1-sakari.ailus@linux.intel.com>

When the v4l2-async framework was introduced, the use case for it was to
connect a camera sensor with a parallel receiver. Both tended to be rather
simple devices with a single connection between them.

The framework has been since improved in multiple ways but there are
limitations that have remained, for instance the assumption an async
sub-device is connected towards a single notifier and via a single link
only.

This patch adds an object that represents the device while an earlier
patch in the series re-purposed the old struct v4l2_async_subdev as the
connection. In other words, multiple connections (via graph endpoints) may
now exist for a given async sub-device.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 245 +++++++++++++++++++++------
 include/media/v4l2-async.h           |  39 ++++-
 include/media/v4l2-subdev.h          |   2 +-
 3 files changed, 226 insertions(+), 60 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index c70d87931ebb6..c24a709d45caa 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -148,6 +148,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 }
 
 static LIST_HEAD(subdev_list);
+static LIST_HEAD(asd_list);
 static LIST_HEAD(notifier_list);
 static DEFINE_MUTEX(list_lock);
 
@@ -239,7 +240,7 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
 
 	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
 		struct v4l2_async_notifier *subdev_notifier =
-			v4l2_async_find_subdev_notifier(asc->sd);
+			v4l2_async_find_subdev_notifier(asc->asd->sd);
 
 		if (subdev_notifier &&
 		    !v4l2_async_nf_can_complete(subdev_notifier))
@@ -313,30 +314,50 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_connection *asc)
 {
 	struct v4l2_async_notifier *subdev_notifier;
+	bool registered = false;
 	int ret;
 
-	ret = v4l2_device_register_subdev(v4l2_dev, sd);
-	if (ret < 0)
-		return ret;
+	if (!asc->asd->bound) {
+		ret = v4l2_device_register_subdev(v4l2_dev, sd);
+		if (ret < 0)
+			return ret;
+		registered = true;
+	}
 
 	ret = v4l2_async_nf_call_bound(notifier, sd, asc);
-	if (ret < 0)
+	if (ret < 0) {
+		if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
+			dev_dbg(notifier_dev(notifier),
+				"failed binding %pfw (%d)\n",
+				asc->match.fwnode, ret);
 		goto err_unregister_subdev;
+	}
 
-	/*
-	 * Depending of the function of the entities involved, we may want to
-	 * create links between them (for example between a sensor and its lens
-	 * or between a sensor's source pad and the connected device's sink
-	 * pad).
-	 */
-	ret = v4l2_async_create_ancillary_links(notifier, sd);
-	if (ret)
-		goto err_call_unbind;
-
-	sd->asd = asc;
-	sd->notifier = notifier;
+	if (registered) {
+		/*
+		 * Depending of the function of the entities involved, we may
+		 * want to create links between them (for example between a
+		 * sensor and its lens or between a sensor's source pad and the
+		 * connected device's sink pad).
+		 */
+		ret = v4l2_async_create_ancillary_links(notifier, sd);
+		if (ret) {
+			if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
+				dev_dbg(notifier_dev(notifier),
+					"failed creating links for %pfw (%d)\n",
+					asc->match.fwnode, ret);
+			goto err_call_unbind;
+		}
+	}
 
-	asc->sd = sd;
+	asc->asd->bound++;
+	if (!sd->asd) {
+		sd->asd = asc->asd;
+		sd->notifier = notifier;
+		asc->asd->sd = sd;
+	} else {
+		WARN_ON(sd->asd != asc->asd);
+	}
 
 	/* Move from the waiting list to notifier's done */
 	list_move(&asc->asc_entry, &notifier->done_list);
@@ -362,9 +383,11 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 
 err_call_unbind:
 	v4l2_async_nf_call_unbind(notifier, sd, asc);
+	list_del(&asc->asc_subdev_entry);
 
 err_unregister_subdev:
-	v4l2_device_unregister_subdev(sd);
+	if (registered)
+		v4l2_device_unregister_subdev(sd);
 
 	return ret;
 }
@@ -410,15 +433,17 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
 	return 0;
 }
 
-static void v4l2_async_cleanup(struct v4l2_subdev *sd)
+static void v4l2_async_unbind_subdev_one(struct v4l2_async_notifier *notifier,
+					 struct v4l2_async_connection *asc)
 {
-	v4l2_device_unregister_subdev(sd);
-	/*
-	 * Subdevice driver will reprobe and put the subdev back
-	 * onto the list
-	 */
-	list_del_init(&sd->async_list);
-	sd->asd = NULL;
+	list_move_tail(&asc->asc_entry, &notifier->waiting_list);
+	asc->asd->bound--;
+	WARN_ON(asc->asd->bound < 0);
+	if (!asc->asd->bound) {
+		v4l2_async_nf_call_unbind(notifier, asc->asd->sd, asc);
+		v4l2_device_unregister_subdev(asc->asd->sd);
+		asc->asd->sd->asd = NULL;
+	}
 }
 
 /* Unbind all sub-devices in the notifier tree. */
@@ -430,16 +455,12 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
 	list_for_each_entry_safe(asc, asc_tmp, &notifier->done_list,
 				 asc_entry) {
 		struct v4l2_async_notifier *subdev_notifier =
-			v4l2_async_find_subdev_notifier(asc->sd);
+			v4l2_async_find_subdev_notifier(asc->asd->sd);
 
 		if (subdev_notifier)
 			v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-		v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
-		v4l2_async_cleanup(asc->sd);
-		list_move_tail(&asc->asc_entry, &notifier->waiting_list);
-		list_move(&asc->sd->async_list, &subdev_list);
-		asc->sd = NULL;
+		v4l2_async_unbind_subdev_one(notifier, asc);
 	}
 
 	notifier->parent = NULL;
@@ -457,7 +478,7 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
 			return true;
 
 	list_for_each_entry(asc, &notifier->done_list, asc_entry) {
-		if (WARN_ON(!asc->sd->asd))
+		if (WARN_ON(!asc->asd->sd->asd))
 			continue;
 
 		if (v4l2_async_match_equal(&asc->match, match))
@@ -632,6 +653,18 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL(v4l2_async_nf_unregister);
 
+static void release_async_subdev(struct kref *kref)
+{
+	struct v4l2_async_subdev *asd =
+		container_of_const(kref, struct v4l2_async_subdev, kref);
+
+	list_del(&asd->asd_entry);
+
+	WARN_ON(asd->asc_list.next && !list_empty(&asd->asc_list));
+
+	kfree(asd);
+}
+
 static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_connection *asc, *tmp;
@@ -642,16 +675,28 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 	WARN_ON(!list_empty(&notifier->done_list));
 
 	list_for_each_entry_safe(asc, tmp, &notifier->waiting_list, asc_entry) {
+		list_del(&asc->asc_entry);
+		list_del(&asc->asc_subdev_entry);
+		v4l2_async_nf_call_destroy(notifier, asc);
+
 		switch (asc->match.type) {
 		case V4L2_ASYNC_MATCH_TYPE_FWNODE:
+			dev_dbg(notifier_dev(notifier),
+				"release async connection for fwnode %pfw\n",
+				asc->match.fwnode);
 			fwnode_handle_put(asc->match.fwnode);
 			break;
-		default:
+		case V4L2_ASYNC_MATCH_TYPE_I2C:
+			dev_dbg(notifier_dev(notifier),
+				"release I²C async connection\n");
 			break;
+		default:
+			dev_dbg(notifier_dev(notifier),
+				"release invalid async connection type %u\n",
+				asc->match.type);
 		}
 
-		list_del(&asc->asc_entry);
-		v4l2_async_nf_call_destroy(notifier, asc);
+		kref_put(&asc->asd->kref, release_async_subdev);
 		kfree(asc);
 	}
 }
@@ -666,16 +711,104 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
 
+static bool async_subdev_has_connection(struct v4l2_async_notifier *notifier,
+					struct v4l2_async_subdev *asd,
+					struct v4l2_async_connection *asc)
+{
+	struct v4l2_async_connection *__asc;
+	struct fwnode_handle *fwnode;
+	bool exists = false;
+
+	fwnode = fwnode_graph_get_port_parent(asc->match.fwnode);
+	if (WARN_ON(!fwnode))
+		return false;
+
+	list_for_each_entry(__asc, &asd->asc_list, asc_subdev_entry) {
+		struct fwnode_handle *__fwnode;
+
+		if (__asc->match.type != V4L2_ASYNC_MATCH_TYPE_FWNODE)
+			continue;
+
+		__fwnode = fwnode_graph_get_port_parent(__asc->match.fwnode);
+		if (WARN_ON(!__fwnode))
+			continue;
+
+		fwnode_handle_put(__fwnode);
+
+		if (__fwnode == fwnode) {
+			exists = true;
+			break;
+		}
+	}
+
+	fwnode_handle_put(fwnode);
+
+	return exists;
+}
+
+/* Find an async sub-device for the async connection. */
+static int v4l2_async_find_async_subdev(struct v4l2_async_notifier *notifier,
+					struct v4l2_async_connection *asc)
+{
+	struct v4l2_async_subdev *asd;
+
+	lockdep_assert_held(&list_lock);
+
+	if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE) {
+		dev_dbg(notifier_dev(notifier),
+			"async: looking up subdev for %pfw\n",
+			asc->match.fwnode);
+
+		/*
+		 * Matching by endpoint nodes may mean there are multiple
+		 * connections to a single device. This is only possible with
+		 * fwnode matching.
+		 */
+		if (fwnode_graph_is_endpoint(asc->match.fwnode)) {
+			list_for_each_entry(asd, &asd_list, asd_entry) {
+				if (async_subdev_has_connection(notifier, asd,
+								asc)) {
+					kref_get(&asd->kref);
+					goto found;
+				}
+			}
+		}
+	}
+
+	dev_dbg(notifier_dev(notifier), "not found, allocating new one\n");
+
+	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
+	if (!asd)
+		return -ENOMEM;
+
+	kref_init(&asd->kref);
+	INIT_LIST_HEAD(&asd->asc_list);
+	list_add(&asd->asd_entry, &asd_list);
+
+found:
+	list_add(&asc->asc_subdev_entry, &asd->asc_list);
+	asc->asd = asd;
+
+	return 0;
+}
+
 static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
 					  struct v4l2_async_connection *asc)
 {
+	int ret;
+
 	mutex_lock(&list_lock);
 
+	ret = v4l2_async_find_async_subdev(notifier, asc);
+	if (ret)
+		goto unlock;
+
 	list_add_tail(&asc->asc_entry, &notifier->waiting_list);
 
+unlock:
 	mutex_unlock(&list_lock);
 
-	return 0;
+	return ret;
 }
 
 struct v4l2_async_connection *
@@ -690,6 +823,7 @@ __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
 	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
+	asc->notifier = notifier;
 	asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
 	asc->match.fwnode = fwnode_handle_get(fwnode);
 
@@ -737,6 +871,7 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 	if (!asc)
 		return ERR_PTR(-ENOMEM);
 
+	asc->notifier = notifier;
 	asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
 	asc->match.i2c.adapter_id = adapter_id;
 	asc->match.i2c.address = address;
@@ -754,7 +889,11 @@ EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 struct v4l2_async_connection *
 v4l2_async_connection_unique(struct v4l2_subdev *sd)
 {
-	return sd->asd;
+	if (!list_is_singular(&sd->asd->asc_list))
+		return NULL;
+
+	return list_first_entry(&sd->asd->asc_list,
+				struct v4l2_async_connection, asc_subdev_entry);
 }
 EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
 
@@ -762,6 +901,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *subdev_notifier;
 	struct v4l2_async_notifier *notifier;
+	struct v4l2_async_connection *asc;
 	int ret;
 
 	/*
@@ -786,7 +926,6 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	list_for_each_entry(notifier, &notifier_list, notifier_entry) {
 		struct v4l2_device *v4l2_dev =
 			v4l2_async_nf_find_v4l2_dev(notifier);
-		struct v4l2_async_connection *asc;
 
 		if (!v4l2_dev)
 			continue;
@@ -823,11 +962,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 	if (subdev_notifier)
 		v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
 
-	if (sd->asd) {
-		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
-		sd->asd->sd = NULL;
-	}
-	v4l2_async_cleanup(sd);
+	if (asc)
+		v4l2_async_unbind_subdev_one(notifier, asc);
 
 	mutex_unlock(&list_lock);
 
@@ -837,6 +973,9 @@ EXPORT_SYMBOL(v4l2_async_register_subdev);
 
 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 {
+	struct v4l2_async_subdev *asd = sd->asd;
+	struct v4l2_async_connection *asc;
+
 	if (!sd->async_list.next)
 		return;
 
@@ -849,15 +988,19 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 	kfree(sd->subdev_notifier);
 	sd->subdev_notifier = NULL;
 
-	if (sd->asd) {
-		struct v4l2_async_notifier *notifier = sd->notifier;
+	if (asd) {
+		list_for_each_entry(asc, &asd->asc_list, asc_subdev_entry) {
+			list_move(&asc->asc_entry,
+				  &asc->notifier->waiting_list);
+
+			v4l2_async_unbind_subdev_one(asc->notifier, asc);
+		}
 
-		list_move(&sd->asd->asc_entry, &notifier->waiting_list);
-		v4l2_async_nf_call_unbind(notifier, sd, sd->asd);
-		sd->asd->sd = NULL;
+		WARN_ON(asd->bound);
 	}
 
-	v4l2_async_cleanup(sd);
+	list_del(&sd->async_list);
+	sd->async_list.next = NULL;
 
 	mutex_unlock(&list_lock);
 }
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 6e0f9a4965aa5..af02d63fa1ab4 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -8,6 +8,7 @@
 #ifndef V4L2_ASYNC_H
 #define V4L2_ASYNC_H
 
+#include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 
@@ -62,27 +63,49 @@ struct v4l2_async_match_desc {
 };
 
 /**
- * struct v4l2_async_connection - connection descriptor, as known to a bridge
+ * struct v4l2_async_subdev - sub-device descriptor
  *
+ * @kref:	kref for refcounting the subdev
+ * @asd_entry:	Entry in the list of async sub-devices
+ * @asc_list:	head for struct v4l2_async_connection.asd_entry list
+ * @sd:		the related sub-device
+ * @bound:	How many times a sub-device has been bound (by a link)
+ */
+struct v4l2_async_subdev {
+	struct kref kref;
+	struct list_head asd_entry;
+	struct list_head asc_list;
+	struct v4l2_subdev *sd;
+	int bound;
+};
+
+/**
+ * struct v4l2_async_connection - sub-device connection descriptor, as known to
+ *				  a bridge
+ *
+ * @asd:	the async sub-device related to this connection
  * @match:	struct of match type and per-bus type matching data sets
+ * @notifier:	the async notifier the connection is related to
  * @asc_entry:	used to add struct v4l2_async_connection objects to the
  *		notifier @waiting_list or @done_list
- * @sd:		the related sub-device
+ * @asc_subdev_entry:	entry in struct v4l2_async_subdev.asc_list list
  *
- * When this struct is used as a member in a driver specific struct,
- * the driver specific struct shall contain the &struct
- * v4l2_async_connection as its first member.
+ * When this struct is used as a member in a driver specific struct, the driver
+ * specific struct shall contain the &struct v4l2_async_connection as its first
+ * member.
  */
 struct v4l2_async_connection {
+	struct v4l2_async_subdev *asd;
 	struct v4l2_async_match_desc match;
+	struct v4l2_async_notifier *notifier;
 	struct list_head asc_entry;
-	struct v4l2_subdev *sd;
+	struct list_head asc_subdev_entry;
 };
 
 /**
  * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations
- * @bound:	a subdevice driver has successfully probed one of the subdevices
- * @complete:	All subdevices have been probed successfully. The complete
+ * @bound:	a sub-device has been bound by the given connection
+ * @complete:	All connections have been bound successfully. The complete
  *		callback is only executed for the root notifier.
  * @unbind:	a subdevice is leaving
  * @destroy:	the asc is about to be freed
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index f689c8eae2803..d2cf9bbae2fb3 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1065,7 +1065,7 @@ struct v4l2_subdev {
 	struct device *dev;
 	struct fwnode_handle *fwnode;
 	struct list_head async_list;
-	struct v4l2_async_connection *asd;
+	struct v4l2_async_subdev *asd;
 	struct v4l2_async_notifier *notifier;
 	struct v4l2_async_notifier *subdev_notifier;
 	struct v4l2_subdev_platform_data *pdata;
-- 
2.30.2


  parent reply	other threads:[~2023-05-16  9:57 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-16  9:54 [PATCH v2 00/31] Separate links and async sub-devices Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 01/31] media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 02/31] media: Documentation: v4l: Document missing async subdev function Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 03/31] media: xilinx-vipp: Clean up bound async notifier callback Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 04/31] media: v4l: async: Add some debug prints Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 05/31] media: v4l: async: Clean testing for duplicated async subdevs Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 06/31] media: v4l: async: Drop unneeded list entry initialisation Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 07/31] media: v4l: async: Don't check whether asd is NULL in validity check Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 08/31] media: v4l: async: Make V4L2 async match information a struct Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 09/31] media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 10/31] media: v4l: async: Only pass match information for async subdev validation Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 11/31] media: v4l: async: Clean up list heads and entries Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 12/31] media: v4l: async: Simplify async sub-device fwnode matching Sakari Ailus
2023-05-16  9:54 ` [PATCH v2 13/31] media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 14/31] media: v4l: async: Clean up error handling in v4l2_async_match_notify Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 15/31] media: v4l: async: Drop duplicate handling when adding connections Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 16/31] media: v4l: async: Rework internal lists Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 17/31] media: v4l: async: Obtain async connection based on sub-device Sakari Ailus
2023-05-16  9:55 ` Sakari Ailus [this message]
2023-05-16  9:55 ` [PATCH v2 19/31] media: v4l: async: Try more connections Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 20/31] media: v4l: async: Support fwnode endpoint list matching for subdevs Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 21/31] media: adv748x: Return to endpoint matching Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 22/31] media: pxa_camera: Fix probe error handling Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 23/31] media: pxa_camera: Register V4L2 device early, fix " Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 24/31] media: marvell: cafe: Register V4L2 device earlier Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 25/31] media: am437x-vpfe: Register V4L2 device early Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 26/31] media: omap3isp: Initialise V4L2 async notifier later Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 27/31] media: xilinx-vipp: Init async notifier after registering V4L2 device Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 28/31] media: davinci: " Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 29/31] media: qcom: Initialise V4L2 async notifier later Sakari Ailus
2023-05-16  9:55 ` [PATCH v2 30/31] media: v4l: async: Set v4l2_device in async notifier init Sakari Ailus
2023-05-16 20:46   ` kernel test robot
2023-05-16  9:55 ` [PATCH v2 31/31] media: Documentation: v4l: Document sub-device notifiers Sakari Ailus
2023-05-17  7:57 ` [PATCH v2 00/31] Separate links and async sub-devices Alexander Stein
2023-05-17  9:15   ` Sakari Ailus
2023-05-17  9:16   ` Sakari Ailus
2023-05-17  9:43 ` Philipp Zabel
2023-05-17 11:24   ` Marcel Ziswiler
2023-05-17 12:06     ` Philipp Zabel
2023-05-17 21:33   ` Sakari Ailus

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230516095517.611711-19-sakari.ailus@linux.intel.com \
    --to=sakari.ailus@linux.intel.com \
    --cc=aishwarya.kothari@toradex.com \
    --cc=bingbu.cao@intel.com \
    --cc=francesco@dolcini.it \
    --cc=hverkuil@xs4all.nl \
    --cc=hyun.kwon@xilinx.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=rfoss@kernel.org \
    --cc=todor.too@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.