linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 01/17] media: v4l2-fwnode: ignore endpoints that have no remote port parent
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Sakari Ailus,
	Sebastian Reichel, Hans Verkuil, Niklas Söderlund,
	open list

Documentation/devicetree/bindings/media/video-interfaces.txt states that
the 'remote-endpoint' property is optional.

So v4l2_async_notifier_fwnode_parse_endpoint() should not return error
if the endpoint has no remote port parent. Just ignore the endpoint,
skip adding an asd to the notifier and return 0.
__v4l2_async_notifier_parse_fwnode_endpoints() will then continue
parsing the remaining port endpoints of the device.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
---
Changes since v5:
- none
Changes since v4:
- none
Changes since v3:
- none
Changes since v2:
- none
Changes since v1:
- don't pass an empty endpoint to the parse_endpoint callback,
  v4l2_async_notifier_fwnode_parse_endpoint() now just ignores them
  and returns success. The current users of
  v4l2_async_notifier_parse_fwnode_endpoints() (omap3isp, rcar-vin,
  intel-ipu3) no longer need modification.
---
 drivers/media/v4l2-core/v4l2-fwnode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 3f77aa3..3240c2a 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -363,7 +363,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 		fwnode_graph_get_remote_port_parent(endpoint);
 	if (!asd->match.fwnode) {
 		dev_warn(dev, "bad remote port parent\n");
-		ret = -EINVAL;
+		ret = -ENOTCONN;
 		goto out_err;
 	}
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
  2018-07-09 22:39 ` [PATCH v6 01/17] media: v4l2-fwnode: ignore endpoints that have no remote port parent Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-09-24 17:06   ` Mauro Carvalho Chehab
  2018-07-09 22:39 ` [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Sakari Ailus,
	Niklas Söderlund, Hans Verkuil, Sebastian Reichel,
	open list

Generalize v4l2_async_notifier_fwnode_has_async_subdev() to allow
searching for any type of async subdev, not just fwnodes. Rename to
v4l2_async_notifier_has_async_subdev() and pass it an asd pointer.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- none
Changes since v4:
- none
Changes since v3:
- removed TODO to support asd compare with CUSTOM match type in
  asd_equal().
Changes since v2:
- code optimization in asd_equal(), and remove unneeded braces,
  suggested by Sakari Ailus.
Changes since v1:
- none
---
 drivers/media/v4l2-core/v4l2-async.c | 73 +++++++++++++++++++++---------------
 1 file changed, 43 insertions(+), 30 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 2b08d03..0e7e529 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -124,6 +124,31 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
 	return NULL;
 }
 
+/* Compare two asd's for equivalence */
+static bool asd_equal(struct v4l2_async_subdev *asd_x,
+		      struct v4l2_async_subdev *asd_y)
+{
+	if (asd_x->match_type != asd_y->match_type)
+		return false;
+
+	switch (asd_x->match_type) {
+	case V4L2_ASYNC_MATCH_DEVNAME:
+		return strcmp(asd_x->match.device_name,
+			      asd_y->match.device_name) == 0;
+	case V4L2_ASYNC_MATCH_I2C:
+		return asd_x->match.i2c.adapter_id ==
+			asd_y->match.i2c.adapter_id &&
+			asd_x->match.i2c.address ==
+			asd_y->match.i2c.address;
+	case V4L2_ASYNC_MATCH_FWNODE:
+		return asd_x->match.fwnode == asd_y->match.fwnode;
+	default:
+		break;
+	}
+
+	return false;
+}
+
 /* Find the sub-device notifier registered by a sub-device driver. */
 static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
 	struct v4l2_subdev *sd)
@@ -308,29 +333,22 @@ static void v4l2_async_notifier_unbind_all_subdevs(
 	notifier->parent = NULL;
 }
 
-/* See if an fwnode can be found in a notifier's lists. */
-static bool __v4l2_async_notifier_fwnode_has_async_subdev(
-	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode)
+/* See if an async sub-device can be found in a notifier's lists. */
+static bool __v4l2_async_notifier_has_async_subdev(
+	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd)
 {
-	struct v4l2_async_subdev *asd;
+	struct v4l2_async_subdev *asd_y;
 	struct v4l2_subdev *sd;
 
-	list_for_each_entry(asd, &notifier->waiting, list) {
-		if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
-			continue;
-
-		if (asd->match.fwnode == fwnode)
+	list_for_each_entry(asd_y, &notifier->waiting, list)
+		if (asd_equal(asd, asd_y))
 			return true;
-	}
 
 	list_for_each_entry(sd, &notifier->done, async_list) {
 		if (WARN_ON(!sd->asd))
 			continue;
 
-		if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
-			continue;
-
-		if (sd->asd->match.fwnode == fwnode)
+		if (asd_equal(asd, sd->asd))
 			return true;
 	}
 
@@ -338,32 +356,28 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
 }
 
 /*
- * Find out whether an async sub-device was set up for an fwnode already or
+ * Find out whether an async sub-device was set up already or
  * whether it exists in a given notifier before @this_index.
  */
-static bool v4l2_async_notifier_fwnode_has_async_subdev(
-	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode,
+static bool v4l2_async_notifier_has_async_subdev(
+	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd,
 	unsigned int this_index)
 {
 	unsigned int j;
 
 	lockdep_assert_held(&list_lock);
 
-	/* Check that an fwnode is not being added more than once. */
+	/* Check that an asd is not being added more than once. */
 	for (j = 0; j < this_index; j++) {
-		struct v4l2_async_subdev *asd = notifier->subdevs[this_index];
-		struct v4l2_async_subdev *other_asd = notifier->subdevs[j];
+		struct v4l2_async_subdev *asd_y = notifier->subdevs[j];
 
-		if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE &&
-		    asd->match.fwnode ==
-		    other_asd->match.fwnode)
+		if (asd_equal(asd, asd_y))
 			return true;
 	}
 
-	/* Check than an fwnode did not exist in other notifiers. */
+	/* Check that an asd does not exist in other notifiers. */
 	list_for_each_entry(notifier, &notifier_list, list)
-		if (__v4l2_async_notifier_fwnode_has_async_subdev(
-			    notifier, fwnode))
+		if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
 			return true;
 
 	return false;
@@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 		case V4L2_ASYNC_MATCH_CUSTOM:
 		case V4L2_ASYNC_MATCH_DEVNAME:
 		case V4L2_ASYNC_MATCH_I2C:
-			break;
 		case V4L2_ASYNC_MATCH_FWNODE:
-			if (v4l2_async_notifier_fwnode_has_async_subdev(
-				    notifier, asd->match.fwnode, i)) {
+			if (v4l2_async_notifier_has_async_subdev(
+				    notifier, asd, i)) {
 				dev_err(dev,
-					"fwnode has already been registered or in notifier's subdev list\n");
+					"asd has already been registered or in notifier's subdev list\n");
 				ret = -EEXIST;
 				goto err_unlock;
 			}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
  2018-07-09 22:39 ` [PATCH v6 01/17] media: v4l2-fwnode: ignore endpoints that have no remote port parent Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-08-03 15:13   ` jacopo mondi
  2018-07-09 22:39 ` [PATCH v6 04/17] media: v4l2: async: Add convenience functions to allocate and add asd's Steve Longerbeam
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Niklas Söderlund,
	Sakari Ailus, Sebastian Reichel, Hans Verkuil, open list

v4l2_async_notifier_add_subdev() adds an asd to the notifier. It checks
that no other equivalent asd's have already been added to this notifier's
asd list, or to other registered notifier's waiting or done lists, and
increments num_subdevs.

v4l2_async_notifier_add_subdev() does not make use of the notifier subdevs
array, otherwise it would have to re-allocate the array every time the
function was called. In place of the subdevs array, the function adds
the newly allocated asd to a new master asd_list. The function will
return error with a WARN() if it is ever called with the subdevs array
allocated.

Drivers are now required to call a v4l2_async_notifier_init(), before the
first call to v4l2_async_notifier_add_subdev(), in order to initialize
the asd_list.

In v4l2_async_notifier_has_async_subdev(), __v4l2_async_notifier_register(),
and v4l2_async_notifier_cleanup(), maintain backward compatibility with
the subdevs array, by alternatively operate on the subdevs array or a
non-empty notifier->asd_list.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- export v4l2_async_notifier_init() which must be called by drivers.
  Suggested by Sakari Ailus.
Changes since v4:
- none
Changes since v3:
- init notifier lists after the sanity checks.
Changes since v2:
- add a NULL asd pointer check to v4l2_async_notifier_asd_valid().
Changes since v1:
- none
---
 drivers/media/v4l2-core/v4l2-async.c | 189 +++++++++++++++++++++++++++--------
 include/media/v4l2-async.h           |  34 ++++++-
 2 files changed, 180 insertions(+), 43 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 0e7e529..8e52df2 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -363,16 +363,26 @@ static bool v4l2_async_notifier_has_async_subdev(
 	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd,
 	unsigned int this_index)
 {
+	struct v4l2_async_subdev *asd_y;
 	unsigned int j;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	for (j = 0; j < this_index; j++) {
-		struct v4l2_async_subdev *asd_y = notifier->subdevs[j];
-
-		if (asd_equal(asd, asd_y))
-			return true;
+	if (notifier->subdevs) {
+		for (j = 0; j < this_index; j++) {
+			asd_y = notifier->subdevs[j];
+			if (asd_equal(asd, asd_y))
+				return true;
+		}
+	} else {
+		j = 0;
+		list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
+			if (j++ >= this_index)
+				break;
+			if (asd_equal(asd, asd_y))
+				return true;
+		}
 	}
 
 	/* Check that an asd does not exist in other notifiers. */
@@ -383,10 +393,46 @@ static bool v4l2_async_notifier_has_async_subdev(
 	return false;
 }
 
-static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
+					 struct v4l2_async_subdev *asd,
+					 unsigned int this_index)
 {
 	struct device *dev =
 		notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
+
+	if (!asd)
+		return -EINVAL;
+
+	switch (asd->match_type) {
+	case V4L2_ASYNC_MATCH_CUSTOM:
+	case V4L2_ASYNC_MATCH_DEVNAME:
+	case V4L2_ASYNC_MATCH_I2C:
+	case V4L2_ASYNC_MATCH_FWNODE:
+		if (v4l2_async_notifier_has_async_subdev(notifier, asd,
+							 this_index))
+			return -EEXIST;
+		break;
+	default:
+		dev_err(dev, "Invalid match type %u on %p\n",
+			asd->match_type, asd);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
+{
+	mutex_lock(&list_lock);
+
+	INIT_LIST_HEAD(&notifier->asd_list);
+
+	mutex_unlock(&list_lock);
+}
+EXPORT_SYMBOL(v4l2_async_notifier_init);
+
+static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+{
 	struct v4l2_async_subdev *asd;
 	int ret;
 	int i;
@@ -399,29 +445,25 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 
 	mutex_lock(&list_lock);
 
-	for (i = 0; i < notifier->num_subdevs; i++) {
-		asd = notifier->subdevs[i];
+	if (notifier->subdevs) {
+		for (i = 0; i < notifier->num_subdevs; i++) {
+			asd = notifier->subdevs[i];
 
-		switch (asd->match_type) {
-		case V4L2_ASYNC_MATCH_CUSTOM:
-		case V4L2_ASYNC_MATCH_DEVNAME:
-		case V4L2_ASYNC_MATCH_I2C:
-		case V4L2_ASYNC_MATCH_FWNODE:
-			if (v4l2_async_notifier_has_async_subdev(
-				    notifier, asd, i)) {
-				dev_err(dev,
-					"asd has already been registered or in notifier's subdev list\n");
-				ret = -EEXIST;
+			ret = v4l2_async_notifier_asd_valid(notifier, asd, i);
+			if (ret)
 				goto err_unlock;
-			}
-			break;
-		default:
-			dev_err(dev, "Invalid match type %u on %p\n",
-				asd->match_type, asd);
-			ret = -EINVAL;
-			goto err_unlock;
+
+			list_add_tail(&asd->list, &notifier->waiting);
+		}
+	} else {
+		i = 0;
+		list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+			ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
+			if (ret)
+				goto err_unlock;
+
+			list_add_tail(&asd->list, &notifier->waiting);
 		}
-		list_add_tail(&asd->list, &notifier->waiting);
 	}
 
 	ret = v4l2_async_notifier_try_all_subdevs(notifier);
@@ -511,36 +553,99 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL(v4l2_async_notifier_unregister);
 
-void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
+static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 {
+	struct v4l2_async_subdev *asd, *tmp;
 	unsigned int i;
 
-	if (!notifier || !notifier->max_subdevs)
+	if (!notifier)
 		return;
 
-	for (i = 0; i < notifier->num_subdevs; i++) {
-		struct v4l2_async_subdev *asd = notifier->subdevs[i];
+	if (notifier->subdevs) {
+		if (!notifier->max_subdevs)
+			return;
 
-		switch (asd->match_type) {
-		case V4L2_ASYNC_MATCH_FWNODE:
-			fwnode_handle_put(asd->match.fwnode);
-			break;
-		default:
-			WARN_ON_ONCE(true);
-			break;
+		for (i = 0; i < notifier->num_subdevs; i++) {
+			asd = notifier->subdevs[i];
+
+			switch (asd->match_type) {
+			case V4L2_ASYNC_MATCH_FWNODE:
+				fwnode_handle_put(asd->match.fwnode);
+				break;
+			default:
+				break;
+			}
+
+			kfree(asd);
 		}
 
-		kfree(asd);
+		notifier->max_subdevs = 0;
+		kvfree(notifier->subdevs);
+		notifier->subdevs = NULL;
+	} else {
+		list_for_each_entry_safe(asd, tmp,
+					 &notifier->asd_list, asd_list) {
+			switch (asd->match_type) {
+			case V4L2_ASYNC_MATCH_FWNODE:
+				fwnode_handle_put(asd->match.fwnode);
+				break;
+			default:
+				break;
+			}
+
+			list_del(&asd->asd_list);
+			kfree(asd);
+		}
 	}
 
-	notifier->max_subdevs = 0;
 	notifier->num_subdevs = 0;
+}
+
+void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
+{
+	mutex_lock(&list_lock);
+
+	__v4l2_async_notifier_cleanup(notifier);
 
-	kvfree(notifier->subdevs);
-	notifier->subdevs = NULL;
+	mutex_unlock(&list_lock);
 }
 EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
 
+int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+				   struct v4l2_async_subdev *asd)
+{
+	int ret;
+
+	mutex_lock(&list_lock);
+
+	if (notifier->num_subdevs >= V4L2_MAX_SUBDEVS) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	/*
+	 * If caller uses this function, it cannot also allocate and
+	 * place asd's in the notifier->subdevs array.
+	 */
+	if (WARN_ON(notifier->subdevs)) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	ret = v4l2_async_notifier_asd_valid(notifier, asd,
+					    notifier->num_subdevs);
+	if (ret)
+		goto unlock;
+
+	list_add_tail(&asd->asd_list, &notifier->asd_list);
+	notifier->num_subdevs++;
+
+unlock:
+	mutex_unlock(&list_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
+
 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *subdev_notifier;
@@ -614,7 +719,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
 	mutex_lock(&list_lock);
 
 	__v4l2_async_notifier_unregister(sd->subdev_notifier);
-	v4l2_async_notifier_cleanup(sd->subdev_notifier);
+	__v4l2_async_notifier_cleanup(sd->subdev_notifier);
 	kfree(sd->subdev_notifier);
 	sd->subdev_notifier = NULL;
 
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 1592d32..ab4d7ac 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -73,6 +73,8 @@ enum v4l2_async_match_type {
  * @match.custom.priv:
  *		Driver-specific private struct with match parameters
  *		to be used if %V4L2_ASYNC_MATCH_CUSTOM.
+ * @asd_list:	used to add struct v4l2_async_subdev objects to the
+ *		master notifier @asd_list
  * @list:	used to link struct v4l2_async_subdev objects, waiting to be
  *		probed, to a notifier->waiting list
  *
@@ -98,6 +100,7 @@ struct v4l2_async_subdev {
 
 	/* v4l2-async core private: not to be used by drivers */
 	struct list_head list;
+	struct list_head asd_list;
 };
 
 /**
@@ -127,6 +130,7 @@ struct v4l2_async_notifier_operations {
  * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
  * @sd:		sub-device that registered the notifier, NULL otherwise
  * @parent:	parent notifier
+ * @asd_list:	master list of struct v4l2_async_subdev, replaces @subdevs
  * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
  * @done:	list of struct v4l2_subdev, already probed
  * @list:	member in a global list of notifiers
@@ -139,12 +143,38 @@ struct v4l2_async_notifier {
 	struct v4l2_device *v4l2_dev;
 	struct v4l2_subdev *sd;
 	struct v4l2_async_notifier *parent;
+	struct list_head asd_list;
 	struct list_head waiting;
 	struct list_head done;
 	struct list_head list;
 };
 
 /**
+ * v4l2_async_notifier_init - Initialize a notifier.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ *
+ * This function initializes the notifier @asd_list. It must be called
+ * before the first call to @v4l2_async_notifier_add_subdev.
+ */
+void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
+
+/**
+ * v4l2_async_notifier_add_subdev - Add an async subdev to the
+ *				notifier's master asd list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @asd: pointer to &struct v4l2_async_subdev
+ *
+ * This can be used before registering a notifier to add an
+ * asd to the notifiers @asd_list. If the caller uses this
+ * method to compose an asd list, it must never allocate
+ * or place asd's in the @subdevs array.
+ */
+int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+				   struct v4l2_async_subdev *asd);
+
+/**
  * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
  *
  * @v4l2_dev: pointer to &struct v4l2_device
@@ -177,7 +207,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
  * Release memory resources related to a notifier, including the async
  * sub-devices allocated for the purposes of the notifier but not the notifier
  * itself. The user is responsible for calling this function to clean up the
- * notifier after calling @v4l2_async_notifier_parse_fwnode_endpoints or
+ * notifier after calling
+ * @v4l2_async_notifier_add_subdev,
+ * @v4l2_async_notifier_parse_fwnode_endpoints or
  * @v4l2_fwnode_reference_parse_sensor_common.
  *
  * There is no harm from calling v4l2_async_notifier_cleanup in other
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 04/17] media: v4l2: async: Add convenience functions to allocate and add asd's
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (2 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 05/17] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Niklas Söderlund,
	Sakari Ailus, Sebastian Reichel, Hans Verkuil, open list

Add these convenience functions, which allocate an asd of match type
fwnode, i2c, or device-name, of size asd_struct_size, and then adds
them to the notifier asd_list.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 76 ++++++++++++++++++++++++++++++++++++
 include/media/v4l2-async.h           | 62 +++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 8e52df2..e60a82a 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -646,6 +646,82 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 }
 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
 
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+				      struct fwnode_handle *fwnode,
+				      unsigned int asd_struct_size)
+{
+	struct v4l2_async_subdev *asd;
+	int ret;
+
+	asd = kzalloc(asd_struct_size, GFP_KERNEL);
+	if (!asd)
+		return ERR_PTR(-ENOMEM);
+
+	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+	asd->match.fwnode = fwnode;
+
+	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	if (ret) {
+		kfree(asd);
+		return ERR_PTR(ret);
+	}
+
+	return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
+
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+				   int adapter_id, unsigned short address,
+				   unsigned int asd_struct_size)
+{
+	struct v4l2_async_subdev *asd;
+	int ret;
+
+	asd = kzalloc(asd_struct_size, GFP_KERNEL);
+	if (!asd)
+		return ERR_PTR(-ENOMEM);
+
+	asd->match_type = V4L2_ASYNC_MATCH_I2C;
+	asd->match.i2c.adapter_id = adapter_id;
+	asd->match.i2c.address = address;
+
+	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	if (ret) {
+		kfree(asd);
+		return ERR_PTR(ret);
+	}
+
+	return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_i2c_subdev);
+
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
+				       const char *device_name,
+				       unsigned int asd_struct_size)
+{
+	struct v4l2_async_subdev *asd;
+	int ret;
+
+	asd = kzalloc(asd_struct_size, GFP_KERNEL);
+	if (!asd)
+		return ERR_PTR(-ENOMEM);
+
+	asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
+	asd->match.device_name = device_name;
+
+	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	if (ret) {
+		kfree(asd);
+		return ERR_PTR(ret);
+	}
+
+	return asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev);
+
 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
 	struct v4l2_async_notifier *subdev_notifier;
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index ab4d7ac..3489e4c 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -175,6 +175,68 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd);
 
 /**
+ * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async
+ *				subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @fwnode: fwnode handle of the sub-device to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ *		     sizeof(struct v4l2_async_subdev). The &struct
+ *		     v4l2_async_subdev shall be the first member of
+ *		     the driver's async sub-device struct, i.e. both
+ *		     begin at the same memory address.
+ *
+ * This can be used before registering a notifier to add a
+ * fwnode-matched asd to the notifiers master asd_list. If the caller
+ * uses this method to compose an asd list, it must never allocate
+ * or place asd's in the @subdevs array.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
+				      struct fwnode_handle *fwnode,
+				      unsigned int asd_struct_size);
+
+/**
+ * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
+ *				subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @adapter_id: I2C adapter ID to be matched
+ * @address: I2C address of sub-device to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ *		     sizeof(struct v4l2_async_subdev). The &struct
+ *		     v4l2_async_subdev shall be the first member of
+ *		     the driver's async sub-device struct, i.e. both
+ *		     begin at the same memory address.
+ *
+ * Same as above but for I2C matched sub-devices.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
+				   int adapter_id, unsigned short address,
+				   unsigned int asd_struct_size);
+
+/**
+ * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name
+ *				async subdev to the notifier's master asd_list.
+ *
+ * @notifier: pointer to &struct v4l2_async_notifier
+ * @device_name: device name string to be matched
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ *		     sizeof(struct v4l2_async_subdev). The &struct
+ *		     v4l2_async_subdev shall be the first member of
+ *		     the driver's async sub-device struct, i.e. both
+ *		     begin at the same memory address.
+ *
+ * Same as above but for device-name matched sub-devices.
+ */
+struct v4l2_async_subdev *
+v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
+				       const char *device_name,
+				       unsigned int asd_struct_size);
+
+
+/**
  * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
  *
  * @v4l2_dev: pointer to &struct v4l2_device
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 05/17] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (3 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 04/17] media: v4l2: async: Add convenience functions to allocate and add asd's Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tian Shu Qiu, Jian Xu Zheng, Mauro Carvalho Chehab,
	Laurent Pinchart, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list,
	open list:MEDIA DRIVERS FOR RENESAS - VIN

The fwnode endpoint and reference parsing functions in v4l2-fwnode.c
are modified to make use of v4l2_async_notifier_add_subdev().
As a result the notifier->subdevs array is no longer allocated or
re-allocated, and by extension the max_subdevs value is also no
longer needed.

Callers of the fwnode endpoint and reference parsing functions must now
first initialize the notifier with a call to v4l2_async_notifier_init().
This includes the function v4l2_async_register_subdev_sensor_common(),
and the intel-ipu3, omap3isp, and rcar-vin drivers.

Since the notifier->subdevs array is no longer allocated in the
fwnode endpoint and reference parsing functions, the callers of
those functions must never reference that array, since it is now
NULL. Of the drivers that make use of the fwnode/ref parsing,
only the intel-ipu3 driver references the ->subdevs[] array,
(in the notifier completion callback), so that driver has been
modified to iterate through the notifier->asd_list instead.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- drivers must now initialize the notifier. Suggested by Sakari Ailus.
---
 drivers/media/pci/intel/ipu3/ipu3-cio2.c    |  12 +--
 drivers/media/platform/omap3isp/isp.c       |   1 +
 drivers/media/platform/rcar-vin/rcar-core.c |   4 +
 drivers/media/v4l2-core/v4l2-async.c        |   4 -
 drivers/media/v4l2-core/v4l2-fwnode.c       | 132 ++++++----------------------
 include/media/v4l2-async.h                  |   2 -
 include/media/v4l2-fwnode.h                 |  22 ++---
 7 files changed, 52 insertions(+), 125 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 2902715..4a5f7c3 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -1435,13 +1435,13 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
 	struct cio2_device *cio2 = container_of(notifier, struct cio2_device,
 						notifier);
 	struct sensor_async_subdev *s_asd;
+	struct v4l2_async_subdev *asd;
 	struct cio2_queue *q;
-	unsigned int i, pad;
+	unsigned int pad;
 	int ret;
 
-	for (i = 0; i < notifier->num_subdevs; i++) {
-		s_asd = container_of(cio2->notifier.subdevs[i],
-				     struct sensor_async_subdev, asd);
+	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
+		s_asd = container_of(asd, struct sensor_async_subdev, asd);
 		q = &cio2->queue[s_asd->csi2.port];
 
 		for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
@@ -1463,7 +1463,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
 		if (ret) {
 			dev_err(&cio2->pci_dev->dev,
 				"failed to create link for %s\n",
-				cio2->queue[i].sensor->name);
+				q->sensor->name);
 			return ret;
 		}
 	}
@@ -1499,6 +1499,8 @@ static int cio2_notifier_init(struct cio2_device *cio2)
 {
 	int ret;
 
+	v4l2_async_notifier_init(&cio2->notifier);
+
 	ret = v4l2_async_notifier_parse_fwnode_endpoints(
 		&cio2->pci_dev->dev, &cio2->notifier,
 		sizeof(struct sensor_async_subdev),
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 03354d51..1211bfe 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2220,6 +2220,7 @@ static int isp_probe(struct platform_device *pdev)
 
 	mutex_init(&isp->isp_mutex);
 	spin_lock_init(&isp->stat_lock);
+	v4l2_async_notifier_init(&isp->notifier);
 
 	ret = v4l2_async_notifier_parse_fwnode_endpoints(
 		&pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev),
diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index 8843367..10ee1859 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -615,6 +615,8 @@ static int rvin_parallel_init(struct rvin_dev *vin)
 {
 	int ret;
 
+	v4l2_async_notifier_init(&vin->notifier);
+
 	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
 		vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity),
 		0, rvin_parallel_parse_v4l2);
@@ -807,6 +809,8 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
 		return 0;
 	}
 
+	v4l2_async_notifier_init(&vin->group->notifier);
+
 	/*
 	 * Have all VIN's look for CSI-2 subdevices. Some subdevices will
 	 * overlap but the parser function can handle it, so each subdevice
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index e60a82a..78cf1a9 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -562,9 +562,6 @@ static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 		return;
 
 	if (notifier->subdevs) {
-		if (!notifier->max_subdevs)
-			return;
-
 		for (i = 0; i < notifier->num_subdevs; i++) {
 			asd = notifier->subdevs[i];
 
@@ -579,7 +576,6 @@ static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 			kfree(asd);
 		}
 
-		notifier->max_subdevs = 0;
 		kvfree(notifier->subdevs);
 		notifier->subdevs = NULL;
 	} else {
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 3240c2a..67ad333 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -316,33 +316,6 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
 }
 EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
 
-static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
-				       unsigned int max_subdevs)
-{
-	struct v4l2_async_subdev **subdevs;
-
-	if (max_subdevs <= notifier->max_subdevs)
-		return 0;
-
-	subdevs = kvmalloc_array(
-		max_subdevs, sizeof(*notifier->subdevs),
-		GFP_KERNEL | __GFP_ZERO);
-	if (!subdevs)
-		return -ENOMEM;
-
-	if (notifier->subdevs) {
-		memcpy(subdevs, notifier->subdevs,
-		       sizeof(*subdevs) * notifier->num_subdevs);
-
-		kvfree(notifier->subdevs);
-	}
-
-	notifier->subdevs = subdevs;
-	notifier->max_subdevs = max_subdevs;
-
-	return 0;
-}
-
 static int v4l2_async_notifier_fwnode_parse_endpoint(
 	struct device *dev, struct v4l2_async_notifier *notifier,
 	struct fwnode_handle *endpoint, unsigned int asd_struct_size,
@@ -387,8 +360,13 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 	if (ret < 0)
 		goto out_err;
 
-	notifier->subdevs[notifier->num_subdevs] = asd;
-	notifier->num_subdevs++;
+	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	if (ret < 0) {
+		/* not an error if asd already exists */
+		if (ret == -EEXIST)
+			ret = 0;
+		goto out_err;
+	}
 
 	return 0;
 
@@ -407,8 +385,7 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
 			    struct v4l2_async_subdev *asd))
 {
 	struct fwnode_handle *fwnode;
-	unsigned int max_subdevs = notifier->max_subdevs;
-	int ret;
+	int ret = 0;
 
 	if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
 		return -EINVAL;
@@ -428,40 +405,6 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
 			struct fwnode_endpoint ep;
 
 			ret = fwnode_graph_parse_endpoint(fwnode, &ep);
-			if (ret) {
-				fwnode_handle_put(fwnode);
-				return ret;
-			}
-
-			if (ep.port != port)
-				continue;
-		}
-		max_subdevs++;
-	}
-
-	/* No subdevs to add? Return here. */
-	if (max_subdevs == notifier->max_subdevs)
-		return 0;
-
-	ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
-	if (ret)
-		return ret;
-
-	for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
-				     dev_fwnode(dev), fwnode)); ) {
-		struct fwnode_handle *dev_fwnode;
-		bool is_available;
-
-		dev_fwnode = fwnode_graph_get_port_parent(fwnode);
-		is_available = fwnode_device_is_available(dev_fwnode);
-		fwnode_handle_put(dev_fwnode);
-		if (!is_available)
-			continue;
-
-		if (has_port) {
-			struct fwnode_endpoint ep;
-
-			ret = fwnode_graph_parse_endpoint(fwnode, &ep);
 			if (ret)
 				break;
 
@@ -469,11 +412,6 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
 				continue;
 		}
 
-		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
-			ret = -EINVAL;
-			break;
-		}
-
 		ret = v4l2_async_notifier_fwnode_parse_endpoint(
 			dev, notifier, fwnode, asd_struct_size, parse_endpoint);
 		if (ret < 0)
@@ -544,31 +482,23 @@ static int v4l2_fwnode_reference_parse(
 	if (ret != -ENOENT && ret != -ENODATA)
 		return ret;
 
-	ret = v4l2_async_notifier_realloc(notifier,
-					  notifier->num_subdevs + index);
-	if (ret)
-		return ret;
-
 	for (index = 0; !fwnode_property_get_reference_args(
 		     dev_fwnode(dev), prop, NULL, 0, index, &args);
 	     index++) {
 		struct v4l2_async_subdev *asd;
 
-		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
-			ret = -EINVAL;
-			goto error;
-		}
+		asd = v4l2_async_notifier_add_fwnode_subdev(
+			notifier, args.fwnode, sizeof(*asd));
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
+			/* not an error if asd already exists */
+			if (ret == -EEXIST) {
+				fwnode_handle_put(args.fwnode);
+				continue;
+			}
 
-		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-		if (!asd) {
-			ret = -ENOMEM;
 			goto error;
 		}
-
-		notifier->subdevs[notifier->num_subdevs] = asd;
-		asd->match.fwnode = args.fwnode;
-		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		notifier->num_subdevs++;
 	}
 
 	return 0;
@@ -839,31 +769,23 @@ static int v4l2_fwnode_reference_parse_int_props(
 		index++;
 	} while (1);
 
-	ret = v4l2_async_notifier_realloc(notifier,
-					  notifier->num_subdevs + index);
-	if (ret)
-		return -ENOMEM;
-
 	for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
 					 dev_fwnode(dev), prop, index, props,
 					 nprops))); index++) {
 		struct v4l2_async_subdev *asd;
 
-		if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
-			ret = -EINVAL;
-			goto error;
-		}
+		asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+							    sizeof(*asd));
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
+			/* not an error if asd already exists */
+			if (ret == -EEXIST) {
+				fwnode_handle_put(fwnode);
+				continue;
+			}
 
-		asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
-		if (!asd) {
-			ret = -ENOMEM;
 			goto error;
 		}
-
-		notifier->subdevs[notifier->num_subdevs] = asd;
-		asd->match.fwnode = fwnode;
-		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		notifier->num_subdevs++;
 	}
 
 	return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
@@ -920,6 +842,8 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
 	if (!notifier)
 		return -ENOMEM;
 
+	v4l2_async_notifier_init(notifier);
+
 	ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
 							     notifier);
 	if (ret < 0)
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 3489e4c..16b1e2b 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -125,7 +125,6 @@ struct v4l2_async_notifier_operations {
  *
  * @ops:	notifier operations
  * @num_subdevs: number of subdevices used in the subdevs array
- * @max_subdevs: number of subdevices allocated in the subdevs array
  * @subdevs:	array of pointers to subdevice descriptors
  * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
  * @sd:		sub-device that registered the notifier, NULL otherwise
@@ -138,7 +137,6 @@ struct v4l2_async_notifier_operations {
 struct v4l2_async_notifier {
 	const struct v4l2_async_notifier_operations *ops;
 	unsigned int num_subdevs;
-	unsigned int max_subdevs;
 	struct v4l2_async_subdev **subdevs;
 	struct v4l2_device *v4l2_dev;
 	struct v4l2_subdev *sd;
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 9cccab6..ea7a8b2 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -247,7 +247,7 @@ typedef int (*parse_endpoint_func)(struct device *dev,
  *		    endpoint. Optional.
  *
  * Parse the fwnode endpoints of the @dev device and populate the async sub-
- * devices array of the notifier. The @parse_endpoint callback function is
+ * devices list in the notifier. The @parse_endpoint callback function is
  * called for each endpoint with the corresponding async sub-device pointer to
  * let the caller initialize the driver-specific part of the async sub-device
  * structure.
@@ -258,10 +258,11 @@ typedef int (*parse_endpoint_func)(struct device *dev,
  * This function may not be called on a registered notifier and may be called on
  * a notifier only once.
  *
- * Do not change the notifier's subdevs array, take references to the subdevs
- * array itself or change the notifier's num_subdevs field. This is because this
- * function allocates and reallocates the subdevs array based on parsing
- * endpoints.
+ * Do not allocate the notifier's subdevs array, or change the notifier's
+ * num_subdevs field. This is because this function uses
+ * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
+ * which is in-place-of the subdevs array which must remain unallocated
+ * and unused.
  *
  * The &struct v4l2_fwnode_endpoint passed to the callback function
  * @parse_endpoint is released once the function is finished. If there is a need
@@ -303,7 +304,7 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
  * devices). In this case the driver must know which ports to parse.
  *
  * Parse the fwnode endpoints of the @dev device on a given @port and populate
- * the async sub-devices array of the notifier. The @parse_endpoint callback
+ * the async sub-devices list of the notifier. The @parse_endpoint callback
  * function is called for each endpoint with the corresponding async sub-device
  * pointer to let the caller initialize the driver-specific part of the async
  * sub-device structure.
@@ -314,10 +315,11 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
  * This function may not be called on a registered notifier and may be called on
  * a notifier only once per port.
  *
- * Do not change the notifier's subdevs array, take references to the subdevs
- * array itself or change the notifier's num_subdevs field. This is because this
- * function allocates and reallocates the subdevs array based on parsing
- * endpoints.
+ * Do not allocate the notifier's subdevs array, or change the notifier's
+ * num_subdevs field. This is because this function uses
+ * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
+ * which is in-place-of the subdevs array which must remain unallocated
+ * and unused.
  *
  * The &struct v4l2_fwnode_endpoint passed to the callback function
  * @parse_endpoint is released once the function is finished. If there is a need
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (4 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 05/17] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-09-13 10:37   ` jacopo mondi
  2018-07-09 22:39 ` [PATCH v6 07/17] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Sakari Ailus,
	Sebastian Reichel, Hans Verkuil, Niklas Söderlund,
	open list

Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
for parsing a sub-device's fwnode port endpoints for connected remote
sub-devices, registering a sub-device notifier, and then registering
the sub-device itself.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- add call to v4l2_async_notifier_init().
Changes since v4:
- none
Changes since v3:
- remove support for port sub-devices, such sub-devices will have to
  role their own.
Changes since v2:
- fix error-out path in v4l2_async_register_fwnode_subdev() that forgot
  to put device.
Changes since v1:
- add #include <media/v4l2-subdev.h> to v4l2-fwnode.h for
  'struct v4l2_subdev' declaration.
---
 drivers/media/v4l2-core/v4l2-fwnode.c | 64 +++++++++++++++++++++++++++++++++++
 include/media/v4l2-fwnode.h           | 38 +++++++++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 67ad333..94d867a 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -872,6 +872,70 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
 
+int v4l2_async_register_fwnode_subdev(
+	struct v4l2_subdev *sd, size_t asd_struct_size,
+	unsigned int *ports, unsigned int num_ports,
+	int (*parse_endpoint)(struct device *dev,
+			      struct v4l2_fwnode_endpoint *vep,
+			      struct v4l2_async_subdev *asd))
+{
+	struct v4l2_async_notifier *notifier;
+	struct device *dev = sd->dev;
+	struct fwnode_handle *fwnode;
+	int ret;
+
+	if (WARN_ON(!dev))
+		return -ENODEV;
+
+	fwnode = dev_fwnode(dev);
+	if (!fwnode_device_is_available(fwnode))
+		return -ENODEV;
+
+	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+	if (!notifier)
+		return -ENOMEM;
+
+	v4l2_async_notifier_init(notifier);
+
+	if (!ports) {
+		ret = v4l2_async_notifier_parse_fwnode_endpoints(
+			dev, notifier, asd_struct_size, parse_endpoint);
+		if (ret < 0)
+			goto out_cleanup;
+	} else {
+		unsigned int i;
+
+		for (i = 0; i < num_ports; i++) {
+			ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+				dev, notifier, asd_struct_size,
+				ports[i], parse_endpoint);
+			if (ret < 0)
+				goto out_cleanup;
+		}
+	}
+
+	ret = v4l2_async_subdev_notifier_register(sd, notifier);
+	if (ret < 0)
+		goto out_cleanup;
+
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0)
+		goto out_unregister;
+
+	sd->subdev_notifier = notifier;
+
+	return 0;
+
+out_unregister:
+	v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+	v4l2_async_notifier_cleanup(notifier);
+	kfree(notifier);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_register_fwnode_subdev);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index ea7a8b2..031ebb0 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 
 #include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
 
 struct fwnode_handle;
 struct v4l2_async_notifier;
@@ -360,4 +361,41 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
 int v4l2_async_notifier_parse_fwnode_sensor_common(
 	struct device *dev, struct v4l2_async_notifier *notifier);
 
+/**
+ * v4l2_async_register_fwnode_subdev - registers a sub-device to the
+ *					asynchronous sub-device framework
+ *					and parses fwnode endpoints
+ *
+ * @sd: pointer to struct &v4l2_subdev
+ * @asd_struct_size: size of the driver's async sub-device struct, including
+ *		     sizeof(struct v4l2_async_subdev). The &struct
+ *		     v4l2_async_subdev shall be the first member of
+ *		     the driver's async sub-device struct, i.e. both
+ *		     begin at the same memory address.
+ * @ports: array of port id's to parse for fwnode endpoints. If NULL, will
+ *	   parse all ports owned by the sub-device.
+ * @num_ports: number of ports in @ports array. Ignored if @ports is NULL.
+ * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
+ *		    endpoint. Optional.
+ *
+ * This function is just like v4l2_async_register_subdev() with the
+ * exception that calling it will also allocate a notifier for the
+ * sub-device, parse the sub-device's firmware node endpoints using
+ * v4l2_async_notifier_parse_fwnode_endpoints() or
+ * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and
+ * registers the sub-device notifier. The sub-device is similarly
+ * unregistered by calling v4l2_async_unregister_subdev().
+ *
+ * While registered, the subdev module is marked as in-use.
+ *
+ * An error is returned if the module is no longer loaded on any attempts
+ * to register it.
+ */
+int v4l2_async_register_fwnode_subdev(
+	struct v4l2_subdev *sd, size_t asd_struct_size,
+	unsigned int *ports, unsigned int num_ports,
+	int (*parse_endpoint)(struct device *dev,
+			      struct v4l2_fwnode_endpoint *vep,
+			      struct v4l2_async_subdev *asd));
+
 #endif /* _V4L2_FWNODE_H */
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 07/17] media: platform: video-mux: Register a subdev notifier
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (5 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 08/17] media: imx: csi: " Steve Longerbeam
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Philipp Zabel,
	Hans Verkuil, Arnd Bergmann, Geert Uytterhoeven,
	Laurent Pinchart, Jacob Chen, Neil Armstrong, open list

Parse neighbor remote devices on the video muxes input ports, add them to a
subdev notifier, and register the subdev notifier for the video mux, by
calling v4l2_async_register_fwnode_subdev().

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- add missing select V4L2_FWNODE to Kconfig for VIDEO_MUX
Changes since v4:
- none
Changes since v3:
- pass num_pads - 1 (num_input_pads) to video_mux_async_register().
Changes since v2:
- none
Changes since v1:
- add #include <linux/slab.h> for kcalloc() declaration.
---
 drivers/media/platform/Kconfig     |  1 +
 drivers/media/platform/video-mux.c | 36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 210b44a..6c3b2b7 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -58,6 +58,7 @@ config VIDEO_MUX
 	select MULTIPLEXER
 	depends on VIDEO_V4L2 && OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
 	select REGMAP
+	select V4L2_FWNODE
 	help
 	  This driver provides support for N:1 video bus multiplexers.
 
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index 1fb8872..e54a719 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -21,8 +21,10 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
+#include <linux/slab.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 struct video_mux {
@@ -207,6 +209,38 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = {
 	.video = &video_mux_subdev_video_ops,
 };
 
+static int video_mux_parse_endpoint(struct device *dev,
+				    struct v4l2_fwnode_endpoint *vep,
+				    struct v4l2_async_subdev *asd)
+{
+	/*
+	 * it's not an error if remote is missing on a video-mux
+	 * input port, return -ENOTCONN to skip this endpoint with
+	 * no error.
+	 */
+	return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
+}
+
+static int video_mux_async_register(struct video_mux *vmux,
+				    unsigned int num_input_pads)
+{
+	unsigned int i, *ports;
+	int ret;
+
+	ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL);
+	if (!ports)
+		return -ENOMEM;
+	for (i = 0; i < num_input_pads; i++)
+		ports[i] = i;
+
+	ret = v4l2_async_register_fwnode_subdev(
+		&vmux->subdev, sizeof(struct v4l2_async_subdev),
+		ports, num_input_pads, video_mux_parse_endpoint);
+
+	kfree(ports);
+	return ret;
+}
+
 static int video_mux_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -272,7 +306,7 @@ static int video_mux_probe(struct platform_device *pdev)
 
 	vmux->subdev.entity.ops = &video_mux_ops;
 
-	return v4l2_async_register_subdev(&vmux->subdev);
+	return video_mux_async_register(vmux, num_pads - 1);
 }
 
 static int video_mux_remove(struct platform_device *pdev)
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 08/17] media: imx: csi: Register a subdev notifier
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (6 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 07/17] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 09/17] media: imx: mipi csi-2: " Steve Longerbeam
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

Parse neighbor remote devices on the CSI port, and add them to a subdev
notifier, by calling v4l2_async_notifier_parse_fwnode_endpoints_by_port()
using the CSI's port id. And register the subdev notifier for the CSI.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- add call to v4l2_async_notifier_init().
Changes since v4:
- none
Changes since v3:
- v4l2_async_register_fwnode_subdev() no longer supports parsing
  port sub-devices, so call
  v4l2_async_notifier_parse_fwnode_endpoints_by_port() directly.
---
 drivers/staging/media/imx/imx-media-csi.c | 57 ++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 4647206..19ef377 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1780,6 +1780,61 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = {
 	.unregistered = csi_unregistered,
 };
 
+static int imx_csi_parse_endpoint(struct device *dev,
+				  struct v4l2_fwnode_endpoint *vep,
+				  struct v4l2_async_subdev *asd)
+{
+	return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
+}
+
+static int imx_csi_async_register(struct csi_priv *priv)
+{
+	struct v4l2_async_notifier *notifier;
+	struct fwnode_handle *fwnode;
+	unsigned int port;
+	int ret;
+
+	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+	if (!notifier)
+		return -ENOMEM;
+
+	v4l2_async_notifier_init(notifier);
+
+	fwnode = dev_fwnode(priv->dev);
+
+	/* get this CSI's port id */
+	ret = fwnode_property_read_u32(fwnode, "reg", &port);
+	if (ret < 0)
+		goto out_free;
+
+	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
+		priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+		port, imx_csi_parse_endpoint);
+	if (ret < 0)
+		goto out_cleanup;
+
+	ret = v4l2_async_subdev_notifier_register(&priv->sd, notifier);
+	if (ret < 0)
+		goto out_cleanup;
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret < 0)
+		goto out_unregister;
+
+	priv->sd.subdev_notifier = notifier;
+
+	return 0;
+
+out_unregister:
+	v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+	v4l2_async_notifier_cleanup(notifier);
+out_free:
+	kfree(notifier);
+
+	return ret;
+}
+
 static int imx_csi_probe(struct platform_device *pdev)
 {
 	struct ipu_client_platformdata *pdata;
@@ -1849,7 +1904,7 @@ static int imx_csi_probe(struct platform_device *pdev)
 			goto free;
 	}
 
-	ret = v4l2_async_register_subdev(&priv->sd);
+	ret = imx_csi_async_register(priv);
 	if (ret)
 		goto free;
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 09/17] media: imx: mipi csi-2: Register a subdev notifier
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (7 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 08/17] media: imx: csi: " Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 10/17] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

Parse neighbor remote devices on the MIPI CSI-2 input port, add
them to a subdev notifier, and register the subdev notifier for the
MIPI CSI-2 receiver, by calling v4l2_async_register_fwnode_subdev().

csi2_parse_endpoints() is modified to be the parse_endpoint callback.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 31 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index ceeeb30..94eb9a1 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -551,35 +551,34 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
 	.registered = csi2_registered,
 };
 
-static int csi2_parse_endpoints(struct csi2_dev *csi2)
+static int csi2_parse_endpoint(struct device *dev,
+			       struct v4l2_fwnode_endpoint *vep,
+			       struct v4l2_async_subdev *asd)
 {
-	struct device_node *node = csi2->dev->of_node;
-	struct device_node *epnode;
-	struct v4l2_fwnode_endpoint ep;
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct csi2_dev *csi2 = sd_to_dev(sd);
 
-	epnode = of_graph_get_endpoint_by_regs(node, 0, -1);
-	if (!epnode) {
-		v4l2_err(&csi2->sd, "failed to get sink endpoint node\n");
+	if (!fwnode_device_is_available(asd->match.fwnode)) {
+		v4l2_err(&csi2->sd, "remote is not available\n");
 		return -EINVAL;
 	}
 
-	v4l2_fwnode_endpoint_parse(of_fwnode_handle(epnode), &ep);
-	of_node_put(epnode);
-
-	if (ep.bus_type != V4L2_MBUS_CSI2) {
+	if (vep->bus_type != V4L2_MBUS_CSI2) {
 		v4l2_err(&csi2->sd, "invalid bus type, must be MIPI CSI2\n");
 		return -EINVAL;
 	}
 
-	csi2->bus = ep.bus.mipi_csi2;
+	csi2->bus = vep->bus.mipi_csi2;
 
 	dev_dbg(csi2->dev, "data lanes: %d\n", csi2->bus.num_data_lanes);
 	dev_dbg(csi2->dev, "flags: 0x%08x\n", csi2->bus.flags);
+
 	return 0;
 }
 
 static int csi2_probe(struct platform_device *pdev)
 {
+	unsigned int sink_port = 0;
 	struct csi2_dev *csi2;
 	struct resource *res;
 	int ret;
@@ -601,10 +600,6 @@ static int csi2_probe(struct platform_device *pdev)
 	csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
 	csi2->sd.grp_id = IMX_MEDIA_GRP_ID_CSI2;
 
-	ret = csi2_parse_endpoints(csi2);
-	if (ret)
-		return ret;
-
 	csi2->pllref_clk = devm_clk_get(&pdev->dev, "ref");
 	if (IS_ERR(csi2->pllref_clk)) {
 		v4l2_err(&csi2->sd, "failed to get pll reference clock\n");
@@ -654,7 +649,9 @@ static int csi2_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, &csi2->sd);
 
-	ret = v4l2_async_register_subdev(&csi2->sd);
+	ret = v4l2_async_register_fwnode_subdev(
+		&csi2->sd, sizeof(struct v4l2_async_subdev),
+		&sink_port, 1, csi2_parse_endpoint);
 	if (ret)
 		goto dphy_off;
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 10/17] media: staging/imx: of: Remove recursive graph walk
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (8 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 09/17] media: imx: mipi csi-2: " Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 11/17] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

After moving to subdev notifiers, it's no longer necessary to recursively
walk the OF graph, because the subdev notifiers will discover and add
devices from the graph for us.

So the recursive of_parse_subdev() function is gone, replaced with
of_add_csi() which adds only the CSI port fwnodes to the imx-media
root notifier.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/media/imx/imx-media-of.c | 106 +++----------------------------
 1 file changed, 8 insertions(+), 98 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c
index acde372..1c91754 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -20,74 +20,19 @@
 #include <video/imx-ipu-v3.h>
 #include "imx-media.h"
 
-static int of_get_port_count(const struct device_node *np)
+static int of_add_csi(struct imx_media_dev *imxmd, struct device_node *csi_np)
 {
-	struct device_node *ports, *child;
-	int num = 0;
-
-	/* check if this node has a ports subnode */
-	ports = of_get_child_by_name(np, "ports");
-	if (ports)
-		np = ports;
-
-	for_each_child_of_node(np, child)
-		if (of_node_cmp(child->name, "port") == 0)
-			num++;
-
-	of_node_put(ports);
-	return num;
-}
-
-/*
- * find the remote device node given local endpoint node
- */
-static bool of_get_remote(struct device_node *epnode,
-			  struct device_node **remote_node)
-{
-	struct device_node *rp, *rpp;
-	struct device_node *remote;
-	bool is_csi_port;
-
-	rp = of_graph_get_remote_port(epnode);
-	rpp = of_graph_get_remote_port_parent(epnode);
-
-	if (of_device_is_compatible(rpp, "fsl,imx6q-ipu")) {
-		/* the remote is one of the CSI ports */
-		remote = rp;
-		of_node_put(rpp);
-		is_csi_port = true;
-	} else {
-		remote = rpp;
-		of_node_put(rp);
-		is_csi_port = false;
-	}
-
-	if (!of_device_is_available(remote)) {
-		of_node_put(remote);
-		*remote_node = NULL;
-	} else {
-		*remote_node = remote;
-	}
-
-	return is_csi_port;
-}
-
-static int
-of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np,
-		bool is_csi_port)
-{
-	int i, num_ports, ret;
+	int ret;
 
-	if (!of_device_is_available(sd_np)) {
+	if (!of_device_is_available(csi_np)) {
 		dev_dbg(imxmd->md.dev, "%s: %s not enabled\n", __func__,
-			sd_np->name);
+			csi_np->name);
 		/* unavailable is not an error */
 		return 0;
 	}
 
-	/* register this subdev with async notifier */
-	ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(sd_np),
-					 NULL);
+	/* add CSI fwnode to async notifier */
+	ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL);
 	if (ret) {
 		if (ret == -EEXIST) {
 			/* already added, everything is fine */
@@ -98,42 +43,7 @@ of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np,
 		return ret;
 	}
 
-	/*
-	 * the ipu-csi has one sink port. The source pads are not
-	 * represented in the device tree by port nodes, but are
-	 * described by the internal pads and links later.
-	 */
-	num_ports = is_csi_port ? 1 : of_get_port_count(sd_np);
-
-	for (i = 0; i < num_ports; i++) {
-		struct device_node *epnode = NULL, *port, *remote_np;
-
-		port = is_csi_port ? sd_np : of_graph_get_port_by_id(sd_np, i);
-		if (!port)
-			continue;
-
-		for_each_child_of_node(port, epnode) {
-			bool remote_is_csi;
-
-			remote_is_csi = of_get_remote(epnode, &remote_np);
-			if (!remote_np)
-				continue;
-
-			ret = of_parse_subdev(imxmd, remote_np, remote_is_csi);
-			of_node_put(remote_np);
-			if (ret)
-				break;
-		}
-
-		if (port != sd_np)
-			of_node_put(port);
-		if (ret) {
-			of_node_put(epnode);
-			break;
-		}
-	}
-
-	return ret;
+	return 0;
 }
 
 int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
@@ -147,7 +57,7 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
 		if (!csi_np)
 			break;
 
-		ret = of_parse_subdev(imxmd, csi_np, true);
+		ret = of_add_csi(imxmd, csi_np);
 		of_node_put(csi_np);
 		if (ret)
 			return ret;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 11/17] media: staging/imx: Loop through all registered subdevs for media links
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (9 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 10/17] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 12/17] media: staging/imx: Rename root notifier Steve Longerbeam
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

The root imx-media notifier no longer sees all bound subdevices because
some of them will be bound to subdev notifiers. So imx_media_create_links()
now needs to loop through all subdevices registered with the v4l2-device,
not just the ones in the root notifier's done list. This should be safe
because imx_media_create_of_links() checks if a fwnode link already
exists before creating.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/media/imx/imx-media-dev.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index b0be80f..ae87c81 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -175,7 +175,7 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
 }
 
 /*
- * create the media links for all subdevs that registered async.
+ * Create the media links for all subdevs that registered.
  * Called after all async subdevs have bound.
  */
 static int imx_media_create_links(struct v4l2_async_notifier *notifier)
@@ -184,14 +184,7 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier)
 	struct v4l2_subdev *sd;
 	int ret;
 
-	/*
-	 * Only links are created between subdevices that are known
-	 * to the async notifier. If there are other non-async subdevices,
-	 * they were created internally by some subdevice (smiapp is one
-	 * example). In those cases it is expected the subdevice is
-	 * responsible for creating those internal links.
-	 */
-	list_for_each_entry(sd, &notifier->done, async_list) {
+	list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
 		switch (sd->grp_id) {
 		case IMX_MEDIA_GRP_ID_VDIC:
 		case IMX_MEDIA_GRP_ID_IC_PRP:
@@ -211,7 +204,10 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier)
 				imx_media_create_csi_of_links(imxmd, sd);
 			break;
 		default:
-			/* this is an external fwnode subdev */
+			/*
+			 * if this subdev has fwnode links, create media
+			 * links for them.
+			 */
 			imx_media_create_of_links(imxmd, sd);
 			break;
 		}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 12/17] media: staging/imx: Rename root notifier
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (10 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 11/17] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 13/17] media: staging/imx: Switch to v4l2_async_notifier_add_*_subdev Steve Longerbeam
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

Rename the imx-media root async notifier from "subdev_notifier" to
simply "notifier", so as not to confuse it with true subdev notifiers.
No functional changes.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/media/imx/imx-media-dev.c | 14 +++++++-------
 drivers/staging/media/imx/imx-media.h     |  2 +-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index ae87c81..982e455 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -29,7 +29,7 @@
 
 static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
 {
-	return container_of(n, struct imx_media_dev, subdev_notifier);
+	return container_of(n, struct imx_media_dev, notifier);
 }
 
 /*
@@ -113,7 +113,7 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
 
 	list_add_tail(&imxasd->list, &imxmd->asd_list);
 
-	imxmd->subdev_notifier.num_subdevs++;
+	imxmd->notifier.num_subdevs++;
 
 	dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n",
 		__func__, np ? np->name : devname, np ? "FWNODE" : "DEVNAME");
@@ -532,7 +532,7 @@ static int imx_media_probe(struct platform_device *pdev)
 		goto unreg_dev;
 	}
 
-	num_subdevs = imxmd->subdev_notifier.num_subdevs;
+	num_subdevs = imxmd->notifier.num_subdevs;
 
 	/* no subdevs? just bail */
 	if (num_subdevs == 0) {
@@ -552,10 +552,10 @@ static int imx_media_probe(struct platform_device *pdev)
 		subdevs[i++] = &imxasd->asd;
 
 	/* prepare the async subdev notifier and register it */
-	imxmd->subdev_notifier.subdevs = subdevs;
-	imxmd->subdev_notifier.ops = &imx_media_subdev_ops;
+	imxmd->notifier.subdevs = subdevs;
+	imxmd->notifier.ops = &imx_media_subdev_ops;
 	ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
-					   &imxmd->subdev_notifier);
+					   &imxmd->notifier);
 	if (ret) {
 		v4l2_err(&imxmd->v4l2_dev,
 			 "v4l2_async_notifier_register failed with %d\n", ret);
@@ -580,7 +580,7 @@ static int imx_media_remove(struct platform_device *pdev)
 
 	v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n");
 
-	v4l2_async_notifier_unregister(&imxmd->subdev_notifier);
+	v4l2_async_notifier_unregister(&imxmd->notifier);
 	imx_media_remove_internal_subdevs(imxmd);
 	v4l2_device_unregister(&imxmd->v4l2_dev);
 	media_device_unregister(&imxmd->md);
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index 57bd094..227b79c 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -150,7 +150,7 @@ struct imx_media_dev {
 
 	/* for async subdev registration */
 	struct list_head asd_list;
-	struct v4l2_async_notifier subdev_notifier;
+	struct v4l2_async_notifier notifier;
 };
 
 enum codespace_sel {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 13/17] media: staging/imx: Switch to v4l2_async_notifier_add_*_subdev
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (11 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 12/17] media: staging/imx: Rename root notifier Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 14/17] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

Switch to v4l2_async_notifier_add_*_subdev() when adding async subdevs
to the imx-media root notifier. This removes the need to check for
an already added asd, since v4l2_async_notifier_add_*_subdev() does this
check. Also no need to allocate a subdevs array when registering the
root notifier, or keeping an internal master asd_list, since this is
moved to the notifier's asd_list.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- remove reference to notifier.num_subdevs and call
  v4l2_async_notifier_init(). Suggested by Sakari Ailus.
---
 drivers/staging/media/imx/imx-media-dev.c         | 121 ++++++----------------
 drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media.h             |   4 +-
 3 files changed, 36 insertions(+), 94 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index 982e455..659420e 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -33,43 +33,10 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
 }
 
 /*
- * Find an asd by fwnode or device name. This is called during
- * driver load to form the async subdev list and bind them.
- */
-static struct v4l2_async_subdev *
-find_async_subdev(struct imx_media_dev *imxmd,
-		  struct fwnode_handle *fwnode,
-		  const char *devname)
-{
-	struct imx_media_async_subdev *imxasd;
-	struct v4l2_async_subdev *asd;
-
-	list_for_each_entry(imxasd, &imxmd->asd_list, list) {
-		asd = &imxasd->asd;
-		switch (asd->match_type) {
-		case V4L2_ASYNC_MATCH_FWNODE:
-			if (fwnode && asd->match.fwnode == fwnode)
-				return asd;
-			break;
-		case V4L2_ASYNC_MATCH_DEVNAME:
-			if (devname && !strcmp(asd->match.device_name,
-					       devname))
-				return asd;
-			break;
-		default:
-			break;
-		}
-	}
-
-	return NULL;
-}
-
-
-/*
- * Adds a subdev to the async subdev list. If fwnode is non-NULL, adds
- * the async as a V4L2_ASYNC_MATCH_FWNODE match type, otherwise as
- * a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name of the
- * given platform_device. This is called during driver load when
+ * Adds a subdev to the root notifier's async subdev list. If fwnode is
+ * non-NULL, adds the async as a V4L2_ASYNC_MATCH_FWNODE match type,
+ * otherwise as a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name
+ * of the given platform_device. This is called during driver load when
  * forming the async subdev list.
  */
 int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
@@ -80,47 +47,34 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
 	struct imx_media_async_subdev *imxasd;
 	struct v4l2_async_subdev *asd;
 	const char *devname = NULL;
-	int ret = 0;
-
-	mutex_lock(&imxmd->mutex);
+	int ret;
 
-	if (pdev)
+	if (fwnode) {
+		asd = v4l2_async_notifier_add_fwnode_subdev(
+			&imxmd->notifier, fwnode, sizeof(*imxasd));
+	} else {
 		devname = dev_name(&pdev->dev);
-
-	/* return -EEXIST if this asd already added */
-	if (find_async_subdev(imxmd, fwnode, devname)) {
-		dev_dbg(imxmd->md.dev, "%s: already added %s\n",
-			__func__, np ? np->name : devname);
-		ret = -EEXIST;
-		goto out;
+		asd = v4l2_async_notifier_add_devname_subdev(
+			&imxmd->notifier, devname, sizeof(*imxasd));
 	}
 
-	imxasd = devm_kzalloc(imxmd->md.dev, sizeof(*imxasd), GFP_KERNEL);
-	if (!imxasd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	asd = &imxasd->asd;
-
-	if (fwnode) {
-		asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		asd->match.fwnode = fwnode;
-	} else {
-		asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
-		asd->match.device_name = devname;
-		imxasd->pdev = pdev;
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
+		if (ret == -EEXIST)
+			dev_dbg(imxmd->md.dev, "%s: already added %s\n",
+				__func__, np ? np->name : devname);
+		return ret;
 	}
 
-	list_add_tail(&imxasd->list, &imxmd->asd_list);
+	imxasd = to_imx_media_asd(asd);
 
-	imxmd->notifier.num_subdevs++;
+	if (devname)
+		imxasd->pdev = pdev;
 
 	dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n",
 		__func__, np ? np->name : devname, np ? "FWNODE" : "DEVNAME");
 
-out:
-	mutex_unlock(&imxmd->mutex);
-	return ret;
+	return 0;
 }
 
 /*
@@ -483,10 +437,8 @@ static int imx_media_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
-	struct imx_media_async_subdev *imxasd;
-	struct v4l2_async_subdev **subdevs;
 	struct imx_media_dev *imxmd;
-	int num_subdevs, i, ret;
+	int ret;
 
 	imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL);
 	if (!imxmd)
@@ -515,44 +467,31 @@ static int imx_media_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
 
-	INIT_LIST_HEAD(&imxmd->asd_list);
 	INIT_LIST_HEAD(&imxmd->vdev_list);
 
+	v4l2_async_notifier_init(&imxmd->notifier);
+
 	ret = imx_media_add_of_subdevs(imxmd, node);
 	if (ret) {
 		v4l2_err(&imxmd->v4l2_dev,
 			 "add_of_subdevs failed with %d\n", ret);
-		goto unreg_dev;
+		goto notifier_cleanup;
 	}
 
 	ret = imx_media_add_internal_subdevs(imxmd);
 	if (ret) {
 		v4l2_err(&imxmd->v4l2_dev,
 			 "add_internal_subdevs failed with %d\n", ret);
-		goto unreg_dev;
+		goto notifier_cleanup;
 	}
 
-	num_subdevs = imxmd->notifier.num_subdevs;
-
 	/* no subdevs? just bail */
-	if (num_subdevs == 0) {
+	if (list_empty(&imxmd->notifier.asd_list)) {
 		ret = -ENODEV;
-		goto unreg_dev;
+		goto notifier_cleanup;
 	}
 
-	subdevs = devm_kcalloc(imxmd->md.dev, num_subdevs, sizeof(*subdevs),
-			       GFP_KERNEL);
-	if (!subdevs) {
-		ret = -ENOMEM;
-		goto unreg_dev;
-	}
-
-	i = 0;
-	list_for_each_entry(imxasd, &imxmd->asd_list, list)
-		subdevs[i++] = &imxasd->asd;
-
 	/* prepare the async subdev notifier and register it */
-	imxmd->notifier.subdevs = subdevs;
 	imxmd->notifier.ops = &imx_media_subdev_ops;
 	ret = v4l2_async_notifier_register(&imxmd->v4l2_dev,
 					   &imxmd->notifier);
@@ -566,7 +505,8 @@ static int imx_media_probe(struct platform_device *pdev)
 
 del_int:
 	imx_media_remove_internal_subdevs(imxmd);
-unreg_dev:
+notifier_cleanup:
+	v4l2_async_notifier_cleanup(&imxmd->notifier);
 	v4l2_device_unregister(&imxmd->v4l2_dev);
 cleanup:
 	media_device_cleanup(&imxmd->md);
@@ -582,6 +522,7 @@ static int imx_media_remove(struct platform_device *pdev)
 
 	v4l2_async_notifier_unregister(&imxmd->notifier);
 	imx_media_remove_internal_subdevs(imxmd);
+	v4l2_async_notifier_cleanup(&imxmd->notifier);
 	v4l2_device_unregister(&imxmd->v4l2_dev);
 	media_device_unregister(&imxmd->md);
 	media_device_cleanup(&imxmd->md);
diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c
index daf66c2..0fdc45d 100644
--- a/drivers/staging/media/imx/imx-media-internal-sd.c
+++ b/drivers/staging/media/imx/imx-media-internal-sd.c
@@ -350,8 +350,11 @@ int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd)
 void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd)
 {
 	struct imx_media_async_subdev *imxasd;
+	struct v4l2_async_subdev *asd;
+
+	list_for_each_entry(asd, &imxmd->notifier.asd_list, asd_list) {
+		imxasd = to_imx_media_asd(asd);
 
-	list_for_each_entry(imxasd, &imxmd->asd_list, list) {
 		if (!imxasd->pdev)
 			continue;
 
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h
index 227b79c..bc7feb8 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -119,12 +119,11 @@ struct imx_media_internal_sd_platformdata {
 	int ipu_id;
 };
 
-
 struct imx_media_async_subdev {
+	/* the base asd - must be first in this struct */
 	struct v4l2_async_subdev asd;
 	/* the platform device of IPU-internal subdevs */
 	struct platform_device *pdev;
-	struct list_head list;
 };
 
 static inline struct imx_media_async_subdev *
@@ -149,7 +148,6 @@ struct imx_media_dev {
 	struct ipu_soc *ipu[2];
 
 	/* for async subdev registration */
-	struct list_head asd_list;
 	struct v4l2_async_notifier notifier;
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 14/17] media: staging/imx: TODO: Remove one assumption about OF graph parsing
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (12 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 13/17] media: staging/imx: Switch to v4l2_async_notifier_add_*_subdev Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array Steve Longerbeam
  2018-07-09 22:39 ` [PATCH v6 17/17] [media] v4l2-subdev.rst: Update doc regarding subdev descriptors Steve Longerbeam
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Steve Longerbeam, Philipp Zabel,
	Mauro Carvalho Chehab, Greg Kroah-Hartman,
	open list:STAGING SUBSYSTEM, open list

The move to subdev notifiers fixes one assumption of OF graph parsing.
If a subdevice has non-video related ports, the subdev driver knows not
to follow those ports when adding remote devices to its subdev notifier.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/staging/media/imx/TODO | 29 +++++++----------------------
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 9eb7326..aeeb154 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -17,29 +17,15 @@
   decided whether this feature is useful enough to make it generally
   available by exporting to v4l2-core.
 
-- The OF graph is walked at probe time to form the list of fwnodes to
-  be passed to v4l2_async_notifier_register(), starting from the IPU
-  CSI ports. And after all async subdevices have been bound,
-  v4l2_fwnode_parse_link() is used to form the media links between
-  the entities discovered by walking the OF graph.
+- After all async subdevices have been bound, v4l2_fwnode_parse_link()
+  is used to form the media links between the devices discovered in
+  the OF graph.
 
   While this approach allows support for arbitrary OF graphs, there
   are some assumptions for this to work:
 
-  1. All port parent nodes reachable in the graph from the IPU CSI
-     ports bind to V4L2 async subdevice drivers.
-
-     If a device has mixed-use ports such as video plus audio, the
-     endpoints from the audio ports are followed to devices that must
-     bind to V4L2 subdevice drivers, and not for example, to an ALSA
-     driver or a non-V4L2 media driver. If the device were bound to
-     such a driver, imx-media would never get an async completion
-     notification because the device fwnode was added to the async
-     list, but the driver does not interface with the V4L2 async
-     framework.
-
-  2. Every port reachable in the graph is treated as a media pad,
-     owned by the V4L2 subdevice that is bound to the port's parent.
+  1. If a port owned by a device in the graph has endpoint nodes, the
+     port is treated as a media pad.
 
      This presents problems for devices that don't make this port = pad
      assumption. Examples are SMIAPP compatible cameras which define only
@@ -54,9 +40,8 @@
      possible long-term solution is to implement a subdev API that
      maps a port id to a media pad index.
 
-  3. Every endpoint of a port reachable in the graph is treated as
-     a media link, between V4L2 subdevices that are bound to the
-     port parents of the local and remote endpoints.
+  2. Every endpoint of a port owned by a device in the graph is treated
+     as a media link.
 
      Which means a port must not contain mixed-use endpoints, they
      must all refer to media links between V4L2 subdevices.
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (13 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 14/17] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  2018-07-23 12:35   ` Sakari Ailus
  2018-07-09 22:39 ` [PATCH v6 17/17] [media] v4l2-subdev.rst: Update doc regarding subdev descriptors Steve Longerbeam
  15 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media
  Cc: Steve Longerbeam, Mauro Carvalho Chehab, Sakari Ailus,
	Niklas Söderlund, Sebastian Reichel, Hans Verkuil,
	open list

All platform drivers have been converted to use
v4l2_async_notifier_add_subdev(), in place of adding
asd's to the notifier subdevs array. So the subdevs
array can now be removed from struct v4l2_async_notifier,
and remove the backward compatibility support for that
array in v4l2-async.c.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- also remove notifier num_subdevs and V4L2_MAX_SUBDEVS macro.
  Suggested by Sakari Ailus.
---
 drivers/media/v4l2-core/v4l2-async.c | 114 ++++++++---------------------------
 include/media/v4l2-async.h           |  21 ++-----
 include/media/v4l2-fwnode.h          |  12 ----
 3 files changed, 30 insertions(+), 117 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 78cf1a9..9d8343e 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -358,31 +358,23 @@ static bool __v4l2_async_notifier_has_async_subdev(
 /*
  * Find out whether an async sub-device was set up already or
  * whether it exists in a given notifier before @this_index.
+ * If @this_index < 0, search the notifier's entire @asd_list.
  */
 static bool v4l2_async_notifier_has_async_subdev(
 	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd,
-	unsigned int this_index)
+	int this_index)
 {
 	struct v4l2_async_subdev *asd_y;
-	unsigned int j;
+	int j = 0;
 
 	lockdep_assert_held(&list_lock);
 
 	/* Check that an asd is not being added more than once. */
-	if (notifier->subdevs) {
-		for (j = 0; j < this_index; j++) {
-			asd_y = notifier->subdevs[j];
-			if (asd_equal(asd, asd_y))
-				return true;
-		}
-	} else {
-		j = 0;
-		list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
-			if (j++ >= this_index)
-				break;
-			if (asd_equal(asd, asd_y))
-				return true;
-		}
+	list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
+		if (this_index >= 0 && j++ >= this_index)
+			break;
+		if (asd_equal(asd, asd_y))
+			return true;
 	}
 
 	/* Check that an asd does not exist in other notifiers. */
@@ -395,7 +387,7 @@ static bool v4l2_async_notifier_has_async_subdev(
 
 static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
 					 struct v4l2_async_subdev *asd,
-					 unsigned int this_index)
+					 int this_index)
 {
 	struct device *dev =
 		notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
@@ -434,36 +426,19 @@ EXPORT_SYMBOL(v4l2_async_notifier_init);
 static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_subdev *asd;
-	int ret;
-	int i;
-
-	if (notifier->num_subdevs > V4L2_MAX_SUBDEVS)
-		return -EINVAL;
+	int ret, i = 0;
 
 	INIT_LIST_HEAD(&notifier->waiting);
 	INIT_LIST_HEAD(&notifier->done);
 
 	mutex_lock(&list_lock);
 
-	if (notifier->subdevs) {
-		for (i = 0; i < notifier->num_subdevs; i++) {
-			asd = notifier->subdevs[i];
-
-			ret = v4l2_async_notifier_asd_valid(notifier, asd, i);
-			if (ret)
-				goto err_unlock;
+	list_for_each_entry(asd, &notifier->asd_list, asd_list) {
+		ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
+		if (ret)
+			goto err_unlock;
 
-			list_add_tail(&asd->list, &notifier->waiting);
-		}
-	} else {
-		i = 0;
-		list_for_each_entry(asd, &notifier->asd_list, asd_list) {
-			ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
-			if (ret)
-				goto err_unlock;
-
-			list_add_tail(&asd->list, &notifier->waiting);
-		}
+		list_add_tail(&asd->list, &notifier->waiting);
 	}
 
 	ret = v4l2_async_notifier_try_all_subdevs(notifier);
@@ -556,45 +531,22 @@ EXPORT_SYMBOL(v4l2_async_notifier_unregister);
 static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 {
 	struct v4l2_async_subdev *asd, *tmp;
-	unsigned int i;
 
 	if (!notifier)
 		return;
 
-	if (notifier->subdevs) {
-		for (i = 0; i < notifier->num_subdevs; i++) {
-			asd = notifier->subdevs[i];
-
-			switch (asd->match_type) {
-			case V4L2_ASYNC_MATCH_FWNODE:
-				fwnode_handle_put(asd->match.fwnode);
-				break;
-			default:
-				break;
-			}
-
-			kfree(asd);
+	list_for_each_entry_safe(asd, tmp, &notifier->asd_list, asd_list) {
+		switch (asd->match_type) {
+		case V4L2_ASYNC_MATCH_FWNODE:
+			fwnode_handle_put(asd->match.fwnode);
+			break;
+		default:
+			break;
 		}
 
-		kvfree(notifier->subdevs);
-		notifier->subdevs = NULL;
-	} else {
-		list_for_each_entry_safe(asd, tmp,
-					 &notifier->asd_list, asd_list) {
-			switch (asd->match_type) {
-			case V4L2_ASYNC_MATCH_FWNODE:
-				fwnode_handle_put(asd->match.fwnode);
-				break;
-			default:
-				break;
-			}
-
-			list_del(&asd->asd_list);
-			kfree(asd);
-		}
+		list_del(&asd->asd_list);
+		kfree(asd);
 	}
-
-	notifier->num_subdevs = 0;
 }
 
 void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
@@ -614,27 +566,11 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 
 	mutex_lock(&list_lock);
 
-	if (notifier->num_subdevs >= V4L2_MAX_SUBDEVS) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	/*
-	 * If caller uses this function, it cannot also allocate and
-	 * place asd's in the notifier->subdevs array.
-	 */
-	if (WARN_ON(notifier->subdevs)) {
-		ret = -EINVAL;
-		goto unlock;
-	}
-
-	ret = v4l2_async_notifier_asd_valid(notifier, asd,
-					    notifier->num_subdevs);
+	ret = v4l2_async_notifier_asd_valid(notifier, asd, -1);
 	if (ret)
 		goto unlock;
 
 	list_add_tail(&asd->asd_list, &notifier->asd_list);
-	notifier->num_subdevs++;
 
 unlock:
 	mutex_unlock(&list_lock);
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 16b1e2b..89b152f 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -20,9 +20,6 @@ struct v4l2_device;
 struct v4l2_subdev;
 struct v4l2_async_notifier;
 
-/* A random max subdevice number, used to allocate an array on stack */
-#define V4L2_MAX_SUBDEVS 128U
-
 /**
  * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used
  *	in order to identify a match
@@ -124,20 +121,16 @@ struct v4l2_async_notifier_operations {
  * struct v4l2_async_notifier - v4l2_device notifier data
  *
  * @ops:	notifier operations
- * @num_subdevs: number of subdevices used in the subdevs array
- * @subdevs:	array of pointers to subdevice descriptors
  * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
  * @sd:		sub-device that registered the notifier, NULL otherwise
  * @parent:	parent notifier
- * @asd_list:	master list of struct v4l2_async_subdev, replaces @subdevs
+ * @asd_list:	master list of struct v4l2_async_subdev
  * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
  * @done:	list of struct v4l2_subdev, already probed
  * @list:	member in a global list of notifiers
  */
 struct v4l2_async_notifier {
 	const struct v4l2_async_notifier_operations *ops;
-	unsigned int num_subdevs;
-	struct v4l2_async_subdev **subdevs;
 	struct v4l2_device *v4l2_dev;
 	struct v4l2_subdev *sd;
 	struct v4l2_async_notifier *parent;
@@ -164,10 +157,8 @@ void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
  * @notifier: pointer to &struct v4l2_async_notifier
  * @asd: pointer to &struct v4l2_async_subdev
  *
- * This can be used before registering a notifier to add an
- * asd to the notifiers @asd_list. If the caller uses this
- * method to compose an asd list, it must never allocate
- * or place asd's in the @subdevs array.
+ * Call this function before registering a notifier to link the
+ * provided asd to the notifiers master @asd_list.
  */
 int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd);
@@ -184,10 +175,8 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
  *		     the driver's async sub-device struct, i.e. both
  *		     begin at the same memory address.
  *
- * This can be used before registering a notifier to add a
- * fwnode-matched asd to the notifiers master asd_list. If the caller
- * uses this method to compose an asd list, it must never allocate
- * or place asd's in the @subdevs array.
+ * Allocate a fwnode-matched asd of size asd_struct_size, and add it
+ * to the notifiers @asd_list.
  */
 struct v4l2_async_subdev *
 v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 031ebb0..8b4873c 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -259,12 +259,6 @@ typedef int (*parse_endpoint_func)(struct device *dev,
  * This function may not be called on a registered notifier and may be called on
  * a notifier only once.
  *
- * Do not allocate the notifier's subdevs array, or change the notifier's
- * num_subdevs field. This is because this function uses
- * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
- * which is in-place-of the subdevs array which must remain unallocated
- * and unused.
- *
  * The &struct v4l2_fwnode_endpoint passed to the callback function
  * @parse_endpoint is released once the function is finished. If there is a need
  * to retain that configuration, the user needs to allocate memory for it.
@@ -316,12 +310,6 @@ int v4l2_async_notifier_parse_fwnode_endpoints(
  * This function may not be called on a registered notifier and may be called on
  * a notifier only once per port.
  *
- * Do not allocate the notifier's subdevs array, or change the notifier's
- * num_subdevs field. This is because this function uses
- * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
- * which is in-place-of the subdevs array which must remain unallocated
- * and unused.
- *
  * The &struct v4l2_fwnode_endpoint passed to the callback function
  * @parse_endpoint is released once the function is finished. If there is a need
  * to retain that configuration, the user needs to allocate memory for it.
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v6 17/17] [media] v4l2-subdev.rst: Update doc regarding subdev descriptors
       [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
                   ` (14 preceding siblings ...)
  2018-07-09 22:39 ` [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array Steve Longerbeam
@ 2018-07-09 22:39 ` Steve Longerbeam
  15 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-09 22:39 UTC (permalink / raw)
  To: linux-media; +Cc: Steve Longerbeam, Mauro Carvalho Chehab, open list

Update the doc to describe the new method of adding subdevice
descriptors to async notifiers.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
Changes since v5:
- add info about v4l2_async_notifier_init().
---
 Documentation/media/kapi/v4l2-subdev.rst | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/Documentation/media/kapi/v4l2-subdev.rst b/Documentation/media/kapi/v4l2-subdev.rst
index e1f0b72..1280e05 100644
--- a/Documentation/media/kapi/v4l2-subdev.rst
+++ b/Documentation/media/kapi/v4l2-subdev.rst
@@ -247,20 +247,28 @@ performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices
 registered this way are stored in a global list of subdevices, ready to be
 picked up by bridge drivers.
 
-Bridge drivers in turn have to register a notifier object with an array of
-subdevice descriptors that the bridge device needs for its operation. This is
+Bridge drivers in turn have to register a notifier object. This is
 performed using the :c:func:`v4l2_async_notifier_register` call. To
 unregister the notifier the driver has to call
 :c:func:`v4l2_async_notifier_unregister`. The former of the two functions
-takes two arguments: a pointer to struct :c:type:`v4l2_device` and a pointer to
-struct :c:type:`v4l2_async_notifier`. The latter contains a pointer to an array
-of pointers to subdevice descriptors of type struct :c:type:`v4l2_async_subdev`
-type. The V4L2 core will then use these descriptors to match asynchronously
-registered
-subdevices to them. If a match is detected the ``.bound()`` notifier callback
-is called. After all subdevices have been located the .complete() callback is
-called. When a subdevice is removed from the system the .unbind() method is
-called. All three callbacks are optional.
+takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
+pointer to struct :c:type:`v4l2_async_notifier`.
+
+Before registering the notifier, bridge drivers must do two things:
+first, the notifier must be initialized using the
+:c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
+begin to form a list of subdevice descriptors that the bridge device
+needs for its operation. Subdevice descriptors are added to the notifier
+using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
+takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
+and a pointer to the subdevice descripter, which is of type struct
+:c:type:`v4l2_async_subdev`.
+
+The V4L2 core will then use these descriptors to match asynchronously
+registered subdevices to them. If a match is detected the ``.bound()``
+notifier callback is called. After all subdevices have been located the
+.complete() callback is called. When a subdevice is removed from the
+system the .unbind() method is called. All three callbacks are optional.
 
 V4L2 sub-device userspace API
 -----------------------------
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
  2018-07-09 22:39 ` [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array Steve Longerbeam
@ 2018-07-23 12:35   ` Sakari Ailus
  2018-07-23 16:44     ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: Sakari Ailus @ 2018-07-23 12:35 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Sakari Ailus, Niklas Söderlund, Sebastian Reichel,
	Hans Verkuil, open list

Hi Steve,

Thanks for the update.

On Mon, Jul 09, 2018 at 03:39:16PM -0700, Steve Longerbeam wrote:
> All platform drivers have been converted to use
> v4l2_async_notifier_add_subdev(), in place of adding
> asd's to the notifier subdevs array. So the subdevs
> array can now be removed from struct v4l2_async_notifier,
> and remove the backward compatibility support for that
> array in v4l2-async.c.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>

This set removes the subdevs and num_subdevs fieldsfrom the notifier (as
discussed previously) but it doesn't include the corresponding
driver changes. Is there a patch missing from the set?

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
  2018-07-23 12:35   ` Sakari Ailus
@ 2018-07-23 16:44     ` Steve Longerbeam
  2018-07-23 17:24       ` Sakari Ailus
  2018-08-04 10:33       ` jacopo mondi
  0 siblings, 2 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-07-23 16:44 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Sakari Ailus, Niklas Söderlund, Sebastian Reichel,
	Hans Verkuil, open list



On 07/23/2018 05:35 AM, Sakari Ailus wrote:
> Hi Steve,
>
> Thanks for the update.
>
> On Mon, Jul 09, 2018 at 03:39:16PM -0700, Steve Longerbeam wrote:
>> All platform drivers have been converted to use
>> v4l2_async_notifier_add_subdev(), in place of adding
>> asd's to the notifier subdevs array. So the subdevs
>> array can now be removed from struct v4l2_async_notifier,
>> and remove the backward compatibility support for that
>> array in v4l2-async.c.
>>
>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> This set removes the subdevs and num_subdevs fieldsfrom the notifier (as
> discussed previously) but it doesn't include the corresponding
> driver changes. Is there a patch missing from the set?

Hi Sakari, yes somehow patch 15/17 (the large patch to all drivers)
got dropped by the ML, maybe because the cc-list was too big?

I will resend with only linux-media and cc: you.

Steve


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
  2018-07-23 16:44     ` Steve Longerbeam
@ 2018-07-23 17:24       ` Sakari Ailus
  2018-08-04 10:33       ` jacopo mondi
  1 sibling, 0 replies; 36+ messages in thread
From: Sakari Ailus @ 2018-07-23 17:24 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Sakari Ailus, linux-media, Steve Longerbeam,
	Mauro Carvalho Chehab, Niklas Söderlund, Sebastian Reichel,
	Hans Verkuil, open list

On Mon, Jul 23, 2018 at 09:44:57AM -0700, Steve Longerbeam wrote:
> 
> 
> On 07/23/2018 05:35 AM, Sakari Ailus wrote:
> > Hi Steve,
> > 
> > Thanks for the update.
> > 
> > On Mon, Jul 09, 2018 at 03:39:16PM -0700, Steve Longerbeam wrote:
> > > All platform drivers have been converted to use
> > > v4l2_async_notifier_add_subdev(), in place of adding
> > > asd's to the notifier subdevs array. So the subdevs
> > > array can now be removed from struct v4l2_async_notifier,
> > > and remove the backward compatibility support for that
> > > array in v4l2-async.c.
> > > 
> > > Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> > This set removes the subdevs and num_subdevs fieldsfrom the notifier (as
> > discussed previously) but it doesn't include the corresponding
> > driver changes. Is there a patch missing from the set?
> 
> Hi Sakari, yes somehow patch 15/17 (the large patch to all drivers)
> got dropped by the ML, maybe because the cc-list was too big?
> 
> I will resend with only linux-media and cc: you.

I noticed the patch in my inbox and I re-pushed my v4l2-fwnode branch,
including that patch. Please still resend to the list. Thanks.

-- 
Sakari Ailus
sakari.ailus@linux.intel.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev
  2018-07-09 22:39 ` [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-08-03 15:13   ` jacopo mondi
  2018-08-04 16:39     ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: jacopo mondi @ 2018-08-03 15:13 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Niklas Söderlund, Sakari Ailus, Sebastian Reichel,
	Hans Verkuil, open list

[-- Attachment #1: Type: text/plain, Size: 13483 bytes --]

Hi Steven,
   I've a small remark, which is probably not only related to your
   patches but was there alreay... Anyway, please read below..


On Mon, Jul 09, 2018 at 03:39:03PM -0700, Steve Longerbeam wrote:
> v4l2_async_notifier_add_subdev() adds an asd to the notifier. It checks
> that no other equivalent asd's have already been added to this notifier's
> asd list, or to other registered notifier's waiting or done lists, and
> increments num_subdevs.
>
> v4l2_async_notifier_add_subdev() does not make use of the notifier subdevs
> array, otherwise it would have to re-allocate the array every time the
> function was called. In place of the subdevs array, the function adds
> the newly allocated asd to a new master asd_list. The function will
> return error with a WARN() if it is ever called with the subdevs array
> allocated.
>
> Drivers are now required to call a v4l2_async_notifier_init(), before the
> first call to v4l2_async_notifier_add_subdev(), in order to initialize
> the asd_list.
>
> In v4l2_async_notifier_has_async_subdev(), __v4l2_async_notifier_register(),
> and v4l2_async_notifier_cleanup(), maintain backward compatibility with
> the subdevs array, by alternatively operate on the subdevs array or a
> non-empty notifier->asd_list.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> Changes since v5:
> - export v4l2_async_notifier_init() which must be called by drivers.
>   Suggested by Sakari Ailus.
> Changes since v4:
> - none
> Changes since v3:
> - init notifier lists after the sanity checks.
> Changes since v2:
> - add a NULL asd pointer check to v4l2_async_notifier_asd_valid().
> Changes since v1:
> - none
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 189 +++++++++++++++++++++++++++--------
>  include/media/v4l2-async.h           |  34 ++++++-
>  2 files changed, 180 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 0e7e529..8e52df2 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -363,16 +363,26 @@ static bool v4l2_async_notifier_has_async_subdev(
>  	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd,
>  	unsigned int this_index)
>  {
> +	struct v4l2_async_subdev *asd_y;
>  	unsigned int j;
>
>  	lockdep_assert_held(&list_lock);
>
>  	/* Check that an asd is not being added more than once. */
> -	for (j = 0; j < this_index; j++) {
> -		struct v4l2_async_subdev *asd_y = notifier->subdevs[j];
> -
> -		if (asd_equal(asd, asd_y))
> -			return true;
> +	if (notifier->subdevs) {
> +		for (j = 0; j < this_index; j++) {
> +			asd_y = notifier->subdevs[j];
> +			if (asd_equal(asd, asd_y))
> +				return true;
> +		}
> +	} else {
> +		j = 0;
> +		list_for_each_entry(asd_y, &notifier->asd_list, asd_list) {
> +			if (j++ >= this_index)
> +				break;
> +			if (asd_equal(asd, asd_y))
> +				return true;
> +		}
>  	}
>
>  	/* Check that an asd does not exist in other notifiers. */
> @@ -383,10 +393,46 @@ static bool v4l2_async_notifier_has_async_subdev(
>  	return false;
>  }
>
> -static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> +static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier,
> +					 struct v4l2_async_subdev *asd,
> +					 unsigned int this_index)
>  {
>  	struct device *dev =
>  		notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL;
> +
> +	if (!asd)
> +		return -EINVAL;
> +
> +	switch (asd->match_type) {
> +	case V4L2_ASYNC_MATCH_CUSTOM:
> +	case V4L2_ASYNC_MATCH_DEVNAME:
> +	case V4L2_ASYNC_MATCH_I2C:
> +	case V4L2_ASYNC_MATCH_FWNODE:
> +		if (v4l2_async_notifier_has_async_subdev(notifier, asd,
> +							 this_index))
> +			return -EEXIST;
> +		break;
> +	default:
> +		dev_err(dev, "Invalid match type %u on %p\n",
> +			asd->match_type, asd);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
> +{
> +	mutex_lock(&list_lock);
> +
> +	INIT_LIST_HEAD(&notifier->asd_list);
> +
> +	mutex_unlock(&list_lock);
> +}
> +EXPORT_SYMBOL(v4l2_async_notifier_init);
> +
> +static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> +{
>  	struct v4l2_async_subdev *asd;
>  	int ret;
>  	int i;
> @@ -399,29 +445,25 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>
>  	mutex_lock(&list_lock);
>
> -	for (i = 0; i < notifier->num_subdevs; i++) {
> -		asd = notifier->subdevs[i];
> +	if (notifier->subdevs) {
> +		for (i = 0; i < notifier->num_subdevs; i++) {
> +			asd = notifier->subdevs[i];
>
> -		switch (asd->match_type) {
> -		case V4L2_ASYNC_MATCH_CUSTOM:
> -		case V4L2_ASYNC_MATCH_DEVNAME:
> -		case V4L2_ASYNC_MATCH_I2C:
> -		case V4L2_ASYNC_MATCH_FWNODE:
> -			if (v4l2_async_notifier_has_async_subdev(
> -				    notifier, asd, i)) {
> -				dev_err(dev,
> -					"asd has already been registered or in notifier's subdev list\n");
> -				ret = -EEXIST;
> +			ret = v4l2_async_notifier_asd_valid(notifier, asd, i);
> +			if (ret)
>  				goto err_unlock;
> -			}
> -			break;
> -		default:
> -			dev_err(dev, "Invalid match type %u on %p\n",
> -				asd->match_type, asd);
> -			ret = -EINVAL;
> -			goto err_unlock;
> +
> +			list_add_tail(&asd->list, &notifier->waiting);
> +		}
> +	} else {
> +		i = 0;
> +		list_for_each_entry(asd, &notifier->asd_list, asd_list) {
> +			ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);

Here the call stack looks like this, if I'm not mistaken:

list_for_each_entry(asd, notifier->asd_list, i) {
        v4l2_async_notifier_asd_valid(notifier, asd, i):
                v4l2_async_notifier_has_async_subdev(notifier, asd, i):
                        list_for_each_entry(asd_y, notifier->asd_list, j) {
                                if (j >= i) break;
                                if (asd == asd_y) return true;
                        }
}

Which is an optimization of O(n^2), but still bad.

This was there already there, it was:
for (i = 0; i < notifier->num_subdevs; i++) {
        v4l2_async_notifier_has_async_subdev(notifier, notifier->subdevs[i], i):
                for (j = 0; j < i; j++) {
                        if (notifier->subdevs[i] == notifier->subdevs[j])
                                return true;
                        }
                }
}

We're not talking high performances here, but I see no reason to go through
the list twice, as after switching to use your here introduced
v4l2_async_notifier_add_subdev() async subdevices are tested at endpoint
parsing time in v4l2_async_notifier_fwnode_parse_endpoint(), which
guarantees we can't have doubles later, at notifier registration time.

If I'm not wrong, this can be anyway optimized later.

Thanks
   j

> +			if (ret)
> +				goto err_unlock;
> +
> +			list_add_tail(&asd->list, &notifier->waiting);
>  		}
> -		list_add_tail(&asd->list, &notifier->waiting);
>  	}
>
>  	ret = v4l2_async_notifier_try_all_subdevs(notifier);
> @@ -511,36 +553,99 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
>  }
>  EXPORT_SYMBOL(v4l2_async_notifier_unregister);
>
> -void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
> +static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
>  {
> +	struct v4l2_async_subdev *asd, *tmp;
>  	unsigned int i;
>
> -	if (!notifier || !notifier->max_subdevs)
> +	if (!notifier)
>  		return;
>
> -	for (i = 0; i < notifier->num_subdevs; i++) {
> -		struct v4l2_async_subdev *asd = notifier->subdevs[i];
> +	if (notifier->subdevs) {
> +		if (!notifier->max_subdevs)
> +			return;
>
> -		switch (asd->match_type) {
> -		case V4L2_ASYNC_MATCH_FWNODE:
> -			fwnode_handle_put(asd->match.fwnode);
> -			break;
> -		default:
> -			WARN_ON_ONCE(true);
> -			break;
> +		for (i = 0; i < notifier->num_subdevs; i++) {
> +			asd = notifier->subdevs[i];
> +
> +			switch (asd->match_type) {
> +			case V4L2_ASYNC_MATCH_FWNODE:
> +				fwnode_handle_put(asd->match.fwnode);
> +				break;
> +			default:
> +				break;
> +			}
> +
> +			kfree(asd);
>  		}
>
> -		kfree(asd);
> +		notifier->max_subdevs = 0;
> +		kvfree(notifier->subdevs);
> +		notifier->subdevs = NULL;
> +	} else {
> +		list_for_each_entry_safe(asd, tmp,
> +					 &notifier->asd_list, asd_list) {
> +			switch (asd->match_type) {
> +			case V4L2_ASYNC_MATCH_FWNODE:
> +				fwnode_handle_put(asd->match.fwnode);
> +				break;
> +			default:
> +				break;
> +			}
> +
> +			list_del(&asd->asd_list);
> +			kfree(asd);
> +		}
>  	}
>
> -	notifier->max_subdevs = 0;
>  	notifier->num_subdevs = 0;
> +}
> +
> +void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
> +{
> +	mutex_lock(&list_lock);
> +
> +	__v4l2_async_notifier_cleanup(notifier);
>
> -	kvfree(notifier->subdevs);
> -	notifier->subdevs = NULL;
> +	mutex_unlock(&list_lock);
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
>
> +int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> +				   struct v4l2_async_subdev *asd)
> +{
> +	int ret;
> +
> +	mutex_lock(&list_lock);
> +
> +	if (notifier->num_subdevs >= V4L2_MAX_SUBDEVS) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	/*
> +	 * If caller uses this function, it cannot also allocate and
> +	 * place asd's in the notifier->subdevs array.
> +	 */
> +	if (WARN_ON(notifier->subdevs)) {
> +		ret = -EINVAL;
> +		goto unlock;
> +	}
> +
> +	ret = v4l2_async_notifier_asd_valid(notifier, asd,
> +					    notifier->num_subdevs);
> +	if (ret)
> +		goto unlock;
> +
> +	list_add_tail(&asd->asd_list, &notifier->asd_list);
> +	notifier->num_subdevs++;
> +
> +unlock:
> +	mutex_unlock(&list_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
> +
>  int v4l2_async_register_subdev(struct v4l2_subdev *sd)
>  {
>  	struct v4l2_async_notifier *subdev_notifier;
> @@ -614,7 +719,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
>  	mutex_lock(&list_lock);
>
>  	__v4l2_async_notifier_unregister(sd->subdev_notifier);
> -	v4l2_async_notifier_cleanup(sd->subdev_notifier);
> +	__v4l2_async_notifier_cleanup(sd->subdev_notifier);
>  	kfree(sd->subdev_notifier);
>  	sd->subdev_notifier = NULL;
>
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 1592d32..ab4d7ac 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -73,6 +73,8 @@ enum v4l2_async_match_type {
>   * @match.custom.priv:
>   *		Driver-specific private struct with match parameters
>   *		to be used if %V4L2_ASYNC_MATCH_CUSTOM.
> + * @asd_list:	used to add struct v4l2_async_subdev objects to the
> + *		master notifier @asd_list
>   * @list:	used to link struct v4l2_async_subdev objects, waiting to be
>   *		probed, to a notifier->waiting list
>   *
> @@ -98,6 +100,7 @@ struct v4l2_async_subdev {
>
>  	/* v4l2-async core private: not to be used by drivers */
>  	struct list_head list;
> +	struct list_head asd_list;
>  };
>
>  /**
> @@ -127,6 +130,7 @@ struct v4l2_async_notifier_operations {
>   * @v4l2_dev:	v4l2_device of the root notifier, NULL otherwise
>   * @sd:		sub-device that registered the notifier, NULL otherwise
>   * @parent:	parent notifier
> + * @asd_list:	master list of struct v4l2_async_subdev, replaces @subdevs
>   * @waiting:	list of struct v4l2_async_subdev, waiting for their drivers
>   * @done:	list of struct v4l2_subdev, already probed
>   * @list:	member in a global list of notifiers
> @@ -139,12 +143,38 @@ struct v4l2_async_notifier {
>  	struct v4l2_device *v4l2_dev;
>  	struct v4l2_subdev *sd;
>  	struct v4l2_async_notifier *parent;
> +	struct list_head asd_list;
>  	struct list_head waiting;
>  	struct list_head done;
>  	struct list_head list;
>  };
>
>  /**
> + * v4l2_async_notifier_init - Initialize a notifier.
> + *
> + * @notifier: pointer to &struct v4l2_async_notifier
> + *
> + * This function initializes the notifier @asd_list. It must be called
> + * before the first call to @v4l2_async_notifier_add_subdev.
> + */
> +void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
> +
> +/**
> + * v4l2_async_notifier_add_subdev - Add an async subdev to the
> + *				notifier's master asd list.
> + *
> + * @notifier: pointer to &struct v4l2_async_notifier
> + * @asd: pointer to &struct v4l2_async_subdev
> + *
> + * This can be used before registering a notifier to add an
> + * asd to the notifiers @asd_list. If the caller uses this
> + * method to compose an asd list, it must never allocate
> + * or place asd's in the @subdevs array.
> + */
> +int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> +				   struct v4l2_async_subdev *asd);
> +
> +/**
>   * v4l2_async_notifier_register - registers a subdevice asynchronous notifier
>   *
>   * @v4l2_dev: pointer to &struct v4l2_device
> @@ -177,7 +207,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
>   * Release memory resources related to a notifier, including the async
>   * sub-devices allocated for the purposes of the notifier but not the notifier
>   * itself. The user is responsible for calling this function to clean up the
> - * notifier after calling @v4l2_async_notifier_parse_fwnode_endpoints or
> + * notifier after calling
> + * @v4l2_async_notifier_add_subdev,
> + * @v4l2_async_notifier_parse_fwnode_endpoints or
>   * @v4l2_fwnode_reference_parse_sensor_common.
>   *
>   * There is no harm from calling v4l2_async_notifier_cleanup in other
> --
> 2.7.4
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
  2018-07-23 16:44     ` Steve Longerbeam
  2018-07-23 17:24       ` Sakari Ailus
@ 2018-08-04 10:33       ` jacopo mondi
  2018-08-04 17:20         ` Steve Longerbeam
  1 sibling, 1 reply; 36+ messages in thread
From: jacopo mondi @ 2018-08-04 10:33 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Sakari Ailus, linux-media, Steve Longerbeam,
	Mauro Carvalho Chehab, Sakari Ailus, Niklas Söderlund,
	Sebastian Reichel, Hans Verkuil, open list

[-- Attachment #1: Type: text/plain, Size: 3598 bytes --]

Hi Steve,

On Mon, Jul 23, 2018 at 09:44:57AM -0700, Steve Longerbeam wrote:
>
>
> On 07/23/2018 05:35 AM, Sakari Ailus wrote:
> >Hi Steve,
> >
> >Thanks for the update.
> >
> >On Mon, Jul 09, 2018 at 03:39:16PM -0700, Steve Longerbeam wrote:
> >>All platform drivers have been converted to use
> >>v4l2_async_notifier_add_subdev(), in place of adding
> >>asd's to the notifier subdevs array. So the subdevs
> >>array can now be removed from struct v4l2_async_notifier,
> >>and remove the backward compatibility support for that
> >>array in v4l2-async.c.
> >>
> >>Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> >This set removes the subdevs and num_subdevs fieldsfrom the notifier (as
> >discussed previously) but it doesn't include the corresponding
> >driver changes. Is there a patch missing from the set?
>
> Hi Sakari, yes somehow patch 15/17 (the large patch to all drivers)
> got dropped by the ML, maybe because the cc-list was too big?
>
> I will resend with only linux-media and cc: you.

For the Renesas CEU and Renesas R-Car VIN you can add my:

Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

I would have a very small comment on the renesas-ceu.c patch. I'm copying
the hunk here below as the patch didn't reach the mailing list

>@@ -1562,40 +1557,46 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
>                        dev_err(ceudev->dev,
>                                "No subdevice connected on endpoint %u.\n", i);
>                        ret = -ENODEV;
>-                       goto error_put_node;
>+                       goto error_cleanup;
>                }
>
>                ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep);
>                if (ret) {
>                if (ret) {
>                        dev_err(ceudev->dev,
>                                "Unable to parse endpoint #%u.\n", i);
>-                       goto error_put_node;
>+                       goto error_cleanup;
>                }
>
>                if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) {
>                        dev_err(ceudev->dev,
>                                "Only parallel input supported.\n");
>                        ret = -EINVAL;
>-                       goto error_put_node;
>+                       goto error_cleanup;
>                }
>
>                /* Setup the ceu subdevice and the async subdevice. */
>                ceu_sd = &ceudev->subdevs[i];
>                INIT_LIST_HEAD(&ceu_sd->asd.list);
>
>+               remote = of_graph_get_remote_port_parent(ep);
>                ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
>                ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
>-               ceu_sd->asd.match.fwnode =
>-                       fwnode_graph_get_remote_port_parent(
>-                                       of_fwnode_handle(ep));
>+               ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
>+
>+               ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
>+                                                    &ceu_sd->asd);
>+               if (ret) {
>+                       of_node_put(remote);

                        ^^^ The 'remote' device node is only put in
                        the error path
>
>+                       goto error_cleanup;
>+               }
>
>-               ceudev->asds[i] = &ceu_sd->asd;
>                of_node_put(ep);
>        }
>
>        return num_ep;
>
>-error_put_node:
>+error_cleanup:
>+       v4l2_async_notifier_cleanup(&ceudev->notifier);
>        of_node_put(ep);
>        return ret;
> }

Thanks
   j

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev
  2018-08-03 15:13   ` jacopo mondi
@ 2018-08-04 16:39     ` Steve Longerbeam
  0 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-08-04 16:39 UTC (permalink / raw)
  To: jacopo mondi
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Niklas Söderlund, Sakari Ailus, Sebastian Reichel,
	Hans Verkuil, open list

Hi Jacopo,


On 08/03/2018 08:13 AM, jacopo mondi wrote:
> Hi Steven,
>     I've a small remark, which is probably not only related to your
>     patches but was there alreay... Anyway, please read below..
>
>
> On Mon, Jul 09, 2018 at 03:39:03PM -0700, Steve Longerbeam wrote:
>> <snip>
>> +static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>> +{
>>   	struct v4l2_async_subdev *asd;
>>   	int ret;
>>   	int i;
>> @@ -399,29 +445,25 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>>
>>   	mutex_lock(&list_lock);
>>
>> -	for (i = 0; i < notifier->num_subdevs; i++) {
>> -		asd = notifier->subdevs[i];
>> +	if (notifier->subdevs) {
>> +		for (i = 0; i < notifier->num_subdevs; i++) {
>> +			asd = notifier->subdevs[i];
>>
>> -		switch (asd->match_type) {
>> -		case V4L2_ASYNC_MATCH_CUSTOM:
>> -		case V4L2_ASYNC_MATCH_DEVNAME:
>> -		case V4L2_ASYNC_MATCH_I2C:
>> -		case V4L2_ASYNC_MATCH_FWNODE:
>> -			if (v4l2_async_notifier_has_async_subdev(
>> -				    notifier, asd, i)) {
>> -				dev_err(dev,
>> -					"asd has already been registered or in notifier's subdev list\n");
>> -				ret = -EEXIST;
>> +			ret = v4l2_async_notifier_asd_valid(notifier, asd, i);
>> +			if (ret)
>>   				goto err_unlock;
>> -			}
>> -			break;
>> -		default:
>> -			dev_err(dev, "Invalid match type %u on %p\n",
>> -				asd->match_type, asd);
>> -			ret = -EINVAL;
>> -			goto err_unlock;
>> +
>> +			list_add_tail(&asd->list, &notifier->waiting);
>> +		}
>> +	} else {
>> +		i = 0;
>> +		list_for_each_entry(asd, &notifier->asd_list, asd_list) {
>> +			ret = v4l2_async_notifier_asd_valid(notifier, asd, i++);
> Here the call stack looks like this, if I'm not mistaken:
>
> list_for_each_entry(asd, notifier->asd_list, i) {
>          v4l2_async_notifier_asd_valid(notifier, asd, i):
>                  v4l2_async_notifier_has_async_subdev(notifier, asd, i):
>                          list_for_each_entry(asd_y, notifier->asd_list, j) {
>                                  if (j >= i) break;
>                                  if (asd == asd_y) return true;
>                          }
> }
>
> Which is an optimization of O(n^2), but still bad.
>
> This was there already there, it was:

Agreed, it should be safe to remove the check for duplicate
asd's at notifier registration, since this check is done now
in v4l2_async_notifier_add_subdev().

Steve

> for (i = 0; i < notifier->num_subdevs; i++) {
>          v4l2_async_notifier_has_async_subdev(notifier, notifier->subdevs[i], i):
>                  for (j = 0; j < i; j++) {
>                          if (notifier->subdevs[i] == notifier->subdevs[j])
>                                  return true;
>                          }
>                  }
> }
>
> We're not talking high performances here, but I see no reason to go through
> the list twice, as after switching to use your here introduced
> v4l2_async_notifier_add_subdev() async subdevices are tested at endpoint
> parsing time in v4l2_async_notifier_fwnode_parse_endpoint(), which
> guarantees we can't have doubles later, at notifier registration time.
>
> If I'm not wrong, this can be anyway optimized later.
>
> Thanks
>     j
>
>


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array
  2018-08-04 10:33       ` jacopo mondi
@ 2018-08-04 17:20         ` Steve Longerbeam
  0 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-08-04 17:20 UTC (permalink / raw)
  To: jacopo mondi
  Cc: Sakari Ailus, linux-media, Steve Longerbeam,
	Mauro Carvalho Chehab, Sakari Ailus, Niklas Söderlund,
	Sebastian Reichel, Hans Verkuil, open list

Hi Jacopo,


On 08/04/2018 03:33 AM, jacopo mondi wrote:
> Hi Steve,
>
> On Mon, Jul 23, 2018 at 09:44:57AM -0700, Steve Longerbeam wrote:
>>
>> On 07/23/2018 05:35 AM, Sakari Ailus wrote:
>>> Hi Steve,
>>>
>>> Thanks for the update.
>>>
>>> On Mon, Jul 09, 2018 at 03:39:16PM -0700, Steve Longerbeam wrote:
>>>> All platform drivers have been converted to use
>>>> v4l2_async_notifier_add_subdev(), in place of adding
>>>> asd's to the notifier subdevs array. So the subdevs
>>>> array can now be removed from struct v4l2_async_notifier,
>>>> and remove the backward compatibility support for that
>>>> array in v4l2-async.c.
>>>>
>>>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>>> This set removes the subdevs and num_subdevs fieldsfrom the notifier (as
>>> discussed previously) but it doesn't include the corresponding
>>> driver changes. Is there a patch missing from the set?
>> Hi Sakari, yes somehow patch 15/17 (the large patch to all drivers)
>> got dropped by the ML, maybe because the cc-list was too big?
>>
>> I will resend with only linux-media and cc: you.
> For the Renesas CEU and Renesas R-Car VIN you can add my:
>
> Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks for testing!

>
> I would have a very small comment on the renesas-ceu.c patch. I'm copying
> the hunk here below as the patch didn't reach the mailing list
>
>> @@ -1562,40 +1557,46 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
>>                         dev_err(ceudev->dev,
>>                                 "No subdevice connected on endpoint %u.\n", i);
>>                         ret = -ENODEV;
>> -                       goto error_put_node;
>> +                       goto error_cleanup;
>>                 }
>>
>>                 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep);
>>                 if (ret) {
>>                 if (ret) {
>>                         dev_err(ceudev->dev,
>>                                 "Unable to parse endpoint #%u.\n", i);
>> -                       goto error_put_node;
>> +                       goto error_cleanup;
>>                 }
>>
>>                 if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) {
>>                         dev_err(ceudev->dev,
>>                                 "Only parallel input supported.\n");
>>                         ret = -EINVAL;
>> -                       goto error_put_node;
>> +                       goto error_cleanup;
>>                 }
>>
>>                 /* Setup the ceu subdevice and the async subdevice. */
>>                 ceu_sd = &ceudev->subdevs[i];
>>                 INIT_LIST_HEAD(&ceu_sd->asd.list);
>>
>> +               remote = of_graph_get_remote_port_parent(ep);
>>                 ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
>>                 ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
>> -               ceu_sd->asd.match.fwnode =
>> -                       fwnode_graph_get_remote_port_parent(
>> -                                       of_fwnode_handle(ep));
>> +               ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
>> +
>> +               ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
>> +                                                    &ceu_sd->asd);
>> +               if (ret) {
>> +                       of_node_put(remote);
>                          ^^^ The 'remote' device node is only put in
>                          the error path

If v4l2_async_notifier_add_subdev() succeeds, then the reference
is kept on the remote node until the asd is freed in
v4l2_async_notifier_cleanup(). Otherwise if
v4l2_async_notifier_add_subdev() fails, the asd is not
added to the notifier asd_list so the caller is responsible
for putting the remote node. So the only case where
the remote needs to be put is in the line you marked above.
Otherwise in the other error-out paths, the remote nodes
for all asd's that have been added will be put below in the
error_cleanup path.

Steve


>> +                       goto error_cleanup;
>> +               }
>>
>> -               ceudev->asds[i] = &ceu_sd->asd;
>>                 of_node_put(ep);
>>         }
>>
>>         return num_ep;
>>
>> -error_put_node:
>> +error_cleanup:
>> +       v4l2_async_notifier_cleanup(&ceudev->notifier);
>>         of_node_put(ep);
>>         return ret;
>> }
> Thanks
>     j


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-07-09 22:39 ` [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
@ 2018-09-13 10:37   ` jacopo mondi
  2018-09-13 12:44     ` Sakari Ailus
  0 siblings, 1 reply; 36+ messages in thread
From: jacopo mondi @ 2018-09-13 10:37 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Sakari Ailus, Sebastian Reichel, Hans Verkuil,
	Niklas Söderlund, open list

[-- Attachment #1: Type: text/plain, Size: 6515 bytes --]

Hi Steve,

On Mon, Jul 09, 2018 at 03:39:06PM -0700, Steve Longerbeam wrote:
> Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
> for parsing a sub-device's fwnode port endpoints for connected remote
> sub-devices, registering a sub-device notifier, and then registering
> the sub-device itself.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> Changes since v5:
> - add call to v4l2_async_notifier_init().
> Changes since v4:
> - none
> Changes since v3:
> - remove support for port sub-devices, such sub-devices will have to
>   role their own.
> Changes since v2:
> - fix error-out path in v4l2_async_register_fwnode_subdev() that forgot
>   to put device.
> Changes since v1:
> - add #include <media/v4l2-subdev.h> to v4l2-fwnode.h for
>   'struct v4l2_subdev' declaration.
> ---
>  drivers/media/v4l2-core/v4l2-fwnode.c | 64 +++++++++++++++++++++++++++++++++++
>  include/media/v4l2-fwnode.h           | 38 +++++++++++++++++++++
>  2 files changed, 102 insertions(+)
>
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> index 67ad333..94d867a 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -872,6 +872,70 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
>
> +int v4l2_async_register_fwnode_subdev(

The meat of this function is to register a subdev with a notifier,
so I would make it clear in the function name which is otherwise
misleading

> +	struct v4l2_subdev *sd, size_t asd_struct_size,
> +	unsigned int *ports, unsigned int num_ports,
> +	int (*parse_endpoint)(struct device *dev,
> +			      struct v4l2_fwnode_endpoint *vep,
> +			      struct v4l2_async_subdev *asd))
> +{
> +	struct v4l2_async_notifier *notifier;
> +	struct device *dev = sd->dev;
> +	struct fwnode_handle *fwnode;
> +	int ret;
> +
> +	if (WARN_ON(!dev))
> +		return -ENODEV;
> +
> +	fwnode = dev_fwnode(dev);
> +	if (!fwnode_device_is_available(fwnode))
> +		return -ENODEV;
> +
> +	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
> +	if (!notifier)
> +		return -ENOMEM;
> +
> +	v4l2_async_notifier_init(notifier);
> +
> +	if (!ports) {
> +		ret = v4l2_async_notifier_parse_fwnode_endpoints(
> +			dev, notifier, asd_struct_size, parse_endpoint);
> +		if (ret < 0)
> +			goto out_cleanup;
> +	} else {
> +		unsigned int i;
> +
> +		for (i = 0; i < num_ports; i++) {

It's not particularly exciting to iterate on pointers received from
callers without checking for num_ports first.

Also the caller has to allocate an array of "ports" and keep track of it
just to pass it to this function and I don't see a way to set the
notifier's ops before the notifier gets registered here below.

> +			ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> +				dev, notifier, asd_struct_size,
> +				ports[i], parse_endpoint);
> +			if (ret < 0)
> +				goto out_cleanup;
> +		}
> +	}
> +
> +	ret = v4l2_async_subdev_notifier_register(sd, notifier);
> +	if (ret < 0)
> +		goto out_cleanup;
> +
> +	ret = v4l2_async_register_subdev(sd);
> +	if (ret < 0)
> +		goto out_unregister;
> +
> +	sd->subdev_notifier = notifier;

This is set already by v4l2_async_subdev_notifier_register()

In general, I have doubts this function is really needed. It requires
the caller to reserve memory just to pass down a list of intergers,
and there is no way to set subdev ops.

Could you have a look at how drivers/media/platform/rcar-vin/rcar-csi2.c
registers a subdevice and an associated notifier and see if in your
opinion it can be implemented in the same way in your imx csi/csi2 driver,
or you still like this one most?

Thanks
   j
> +
> +	return 0;
> +
> +out_unregister:
> +	v4l2_async_notifier_unregister(notifier);
> +out_cleanup:
> +	v4l2_async_notifier_cleanup(notifier);
> +	kfree(notifier);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(v4l2_async_register_fwnode_subdev);
> +
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
>  MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
> diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
> index ea7a8b2..031ebb0 100644
> --- a/include/media/v4l2-fwnode.h
> +++ b/include/media/v4l2-fwnode.h
> @@ -23,6 +23,7 @@
>  #include <linux/types.h>
>
>  #include <media/v4l2-mediabus.h>
> +#include <media/v4l2-subdev.h>
>
>  struct fwnode_handle;
>  struct v4l2_async_notifier;
> @@ -360,4 +361,41 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
>  int v4l2_async_notifier_parse_fwnode_sensor_common(
>  	struct device *dev, struct v4l2_async_notifier *notifier);
>
> +/**
> + * v4l2_async_register_fwnode_subdev - registers a sub-device to the
> + *					asynchronous sub-device framework
> + *					and parses fwnode endpoints
> + *
> + * @sd: pointer to struct &v4l2_subdev
> + * @asd_struct_size: size of the driver's async sub-device struct, including
> + *		     sizeof(struct v4l2_async_subdev). The &struct
> + *		     v4l2_async_subdev shall be the first member of
> + *		     the driver's async sub-device struct, i.e. both
> + *		     begin at the same memory address.
> + * @ports: array of port id's to parse for fwnode endpoints. If NULL, will
> + *	   parse all ports owned by the sub-device.
> + * @num_ports: number of ports in @ports array. Ignored if @ports is NULL.
> + * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
> + *		    endpoint. Optional.
> + *
> + * This function is just like v4l2_async_register_subdev() with the
> + * exception that calling it will also allocate a notifier for the
> + * sub-device, parse the sub-device's firmware node endpoints using
> + * v4l2_async_notifier_parse_fwnode_endpoints() or
> + * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and
> + * registers the sub-device notifier. The sub-device is similarly
> + * unregistered by calling v4l2_async_unregister_subdev().
> + *
> + * While registered, the subdev module is marked as in-use.
> + *
> + * An error is returned if the module is no longer loaded on any attempts
> + * to register it.
> + */
> +int v4l2_async_register_fwnode_subdev(
> +	struct v4l2_subdev *sd, size_t asd_struct_size,
> +	unsigned int *ports, unsigned int num_ports,
> +	int (*parse_endpoint)(struct device *dev,
> +			      struct v4l2_fwnode_endpoint *vep,
> +			      struct v4l2_async_subdev *asd));
> +
>  #endif /* _V4L2_FWNODE_H */
> --
> 2.7.4
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-09-13 10:37   ` jacopo mondi
@ 2018-09-13 12:44     ` Sakari Ailus
  2018-09-13 12:58       ` jacopo mondi
  0 siblings, 1 reply; 36+ messages in thread
From: Sakari Ailus @ 2018-09-13 12:44 UTC (permalink / raw)
  To: jacopo mondi
  Cc: Steve Longerbeam, linux-media, Steve Longerbeam,
	Mauro Carvalho Chehab, Sebastian Reichel, Hans Verkuil,
	Niklas Söderlund, open list

Hi Jacopo,

On Thu, Sep 13, 2018 at 12:37:27PM +0200, jacopo mondi wrote:
> Hi Steve,
> 
> On Mon, Jul 09, 2018 at 03:39:06PM -0700, Steve Longerbeam wrote:
> > Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
> > for parsing a sub-device's fwnode port endpoints for connected remote
> > sub-devices, registering a sub-device notifier, and then registering
> > the sub-device itself.
> >
> > Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> > ---
> > Changes since v5:
> > - add call to v4l2_async_notifier_init().
> > Changes since v4:
> > - none
> > Changes since v3:
> > - remove support for port sub-devices, such sub-devices will have to
> >   role their own.
> > Changes since v2:
> > - fix error-out path in v4l2_async_register_fwnode_subdev() that forgot
> >   to put device.
> > Changes since v1:
> > - add #include <media/v4l2-subdev.h> to v4l2-fwnode.h for
> >   'struct v4l2_subdev' declaration.
> > ---
> >  drivers/media/v4l2-core/v4l2-fwnode.c | 64 +++++++++++++++++++++++++++++++++++
> >  include/media/v4l2-fwnode.h           | 38 +++++++++++++++++++++
> >  2 files changed, 102 insertions(+)
> >
> > diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> > index 67ad333..94d867a 100644
> > --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> > +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> > @@ -872,6 +872,70 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
> >  }
> >  EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
> >
> > +int v4l2_async_register_fwnode_subdev(
> 
> The meat of this function is to register a subdev with a notifier,
> so I would make it clear in the function name which is otherwise
> misleading
> 
> > +	struct v4l2_subdev *sd, size_t asd_struct_size,
> > +	unsigned int *ports, unsigned int num_ports,
> > +	int (*parse_endpoint)(struct device *dev,
> > +			      struct v4l2_fwnode_endpoint *vep,
> > +			      struct v4l2_async_subdev *asd))
> > +{
> > +	struct v4l2_async_notifier *notifier;
> > +	struct device *dev = sd->dev;
> > +	struct fwnode_handle *fwnode;
> > +	int ret;
> > +
> > +	if (WARN_ON(!dev))
> > +		return -ENODEV;
> > +
> > +	fwnode = dev_fwnode(dev);
> > +	if (!fwnode_device_is_available(fwnode))
> > +		return -ENODEV;
> > +
> > +	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
> > +	if (!notifier)
> > +		return -ENOMEM;
> > +
> > +	v4l2_async_notifier_init(notifier);
> > +
> > +	if (!ports) {
> > +		ret = v4l2_async_notifier_parse_fwnode_endpoints(
> > +			dev, notifier, asd_struct_size, parse_endpoint);
> > +		if (ret < 0)
> > +			goto out_cleanup;
> > +	} else {
> > +		unsigned int i;
> > +
> > +		for (i = 0; i < num_ports; i++) {
> 
> It's not particularly exciting to iterate on pointers received from
> callers without checking for num_ports first.

The loop is not executed if num_ports is zero, so I don't see a problem
with that.

> 
> Also the caller has to allocate an array of "ports" and keep track of it
> just to pass it to this function and I don't see a way to set the
> notifier's ops before the notifier gets registered here below.

True; this can be seen as an omission but quite a few drivers have no need
for this either. It could be added later on --- I think it'd make perfect
sense.

> 
> > +			ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> > +				dev, notifier, asd_struct_size,
> > +				ports[i], parse_endpoint);
> > +			if (ret < 0)
> > +				goto out_cleanup;
> > +		}
> > +	}
> > +
> > +	ret = v4l2_async_subdev_notifier_register(sd, notifier);
> > +	if (ret < 0)
> > +		goto out_cleanup;
> > +
> > +	ret = v4l2_async_register_subdev(sd);
> > +	if (ret < 0)
> > +		goto out_unregister;
> > +
> > +	sd->subdev_notifier = notifier;
> 
> This is set already by v4l2_async_subdev_notifier_register()

The same pattern is actually present in
v4l2_async_register_subdev_sensor_common(). It's used in unregistration
that can only happen after the registration, i.e. this function, has
completed.

> 
> In general, I have doubts this function is really needed. It requires
> the caller to reserve memory just to pass down a list of intergers,
> and there is no way to set subdev ops.
> 
> Could you have a look at how drivers/media/platform/rcar-vin/rcar-csi2.c
> registers a subdevice and an associated notifier and see if in your
> opinion it can be implemented in the same way in your imx csi/csi2 driver,
> or you still like this one most?

I was actually thinking of changing this later on a bit. I came to think of
this after picking up the patchset to my tree... oh well.

This function is meant for cases where you have multiple ports. That's not
working very nicely at the moment, and even with my patches, you can't pass
default configuration to e.g. v4l2_async_notifier_parse_fwnode_endpoints().
So there's definitely work to do. I'd like to move the details of parsing
out of drivers; every driver is doing almost the same but just in a little
bit different way.

The arguments should to be put into a struct. That way we get rid of a very
long series of hard-to-read function arguments, as well as we don't need to
change every caller when the function gets something new and interesting to
do.

Right now the entire patchset is so big (40 patches) that I'd prefer to get
it in unless serious issues are found, and proceed the development on top.

-- 
Kind regards,

Sakari Ailus
sakari.ailus@linux.intel.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-09-13 12:44     ` Sakari Ailus
@ 2018-09-13 12:58       ` jacopo mondi
  2018-09-14  0:57         ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: jacopo mondi @ 2018-09-13 12:58 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Steve Longerbeam, linux-media, Steve Longerbeam,
	Mauro Carvalho Chehab, Sebastian Reichel, Hans Verkuil,
	Niklas Söderlund, open list

[-- Attachment #1: Type: text/plain, Size: 6182 bytes --]

Hi Sakari,

On Thu, Sep 13, 2018 at 03:44:25PM +0300, Sakari Ailus wrote:
> Hi Jacopo,
>
> On Thu, Sep 13, 2018 at 12:37:27PM +0200, jacopo mondi wrote:
> > Hi Steve,
> >
> > On Mon, Jul 09, 2018 at 03:39:06PM -0700, Steve Longerbeam wrote:
> > > Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
> > > for parsing a sub-device's fwnode port endpoints for connected remote
> > > sub-devices, registering a sub-device notifier, and then registering
> > > the sub-device itself.
> > >
> > > Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> > > ---
> > > Changes since v5:
> > > - add call to v4l2_async_notifier_init().
> > > Changes since v4:
> > > - none
> > > Changes since v3:
> > > - remove support for port sub-devices, such sub-devices will have to
> > >   role their own.
> > > Changes since v2:
> > > - fix error-out path in v4l2_async_register_fwnode_subdev() that forgot
> > >   to put device.
> > > Changes since v1:
> > > - add #include <media/v4l2-subdev.h> to v4l2-fwnode.h for
> > >   'struct v4l2_subdev' declaration.
> > > ---
> > >  drivers/media/v4l2-core/v4l2-fwnode.c | 64 +++++++++++++++++++++++++++++++++++
> > >  include/media/v4l2-fwnode.h           | 38 +++++++++++++++++++++
> > >  2 files changed, 102 insertions(+)
> > >
> > > diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> > > index 67ad333..94d867a 100644
> > > --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> > > +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> > > @@ -872,6 +872,70 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
> > >  }
> > >  EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
> > >
> > > +int v4l2_async_register_fwnode_subdev(
> >
> > The meat of this function is to register a subdev with a notifier,
> > so I would make it clear in the function name which is otherwise
> > misleading
> >
> > > +	struct v4l2_subdev *sd, size_t asd_struct_size,
> > > +	unsigned int *ports, unsigned int num_ports,
> > > +	int (*parse_endpoint)(struct device *dev,
> > > +			      struct v4l2_fwnode_endpoint *vep,
> > > +			      struct v4l2_async_subdev *asd))
> > > +{
> > > +	struct v4l2_async_notifier *notifier;
> > > +	struct device *dev = sd->dev;
> > > +	struct fwnode_handle *fwnode;
> > > +	int ret;
> > > +
> > > +	if (WARN_ON(!dev))
> > > +		return -ENODEV;
> > > +
> > > +	fwnode = dev_fwnode(dev);
> > > +	if (!fwnode_device_is_available(fwnode))
> > > +		return -ENODEV;
> > > +
> > > +	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
> > > +	if (!notifier)
> > > +		return -ENOMEM;
> > > +
> > > +	v4l2_async_notifier_init(notifier);
> > > +
> > > +	if (!ports) {
> > > +		ret = v4l2_async_notifier_parse_fwnode_endpoints(
> > > +			dev, notifier, asd_struct_size, parse_endpoint);
> > > +		if (ret < 0)
> > > +			goto out_cleanup;
> > > +	} else {
> > > +		unsigned int i;
> > > +
> > > +		for (i = 0; i < num_ports; i++) {
> >
> > It's not particularly exciting to iterate on pointers received from
> > callers without checking for num_ports first.
>
> The loop is not executed if num_ports is zero, so I don't see a problem
> with that.
>

I know this is internal drivers API and failures are meant to be
catched early in development, but what if the actual number of ports
identifiers is < then the num_ports parameter?

> >
> > Also the caller has to allocate an array of "ports" and keep track of it
> > just to pass it to this function and I don't see a way to set the
> > notifier's ops before the notifier gets registered here below.
>
> True; this can be seen as an omission but quite a few drivers have no need
> for this either. It could be added later on --- I think it'd make perfect
> sense.
>

In a 'notifier configuration' structure that gather these and existing
function parameters together as you suggested...

> >
> > > +			ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> > > +				dev, notifier, asd_struct_size,
> > > +				ports[i], parse_endpoint);
> > > +			if (ret < 0)
> > > +				goto out_cleanup;
> > > +		}
> > > +	}
> > > +
> > > +	ret = v4l2_async_subdev_notifier_register(sd, notifier);
> > > +	if (ret < 0)
> > > +		goto out_cleanup;
> > > +
> > > +	ret = v4l2_async_register_subdev(sd);
> > > +	if (ret < 0)
> > > +		goto out_unregister;
> > > +
> > > +	sd->subdev_notifier = notifier;
> >
> > This is set already by v4l2_async_subdev_notifier_register()
>
> The same pattern is actually present in
> v4l2_async_register_subdev_sensor_common(). It's used in unregistration
> that can only happen after the registration, i.e. this function, has
> completed.
>
> >
> > In general, I have doubts this function is really needed. It requires
> > the caller to reserve memory just to pass down a list of intergers,
> > and there is no way to set subdev ops.
> >
> > Could you have a look at how drivers/media/platform/rcar-vin/rcar-csi2.c
> > registers a subdevice and an associated notifier and see if in your
> > opinion it can be implemented in the same way in your imx csi/csi2 driver,
> > or you still like this one most?
>
> I was actually thinking of changing this later on a bit. I came to think of
> this after picking up the patchset to my tree... oh well.
>
> This function is meant for cases where you have multiple ports. That's not
> working very nicely at the moment, and even with my patches, you can't pass
> default configuration to e.g. v4l2_async_notifier_parse_fwnode_endpoints().
> So there's definitely work to do. I'd like to move the details of parsing
> out of drivers; every driver is doing almost the same but just in a little
> bit different way.
>

I see...

> The arguments should to be put into a struct. That way we get rid of a very
> long series of hard-to-read function arguments, as well as we don't need to
> change every caller when the function gets something new and interesting to
> do.
>
> Right now the entire patchset is so big (40 patches) that I'd prefer to get
> it in unless serious issues are found, and proceed the development on top.
>

Sure, please go ahead and thanks for the reply.

Cheers
   j

> --
> Kind regards,
>
> Sakari Ailus
> sakari.ailus@linux.intel.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-09-13 12:58       ` jacopo mondi
@ 2018-09-14  0:57         ` Steve Longerbeam
  0 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-09-14  0:57 UTC (permalink / raw)
  To: jacopo mondi, Sakari Ailus
  Cc: Steve Longerbeam, linux-media, Mauro Carvalho Chehab,
	Sebastian Reichel, Hans Verkuil, Niklas Söderlund,
	open list

Hi Jacopo,


On 09/13/2018 05:58 AM, jacopo mondi wrote:
> Hi Sakari,
>
> On Thu, Sep 13, 2018 at 03:44:25PM +0300, Sakari Ailus wrote:
>> Hi Jacopo,
>>
>> On Thu, Sep 13, 2018 at 12:37:27PM +0200, jacopo mondi wrote:
>>> Hi Steve,
>>>
>>> On Mon, Jul 09, 2018 at 03:39:06PM -0700, Steve Longerbeam wrote:
>>>> Adds v4l2_async_register_fwnode_subdev(), which is a convenience function
>>>> for parsing a sub-device's fwnode port endpoints for connected remote
>>>> sub-devices, registering a sub-device notifier, and then registering
>>>> the sub-device itself.
>>>>
>>>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>>>> ---
>>>> Changes since v5:
>>>> - add call to v4l2_async_notifier_init().
>>>> Changes since v4:
>>>> - none
>>>> Changes since v3:
>>>> - remove support for port sub-devices, such sub-devices will have to
>>>>    role their own.
>>>> Changes since v2:
>>>> - fix error-out path in v4l2_async_register_fwnode_subdev() that forgot
>>>>    to put device.
>>>> Changes since v1:
>>>> - add #include <media/v4l2-subdev.h> to v4l2-fwnode.h for
>>>>    'struct v4l2_subdev' declaration.
>>>> ---
>>>>   drivers/media/v4l2-core/v4l2-fwnode.c | 64 +++++++++++++++++++++++++++++++++++
>>>>   include/media/v4l2-fwnode.h           | 38 +++++++++++++++++++++
>>>>   2 files changed, 102 insertions(+)
>>>>
>>>> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
>>>> index 67ad333..94d867a 100644
>>>> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
>>>> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
>>>> @@ -872,6 +872,70 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
>>>>   }
>>>>   EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
>>>>
>>>> +int v4l2_async_register_fwnode_subdev(
>>> The meat of this function is to register a subdev with a notifier,
>>> so I would make it clear in the function name which is otherwise
>>> misleading

Yes, I struggled with how to name this function without making it
ridiculously long.

>>>
>>>> +	struct v4l2_subdev *sd, size_t asd_struct_size,
>>>> +	unsigned int *ports, unsigned int num_ports,
>>>> +	int (*parse_endpoint)(struct device *dev,
>>>> +			      struct v4l2_fwnode_endpoint *vep,
>>>> +			      struct v4l2_async_subdev *asd))
>>>> +{
>>>> +	struct v4l2_async_notifier *notifier;
>>>> +	struct device *dev = sd->dev;
>>>> +	struct fwnode_handle *fwnode;
>>>> +	int ret;
>>>> +
>>>> +	if (WARN_ON(!dev))
>>>> +		return -ENODEV;
>>>> +
>>>> +	fwnode = dev_fwnode(dev);
>>>> +	if (!fwnode_device_is_available(fwnode))
>>>> +		return -ENODEV;
>>>> +
>>>> +	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
>>>> +	if (!notifier)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	v4l2_async_notifier_init(notifier);
>>>> +
>>>> +	if (!ports) {
>>>> +		ret = v4l2_async_notifier_parse_fwnode_endpoints(
>>>> +			dev, notifier, asd_struct_size, parse_endpoint);
>>>> +		if (ret < 0)
>>>> +			goto out_cleanup;
>>>> +	} else {
>>>> +		unsigned int i;
>>>> +
>>>> +		for (i = 0; i < num_ports; i++) {
>>> It's not particularly exciting to iterate on pointers received from
>>> callers without checking for num_ports first.
>> The loop is not executed if num_ports is zero, so I don't see a problem
>> with that.
>>
> I know this is internal drivers API and failures are meant to be
> catched early in development, but what if the actual number of ports
> identifiers is < then the num_ports parameter?

see below.

>
>>> Also the caller has to allocate an array of "ports" and keep track of it
>>> just to pass it to this function

I agree that it is cumbersome to require callers to allocate a ports
array. Perhaps the ports array and num_ports could be replaced by a
u64 bit mask, but that would limit port ID's to 0 - 63.


Steve


>>>   and I don't see a way to set the
>>> notifier's ops before the notifier gets registered here below.
>> True; this can be seen as an omission but quite a few drivers have no need
>> for this either. It could be added later on --- I think it'd make perfect
>> sense.
>>
> In a 'notifier configuration' structure that gather these and existing
> function parameters together as you suggested...
>
>>>> +			ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
>>>> +				dev, notifier, asd_struct_size,
>>>> +				ports[i], parse_endpoint);
>>>> +			if (ret < 0)
>>>> +				goto out_cleanup;
>>>> +		}
>>>> +	}
>>>> +
>>>> +	ret = v4l2_async_subdev_notifier_register(sd, notifier);
>>>> +	if (ret < 0)
>>>> +		goto out_cleanup;
>>>> +
>>>> +	ret = v4l2_async_register_subdev(sd);
>>>> +	if (ret < 0)
>>>> +		goto out_unregister;
>>>> +
>>>> +	sd->subdev_notifier = notifier;
>>> This is set already by v4l2_async_subdev_notifier_register()
>> The same pattern is actually present in
>> v4l2_async_register_subdev_sensor_common(). It's used in unregistration
>> that can only happen after the registration, i.e. this function, has
>> completed.
>>
>>> In general, I have doubts this function is really needed. It requires
>>> the caller to reserve memory just to pass down a list of intergers,
>>> and there is no way to set subdev ops.
>>>
>>> Could you have a look at how drivers/media/platform/rcar-vin/rcar-csi2.c
>>> registers a subdevice and an associated notifier and see if in your
>>> opinion it can be implemented in the same way in your imx csi/csi2 driver,
>>> or you still like this one most?
>> I was actually thinking of changing this later on a bit. I came to think of
>> this after picking up the patchset to my tree... oh well.
>>
>> This function is meant for cases where you have multiple ports. That's not
>> working very nicely at the moment, and even with my patches, you can't pass
>> default configuration to e.g. v4l2_async_notifier_parse_fwnode_endpoints().
>> So there's definitely work to do. I'd like to move the details of parsing
>> out of drivers; every driver is doing almost the same but just in a little
>> bit different way.
>>
> I see...
>
>> The arguments should to be put into a struct. That way we get rid of a very
>> long series of hard-to-read function arguments, as well as we don't need to
>> change every caller when the function gets something new and interesting to
>> do.
>>
>> Right now the entire patchset is so big (40 patches) that I'd prefer to get
>> it in unless serious issues are found, and proceed the development on top.
>>
> Sure, please go ahead and thanks for the reply.
>
> Cheers
>     j
>
>> --
>> Kind regards,
>>
>> Sakari Ailus
>> sakari.ailus@linux.intel.com


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-07-09 22:39 ` [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
@ 2018-09-24 17:06   ` Mauro Carvalho Chehab
  2018-09-25 21:04     ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: Mauro Carvalho Chehab @ 2018-09-24 17:06 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: linux-media, Steve Longerbeam, Mauro Carvalho Chehab,
	Sakari Ailus, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list

Em Mon,  9 Jul 2018 15:39:02 -0700
Steve Longerbeam <slongerbeam@gmail.com> escreveu:

> Generalize v4l2_async_notifier_fwnode_has_async_subdev() to allow
> searching for any type of async subdev, not just fwnodes. Rename to
> v4l2_async_notifier_has_async_subdev() and pass it an asd pointer.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
> Changes since v5:
> - none
> Changes since v4:
> - none
> Changes since v3:
> - removed TODO to support asd compare with CUSTOM match type in
>   asd_equal().
> Changes since v2:
> - code optimization in asd_equal(), and remove unneeded braces,
>   suggested by Sakari Ailus.
> Changes since v1:
> - none
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 73 +++++++++++++++++++++---------------
>  1 file changed, 43 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 2b08d03..0e7e529 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -124,6 +124,31 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
>  	return NULL;
>  }
>  
> +/* Compare two asd's for equivalence */

Please, on comments, instead of "asd" prefer to use what this 3 random
letters mean, e. g.:
	asd -> asynchronous subdevice

> +static bool asd_equal(struct v4l2_async_subdev *asd_x,
> +		      struct v4l2_async_subdev *asd_y)
> +{
> +	if (asd_x->match_type != asd_y->match_type)
> +		return false;
> +
> +	switch (asd_x->match_type) {
> +	case V4L2_ASYNC_MATCH_DEVNAME:
> +		return strcmp(asd_x->match.device_name,
> +			      asd_y->match.device_name) == 0;
> +	case V4L2_ASYNC_MATCH_I2C:
> +		return asd_x->match.i2c.adapter_id ==
> +			asd_y->match.i2c.adapter_id &&
> +			asd_x->match.i2c.address ==
> +			asd_y->match.i2c.address;
> +	case V4L2_ASYNC_MATCH_FWNODE:
> +		return asd_x->match.fwnode == asd_y->match.fwnode;
> +	default:
> +		break;
> +	}
> +
> +	return false;
> +}
> +
>  /* Find the sub-device notifier registered by a sub-device driver. */
>  static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
>  	struct v4l2_subdev *sd)
> @@ -308,29 +333,22 @@ static void v4l2_async_notifier_unbind_all_subdevs(
>  	notifier->parent = NULL;
>  }
>  
> -/* See if an fwnode can be found in a notifier's lists. */
> -static bool __v4l2_async_notifier_fwnode_has_async_subdev(
> -	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode)
> +/* See if an async sub-device can be found in a notifier's lists. */
> +static bool __v4l2_async_notifier_has_async_subdev(
> +	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd)

This is a minor issue, but checkpatch complains (with reason)
(with --strict) about the above:

	CHECK: Lines should not end with a '('
	#63: FILE: drivers/media/v4l2-core/v4l2-async.c:337:
	+static bool __v4l2_async_notifier_has_async_subdev(

Better to declare it, instead, as:

static bool 
__v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
				       struct v4l2_async_subdev *asd)

Similar warnings appear on other places:
CHECK: Lines should not end with a '('
#102: FILE: drivers/media/v4l2-core/v4l2-async.c:362:
+static bool v4l2_async_notifier_has_async_subdev(

CHECK: Lines should not end with a '('
#141: FILE: drivers/media/v4l2-core/v4l2-async.c:410:
+			if (v4l2_async_notifier_has_async_subdev(

Btw, Checkpatch also complains that the author's email is different
than the SOB's one:

WARNING: Missing Signed-off-by: line by nominal patch author 'Steve Longerbeam <slongerbeam@gmail.com>'

(the some comes with Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>)

I suspect that other patches on this series will suffer from the same issue.


>  {
> -	struct v4l2_async_subdev *asd;
> +	struct v4l2_async_subdev *asd_y;
>  	struct v4l2_subdev *sd;
>  
> -	list_for_each_entry(asd, &notifier->waiting, list) {
> -		if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
> -			continue;
> -
> -		if (asd->match.fwnode == fwnode)
> +	list_for_each_entry(asd_y, &notifier->waiting, list)
> +		if (asd_equal(asd, asd_y))
>  			return true;
> -	}
>  
>  	list_for_each_entry(sd, &notifier->done, async_list) {
>  		if (WARN_ON(!sd->asd))
>  			continue;
>  
> -		if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE)
> -			continue;
> -
> -		if (sd->asd->match.fwnode == fwnode)
> +		if (asd_equal(asd, sd->asd))
>  			return true;
>  	}
>  
> @@ -338,32 +356,28 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
>  }
>  
>  /*
> - * Find out whether an async sub-device was set up for an fwnode already or
> + * Find out whether an async sub-device was set up already or
>   * whether it exists in a given notifier before @this_index.
>   */
> -static bool v4l2_async_notifier_fwnode_has_async_subdev(
> -	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode,
> +static bool v4l2_async_notifier_has_async_subdev(
> +	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd,
>  	unsigned int this_index)
>  {
>  	unsigned int j;
>  
>  	lockdep_assert_held(&list_lock);
>  
> -	/* Check that an fwnode is not being added more than once. */
> +	/* Check that an asd is not being added more than once. */
>  	for (j = 0; j < this_index; j++) {
> -		struct v4l2_async_subdev *asd = notifier->subdevs[this_index];
> -		struct v4l2_async_subdev *other_asd = notifier->subdevs[j];
> +		struct v4l2_async_subdev *asd_y = notifier->subdevs[j];
>  
> -		if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE &&
> -		    asd->match.fwnode ==
> -		    other_asd->match.fwnode)
> +		if (asd_equal(asd, asd_y))
>  			return true;
>  	}
>  
> -	/* Check than an fwnode did not exist in other notifiers. */
> +	/* Check that an asd does not exist in other notifiers. */
>  	list_for_each_entry(notifier, &notifier_list, list)
> -		if (__v4l2_async_notifier_fwnode_has_async_subdev(
> -			    notifier, fwnode))
> +		if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
>  			return true;
>  
>  	return false;
> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>  		case V4L2_ASYNC_MATCH_CUSTOM:
>  		case V4L2_ASYNC_MATCH_DEVNAME:
>  		case V4L2_ASYNC_MATCH_I2C:
> -			break;
>  		case V4L2_ASYNC_MATCH_FWNODE:
> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
> -				    notifier, asd->match.fwnode, i)) {
> +			if (v4l2_async_notifier_has_async_subdev(
> +				    notifier, asd, i)) {
>  				dev_err(dev,
> -					"fwnode has already been registered or in notifier's subdev list\n");
> +					"asd has already been registered or in notifier's subdev list\n");

Please, never use "asd" on messages printed to the user. While someone
may understand it while reading the source code, for a poor use,
"asd" is just a random sequence of 3 characters.

>  				ret = -EEXIST;
>  				goto err_unlock;
>  			}



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-24 17:06   ` Mauro Carvalho Chehab
@ 2018-09-25 21:04     ` Steve Longerbeam
  2018-09-25 22:20       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-09-25 21:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Steve Longerbeam
  Cc: linux-media, Mauro Carvalho Chehab, Sakari Ailus,
	Niklas Söderlund, Hans Verkuil, Sebastian Reichel,
	open list

Hi Mauro,


On 09/24/2018 10:06 AM, Mauro Carvalho Chehab wrote:
> Em Mon,  9 Jul 2018 15:39:02 -0700
> Steve Longerbeam <slongerbeam@gmail.com> escreveu:
>
>> Generalize v4l2_async_notifier_fwnode_has_async_subdev() to allow
>> searching for any type of async subdev, not just fwnodes. Rename to
>> v4l2_async_notifier_has_async_subdev() and pass it an asd pointer.
>>
>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>> ---
>> Changes since v5:
>> - none
>> Changes since v4:
>> - none
>> Changes since v3:
>> - removed TODO to support asd compare with CUSTOM match type in
>>    asd_equal().
>> Changes since v2:
>> - code optimization in asd_equal(), and remove unneeded braces,
>>    suggested by Sakari Ailus.
>> Changes since v1:
>> - none
>> ---
>>   drivers/media/v4l2-core/v4l2-async.c | 73 +++++++++++++++++++++---------------
>>   1 file changed, 43 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
>> index 2b08d03..0e7e529 100644
>> --- a/drivers/media/v4l2-core/v4l2-async.c
>> +++ b/drivers/media/v4l2-core/v4l2-async.c
>> @@ -124,6 +124,31 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
>>   	return NULL;
>>   }
>>   
>> +/* Compare two asd's for equivalence */
> Please, on comments, instead of "asd" prefer to use what this 3 random
> letters mean, e. g.:
> 	asd -> asynchronous subdevice

Ok, I will change the comment to read:

/* Compare two async subdevice descriptors for equivalence */

>
>> +static bool asd_equal(struct v4l2_async_subdev *asd_x,
>> +		      struct v4l2_async_subdev *asd_y)
>> +{
>> +	if (asd_x->match_type != asd_y->match_type)
>> +		return false;
>> +
>> +	switch (asd_x->match_type) {
>> +	case V4L2_ASYNC_MATCH_DEVNAME:
>> +		return strcmp(asd_x->match.device_name,
>> +			      asd_y->match.device_name) == 0;
>> +	case V4L2_ASYNC_MATCH_I2C:
>> +		return asd_x->match.i2c.adapter_id ==
>> +			asd_y->match.i2c.adapter_id &&
>> +			asd_x->match.i2c.address ==
>> +			asd_y->match.i2c.address;
>> +	case V4L2_ASYNC_MATCH_FWNODE:
>> +		return asd_x->match.fwnode == asd_y->match.fwnode;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>>   /* Find the sub-device notifier registered by a sub-device driver. */
>>   static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
>>   	struct v4l2_subdev *sd)
>> @@ -308,29 +333,22 @@ static void v4l2_async_notifier_unbind_all_subdevs(
>>   	notifier->parent = NULL;
>>   }
>>   
>> -/* See if an fwnode can be found in a notifier's lists. */
>> -static bool __v4l2_async_notifier_fwnode_has_async_subdev(
>> -	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode)
>> +/* See if an async sub-device can be found in a notifier's lists. */
>> +static bool __v4l2_async_notifier_has_async_subdev(
>> +	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd)
> This is a minor issue, but checkpatch complains (with reason)
> (with --strict) about the above:
>
> 	CHECK: Lines should not end with a '('
> 	#63: FILE: drivers/media/v4l2-core/v4l2-async.c:337:
> 	+static bool __v4l2_async_notifier_has_async_subdev(
>
> Better to declare it, instead, as:
>
> static bool
> __v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
> 				       struct v4l2_async_subdev *asd)
>
> Similar warnings appear on other places:
> CHECK: Lines should not end with a '('
> #102: FILE: drivers/media/v4l2-core/v4l2-async.c:362:
> +static bool v4l2_async_notifier_has_async_subdev(
>
> CHECK: Lines should not end with a '('
> #141: FILE: drivers/media/v4l2-core/v4l2-async.c:410:
> +			if (v4l2_async_notifier_has_async_subdev(

Will fix.

>
> Btw, Checkpatch also complains that the author's email is different
> than the SOB's one:
>
> WARNING: Missing Signed-off-by: line by nominal patch author 'Steve Longerbeam <slongerbeam@gmail.com>'
>
> (the some comes with Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>)
>
> I suspect that other patches on this series will suffer from the same issue.

Will fix when submitting v7.

> <snip>
>
>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>>   		case V4L2_ASYNC_MATCH_CUSTOM:
>>   		case V4L2_ASYNC_MATCH_DEVNAME:
>>   		case V4L2_ASYNC_MATCH_I2C:
>> -			break;
>>   		case V4L2_ASYNC_MATCH_FWNODE:
>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
>> -				    notifier, asd->match.fwnode, i)) {
>> +			if (v4l2_async_notifier_has_async_subdev(
>> +				    notifier, asd, i)) {
>>   				dev_err(dev,
>> -					"fwnode has already been registered or in notifier's subdev list\n");
>> +					"asd has already been registered or in notifier's subdev list\n");
> Please, never use "asd" on messages printed to the user. While someone
> may understand it while reading the source code, for a poor use,
> "asd" is just a random sequence of 3 characters.

I will change the message to read:

"subdev descriptor already listed in this or other notifiers".


Steve


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-25 21:04     ` Steve Longerbeam
@ 2018-09-25 22:20       ` Mauro Carvalho Chehab
  2018-09-26  1:05         ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: Mauro Carvalho Chehab @ 2018-09-25 22:20 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Steve Longerbeam, linux-media, Mauro Carvalho Chehab,
	Sakari Ailus, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list

Em Tue, 25 Sep 2018 14:04:21 -0700
Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:

> Hi Mauro,
> 
> 
> On 09/24/2018 10:06 AM, Mauro Carvalho Chehab wrote:
> > Em Mon,  9 Jul 2018 15:39:02 -0700
> > Steve Longerbeam <slongerbeam@gmail.com> escreveu:
> >  
> >> Generalize v4l2_async_notifier_fwnode_has_async_subdev() to allow
> >> searching for any type of async subdev, not just fwnodes. Rename to
> >> v4l2_async_notifier_has_async_subdev() and pass it an asd pointer.
> >>
> >> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> >> ---
> >> Changes since v5:
> >> - none
> >> Changes since v4:
> >> - none
> >> Changes since v3:
> >> - removed TODO to support asd compare with CUSTOM match type in
> >>    asd_equal().
> >> Changes since v2:
> >> - code optimization in asd_equal(), and remove unneeded braces,
> >>    suggested by Sakari Ailus.
> >> Changes since v1:
> >> - none
> >> ---
> >>   drivers/media/v4l2-core/v4l2-async.c | 73 +++++++++++++++++++++---------------
> >>   1 file changed, 43 insertions(+), 30 deletions(-)
> >>
> >> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> >> index 2b08d03..0e7e529 100644
> >> --- a/drivers/media/v4l2-core/v4l2-async.c
> >> +++ b/drivers/media/v4l2-core/v4l2-async.c
> >> @@ -124,6 +124,31 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
> >>   	return NULL;
> >>   }
> >>   
> >> +/* Compare two asd's for equivalence */  
> > Please, on comments, instead of "asd" prefer to use what this 3 random
> > letters mean, e. g.:
> > 	asd -> asynchronous subdevice  
> 
> Ok, I will change the comment to read:
> 
> /* Compare two async subdevice descriptors for equivalence */

OK

> 
> >  
> >> +static bool asd_equal(struct v4l2_async_subdev *asd_x,
> >> +		      struct v4l2_async_subdev *asd_y)
> >> +{
> >> +	if (asd_x->match_type != asd_y->match_type)
> >> +		return false;
> >> +
> >> +	switch (asd_x->match_type) {
> >> +	case V4L2_ASYNC_MATCH_DEVNAME:
> >> +		return strcmp(asd_x->match.device_name,
> >> +			      asd_y->match.device_name) == 0;
> >> +	case V4L2_ASYNC_MATCH_I2C:
> >> +		return asd_x->match.i2c.adapter_id ==
> >> +			asd_y->match.i2c.adapter_id &&
> >> +			asd_x->match.i2c.address ==
> >> +			asd_y->match.i2c.address;
> >> +	case V4L2_ASYNC_MATCH_FWNODE:
> >> +		return asd_x->match.fwnode == asd_y->match.fwnode;
> >> +	default:
> >> +		break;
> >> +	}
> >> +
> >> +	return false;
> >> +}
> >> +
> >>   /* Find the sub-device notifier registered by a sub-device driver. */
> >>   static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
> >>   	struct v4l2_subdev *sd)
> >> @@ -308,29 +333,22 @@ static void v4l2_async_notifier_unbind_all_subdevs(
> >>   	notifier->parent = NULL;
> >>   }
> >>   
> >> -/* See if an fwnode can be found in a notifier's lists. */
> >> -static bool __v4l2_async_notifier_fwnode_has_async_subdev(
> >> -	struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode)
> >> +/* See if an async sub-device can be found in a notifier's lists. */
> >> +static bool __v4l2_async_notifier_has_async_subdev(
> >> +	struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd)  
> > This is a minor issue, but checkpatch complains (with reason)
> > (with --strict) about the above:
> >
> > 	CHECK: Lines should not end with a '('
> > 	#63: FILE: drivers/media/v4l2-core/v4l2-async.c:337:
> > 	+static bool __v4l2_async_notifier_has_async_subdev(
> >
> > Better to declare it, instead, as:
> >
> > static bool
> > __v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier,
> > 				       struct v4l2_async_subdev *asd)
> >
> > Similar warnings appear on other places:
> > CHECK: Lines should not end with a '('
> > #102: FILE: drivers/media/v4l2-core/v4l2-async.c:362:
> > +static bool v4l2_async_notifier_has_async_subdev(
> >
> > CHECK: Lines should not end with a '('
> > #141: FILE: drivers/media/v4l2-core/v4l2-async.c:410:
> > +			if (v4l2_async_notifier_has_async_subdev(  
> 
> Will fix.
> 
> >
> > Btw, Checkpatch also complains that the author's email is different
> > than the SOB's one:
> >
> > WARNING: Missing Signed-off-by: line by nominal patch author 'Steve Longerbeam <slongerbeam@gmail.com>'
> >
> > (the some comes with Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>)
> >
> > I suspect that other patches on this series will suffer from the same issue.  
> 
> Will fix when submitting v7.
> 
> > <snip>
> >  
> >> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> >>   		case V4L2_ASYNC_MATCH_CUSTOM:
> >>   		case V4L2_ASYNC_MATCH_DEVNAME:
> >>   		case V4L2_ASYNC_MATCH_I2C:
> >> -			break;
> >>   		case V4L2_ASYNC_MATCH_FWNODE:
> >> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
> >> -				    notifier, asd->match.fwnode, i)) {
> >> +			if (v4l2_async_notifier_has_async_subdev(
> >> +				    notifier, asd, i)) {
> >>   				dev_err(dev,
> >> -					"fwnode has already been registered or in notifier's subdev list\n");
> >> +					"asd has already been registered or in notifier's subdev list\n");  
> > Please, never use "asd" on messages printed to the user. While someone
> > may understand it while reading the source code, for a poor use,
> > "asd" is just a random sequence of 3 characters.  
> 
> I will change the message to read:
> 
> "subdev descriptor already listed in this or other notifiers".

Perfect!

Thanks!
Mauro

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-25 22:20       ` Mauro Carvalho Chehab
@ 2018-09-26  1:05         ` Steve Longerbeam
  2018-09-26  9:33           ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-09-26  1:05 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Steve Longerbeam, linux-media, Mauro Carvalho Chehab,
	Sakari Ailus, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list



On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
> Em Tue, 25 Sep 2018 14:04:21 -0700
> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
>
>>>   
>>>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>>>>    		case V4L2_ASYNC_MATCH_CUSTOM:
>>>>    		case V4L2_ASYNC_MATCH_DEVNAME:
>>>>    		case V4L2_ASYNC_MATCH_I2C:
>>>> -			break;
>>>>    		case V4L2_ASYNC_MATCH_FWNODE:
>>>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
>>>> -				    notifier, asd->match.fwnode, i)) {
>>>> +			if (v4l2_async_notifier_has_async_subdev(
>>>> +				    notifier, asd, i)) {
>>>>    				dev_err(dev,
>>>> -					"fwnode has already been registered or in notifier's subdev list\n");
>>>> +					"asd has already been registered or in notifier's subdev list\n");
>>> Please, never use "asd" on messages printed to the user. While someone
>>> may understand it while reading the source code, for a poor use,
>>> "asd" is just a random sequence of 3 characters.
>> I will change the message to read:
>>
>> "subdev descriptor already listed in this or other notifiers".
> Perfect!

But the error message is removed in the subsequent patch
"[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".

I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
this shouldn't be a dev_err() anymore since it is up to the media platform
to decide whether an already existing subdev descriptor is an error.

Steve



^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-26  1:05         ` Steve Longerbeam
@ 2018-09-26  9:33           ` Mauro Carvalho Chehab
  2018-09-26 10:40             ` Sakari Ailus
  0 siblings, 1 reply; 36+ messages in thread
From: Mauro Carvalho Chehab @ 2018-09-26  9:33 UTC (permalink / raw)
  To: Steve Longerbeam, Sakari Ailus
  Cc: Steve Longerbeam, linux-media, Mauro Carvalho Chehab,
	Niklas Söderlund, Hans Verkuil, Sebastian Reichel,
	open list

Em Tue, 25 Sep 2018 18:05:36 -0700
Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:

> On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
> > Em Tue, 25 Sep 2018 14:04:21 -0700
> > Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
> >  
> >>>     
> >>>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> >>>>    		case V4L2_ASYNC_MATCH_CUSTOM:
> >>>>    		case V4L2_ASYNC_MATCH_DEVNAME:
> >>>>    		case V4L2_ASYNC_MATCH_I2C:
> >>>> -			break;
> >>>>    		case V4L2_ASYNC_MATCH_FWNODE:
> >>>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
> >>>> -				    notifier, asd->match.fwnode, i)) {
> >>>> +			if (v4l2_async_notifier_has_async_subdev(
> >>>> +				    notifier, asd, i)) {
> >>>>    				dev_err(dev,
> >>>> -					"fwnode has already been registered or in notifier's subdev list\n");
> >>>> +					"asd has already been registered or in notifier's subdev list\n");  
> >>> Please, never use "asd" on messages printed to the user. While someone
> >>> may understand it while reading the source code, for a poor use,
> >>> "asd" is just a random sequence of 3 characters.  
> >> I will change the message to read:
> >>
> >> "subdev descriptor already listed in this or other notifiers".  
> > Perfect!  
> 
> But the error message is removed in the subsequent patch
> "[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".
> 
> I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
> this shouldn't be a dev_err() anymore since it is up to the media platform
> to decide whether an already existing subdev descriptor is an error.

Hmm... that's an interesting discussion... what cases do you think it
would be fine to try to register twice an asd notifier?

Haven't write myself any piece of code using async framework, on a first
glance, trying to register twice sounds like an error to me.

Sakari, what do you think?

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-26  9:33           ` Mauro Carvalho Chehab
@ 2018-09-26 10:40             ` Sakari Ailus
  2018-09-26 17:49               ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: Sakari Ailus @ 2018-09-26 10:40 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Steve Longerbeam, Steve Longerbeam, linux-media,
	Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list

Hi Mauro, Steve,

On Wed, Sep 26, 2018 at 06:33:35AM -0300, Mauro Carvalho Chehab wrote:
> Em Tue, 25 Sep 2018 18:05:36 -0700
> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
> 
> > On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
> > > Em Tue, 25 Sep 2018 14:04:21 -0700
> > > Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
> > >  
> > >>>     
> > >>>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> > >>>>    		case V4L2_ASYNC_MATCH_CUSTOM:
> > >>>>    		case V4L2_ASYNC_MATCH_DEVNAME:
> > >>>>    		case V4L2_ASYNC_MATCH_I2C:
> > >>>> -			break;
> > >>>>    		case V4L2_ASYNC_MATCH_FWNODE:
> > >>>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
> > >>>> -				    notifier, asd->match.fwnode, i)) {
> > >>>> +			if (v4l2_async_notifier_has_async_subdev(
> > >>>> +				    notifier, asd, i)) {
> > >>>>    				dev_err(dev,
> > >>>> -					"fwnode has already been registered or in notifier's subdev list\n");
> > >>>> +					"asd has already been registered or in notifier's subdev list\n");  
> > >>> Please, never use "asd" on messages printed to the user. While someone
> > >>> may understand it while reading the source code, for a poor use,
> > >>> "asd" is just a random sequence of 3 characters.  
> > >> I will change the message to read:
> > >>
> > >> "subdev descriptor already listed in this or other notifiers".  
> > > Perfect!  
> > 
> > But the error message is removed in the subsequent patch
> > "[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".
> > 
> > I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
> > this shouldn't be a dev_err() anymore since it is up to the media platform
> > to decide whether an already existing subdev descriptor is an error.
> 
> Hmm... that's an interesting discussion... what cases do you think it
> would be fine to try to register twice an asd notifier?

Only the error message is removed; this case is still considered an error.
I think it'd be better to keep this error message; it helps debugging.

> 
> Haven't write myself any piece of code using async framework, on a first
> glance, trying to register twice sounds like an error to me.
> 
> Sakari, what do you think?

-- 
Regards,

Sakari Ailus
sakari.ailus@linux.intel.com

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-26 10:40             ` Sakari Ailus
@ 2018-09-26 17:49               ` Steve Longerbeam
  2018-09-28 12:16                 ` Sakari Ailus
  0 siblings, 1 reply; 36+ messages in thread
From: Steve Longerbeam @ 2018-09-26 17:49 UTC (permalink / raw)
  To: Sakari Ailus, Mauro Carvalho Chehab
  Cc: Steve Longerbeam, linux-media, Mauro Carvalho Chehab,
	Niklas Söderlund, Hans Verkuil, Sebastian Reichel,
	open list

Hi Mauro, Sakari,


On 09/26/2018 03:40 AM, Sakari Ailus wrote:
> Hi Mauro, Steve,
>
> On Wed, Sep 26, 2018 at 06:33:35AM -0300, Mauro Carvalho Chehab wrote:
>> Em Tue, 25 Sep 2018 18:05:36 -0700
>> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
>>
>>> On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
>>>> Em Tue, 25 Sep 2018 14:04:21 -0700
>>>> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
>>>>   
>>>>>>      
>>>>>>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>>>>>>>     		case V4L2_ASYNC_MATCH_CUSTOM:
>>>>>>>     		case V4L2_ASYNC_MATCH_DEVNAME:
>>>>>>>     		case V4L2_ASYNC_MATCH_I2C:
>>>>>>> -			break;
>>>>>>>     		case V4L2_ASYNC_MATCH_FWNODE:
>>>>>>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
>>>>>>> -				    notifier, asd->match.fwnode, i)) {
>>>>>>> +			if (v4l2_async_notifier_has_async_subdev(
>>>>>>> +				    notifier, asd, i)) {
>>>>>>>     				dev_err(dev,
>>>>>>> -					"fwnode has already been registered or in notifier's subdev list\n");
>>>>>>> +					"asd has already been registered or in notifier's subdev list\n");
>>>>>> Please, never use "asd" on messages printed to the user. While someone
>>>>>> may understand it while reading the source code, for a poor use,
>>>>>> "asd" is just a random sequence of 3 characters.
>>>>> I will change the message to read:
>>>>>
>>>>> "subdev descriptor already listed in this or other notifiers".
>>>> Perfect!
>>> But the error message is removed in the subsequent patch
>>> "[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".
>>>
>>> I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
>>> this shouldn't be a dev_err() anymore since it is up to the media platform
>>> to decide whether an already existing subdev descriptor is an error.
>> Hmm... that's an interesting discussion... what cases do you think it
>> would be fine to try to register twice an asd notifier?

It should be a fairly common case that a sub-device has multiple fwnode
output ports. In that case it's possible multiple sub-devices downstream
from it will each encounter it when parsing the fwnode graph, and attempt
to add it to their notifiers asd_list multiple times. That isn't an 
error, any
attempt to add it after the first add should be ignored.

imx-media is an example, there is a CSI-2 transmitter with four fwnode
output ports for each CSI-2 virtual channel. Those channels each go to
one of four Camera Sensor Interface in the imx6 IPU. So each CSI will
encounter the CSI-2 transmitter when parsing its fwnode ports.


> Only the error message is removed; this case is still considered an error.
> I think it'd be better to keep this error message; it helps debugging.

Ok I will add it back, but it should be a dev_dbg().

Steve

>
>> Haven't write myself any piece of code using async framework, on a first
>> glance, trying to register twice sounds like an error to me.
>>
>> Sakari, what do you think?


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-26 17:49               ` Steve Longerbeam
@ 2018-09-28 12:16                 ` Sakari Ailus
  2018-09-29 17:40                   ` Steve Longerbeam
  0 siblings, 1 reply; 36+ messages in thread
From: Sakari Ailus @ 2018-09-28 12:16 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Sakari Ailus, Mauro Carvalho Chehab, Steve Longerbeam,
	linux-media, Mauro Carvalho Chehab, Niklas Söderlund,
	Hans Verkuil, Sebastian Reichel, open list

On Wed, Sep 26, 2018 at 10:49:18AM -0700, Steve Longerbeam wrote:
> Hi Mauro, Sakari,
> 
> 
> On 09/26/2018 03:40 AM, Sakari Ailus wrote:
> > Hi Mauro, Steve,
> > 
> > On Wed, Sep 26, 2018 at 06:33:35AM -0300, Mauro Carvalho Chehab wrote:
> > > Em Tue, 25 Sep 2018 18:05:36 -0700
> > > Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
> > > 
> > > > On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
> > > > > Em Tue, 25 Sep 2018 14:04:21 -0700
> > > > > Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
> > > > > > > > @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
> > > > > > > >     		case V4L2_ASYNC_MATCH_CUSTOM:
> > > > > > > >     		case V4L2_ASYNC_MATCH_DEVNAME:
> > > > > > > >     		case V4L2_ASYNC_MATCH_I2C:
> > > > > > > > -			break;
> > > > > > > >     		case V4L2_ASYNC_MATCH_FWNODE:
> > > > > > > > -			if (v4l2_async_notifier_fwnode_has_async_subdev(
> > > > > > > > -				    notifier, asd->match.fwnode, i)) {
> > > > > > > > +			if (v4l2_async_notifier_has_async_subdev(
> > > > > > > > +				    notifier, asd, i)) {
> > > > > > > >     				dev_err(dev,
> > > > > > > > -					"fwnode has already been registered or in notifier's subdev list\n");
> > > > > > > > +					"asd has already been registered or in notifier's subdev list\n");
> > > > > > > Please, never use "asd" on messages printed to the user. While someone
> > > > > > > may understand it while reading the source code, for a poor use,
> > > > > > > "asd" is just a random sequence of 3 characters.
> > > > > > I will change the message to read:
> > > > > > 
> > > > > > "subdev descriptor already listed in this or other notifiers".
> > > > > Perfect!
> > > > But the error message is removed in the subsequent patch
> > > > "[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".
> > > > 
> > > > I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
> > > > this shouldn't be a dev_err() anymore since it is up to the media platform
> > > > to decide whether an already existing subdev descriptor is an error.
> > > Hmm... that's an interesting discussion... what cases do you think it
> > > would be fine to try to register twice an asd notifier?
> 
> It should be a fairly common case that a sub-device has multiple fwnode
> output ports. In that case it's possible multiple sub-devices downstream
> from it will each encounter it when parsing the fwnode graph, and attempt
> to add it to their notifiers asd_list multiple times. That isn't an error,
> any
> attempt to add it after the first add should be ignored.
> 
> imx-media is an example, there is a CSI-2 transmitter with four fwnode
> output ports for each CSI-2 virtual channel. Those channels each go to
> one of four Camera Sensor Interface in the imx6 IPU. So each CSI will
> encounter the CSI-2 transmitter when parsing its fwnode ports.
> 
> 
> > Only the error message is removed; this case is still considered an error.
> > I think it'd be better to keep this error message; it helps debugging.
> 
> Ok I will add it back, but it should be a dev_dbg().

Fine for me.

Could you address especially the author vs. SoB line difference in the set,
and re-post to the list, please?

I've pushed the latest set including my fwnode patches (which you can
ignore) to my linuxtv.org tree v4l2-fwnode branch; feel free to use these
as the basis. I've fixed a few conflicts in there in rebasing on current
media tree master.

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type
  2018-09-28 12:16                 ` Sakari Ailus
@ 2018-09-29 17:40                   ` Steve Longerbeam
  0 siblings, 0 replies; 36+ messages in thread
From: Steve Longerbeam @ 2018-09-29 17:40 UTC (permalink / raw)
  To: Sakari Ailus, Steve Longerbeam
  Cc: Sakari Ailus, Mauro Carvalho Chehab, linux-media,
	Mauro Carvalho Chehab, Niklas Söderlund, Hans Verkuil,
	Sebastian Reichel, open list

Hi Sakari,


On 09/28/2018 05:16 AM, Sakari Ailus wrote:
> On Wed, Sep 26, 2018 at 10:49:18AM -0700, Steve Longerbeam wrote:
>> Hi Mauro, Sakari,
>>
>>
>> On 09/26/2018 03:40 AM, Sakari Ailus wrote:
>>> Hi Mauro, Steve,
>>>
>>> On Wed, Sep 26, 2018 at 06:33:35AM -0300, Mauro Carvalho Chehab wrote:
>>>> Em Tue, 25 Sep 2018 18:05:36 -0700
>>>> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
>>>>
>>>>> On 09/25/2018 03:20 PM, Mauro Carvalho Chehab wrote:
>>>>>> Em Tue, 25 Sep 2018 14:04:21 -0700
>>>>>> Steve Longerbeam <steve_longerbeam@mentor.com> escreveu:
>>>>>>>>> @@ -392,12 +406,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
>>>>>>>>>      		case V4L2_ASYNC_MATCH_CUSTOM:
>>>>>>>>>      		case V4L2_ASYNC_MATCH_DEVNAME:
>>>>>>>>>      		case V4L2_ASYNC_MATCH_I2C:
>>>>>>>>> -			break;
>>>>>>>>>      		case V4L2_ASYNC_MATCH_FWNODE:
>>>>>>>>> -			if (v4l2_async_notifier_fwnode_has_async_subdev(
>>>>>>>>> -				    notifier, asd->match.fwnode, i)) {
>>>>>>>>> +			if (v4l2_async_notifier_has_async_subdev(
>>>>>>>>> +				    notifier, asd, i)) {
>>>>>>>>>      				dev_err(dev,
>>>>>>>>> -					"fwnode has already been registered or in notifier's subdev list\n");
>>>>>>>>> +					"asd has already been registered or in notifier's subdev list\n");
>>>>>>>> Please, never use "asd" on messages printed to the user. While someone
>>>>>>>> may understand it while reading the source code, for a poor use,
>>>>>>>> "asd" is just a random sequence of 3 characters.
>>>>>>> I will change the message to read:
>>>>>>>
>>>>>>> "subdev descriptor already listed in this or other notifiers".
>>>>>> Perfect!
>>>>> But the error message is removed in the subsequent patch
>>>>> "[PATCH 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev".
>>>>>
>>>>> I could bring it back as a dev_dbg() in v4l2_async_notifier_asd_valid(), but
>>>>> this shouldn't be a dev_err() anymore since it is up to the media platform
>>>>> to decide whether an already existing subdev descriptor is an error.
>>>> Hmm... that's an interesting discussion... what cases do you think it
>>>> would be fine to try to register twice an asd notifier?
>> It should be a fairly common case that a sub-device has multiple fwnode
>> output ports. In that case it's possible multiple sub-devices downstream
>> from it will each encounter it when parsing the fwnode graph, and attempt
>> to add it to their notifiers asd_list multiple times. That isn't an error,
>> any
>> attempt to add it after the first add should be ignored.
>>
>> imx-media is an example, there is a CSI-2 transmitter with four fwnode
>> output ports for each CSI-2 virtual channel. Those channels each go to
>> one of four Camera Sensor Interface in the imx6 IPU. So each CSI will
>> encounter the CSI-2 transmitter when parsing its fwnode ports.
>>
>>
>>> Only the error message is removed; this case is still considered an error.
>>> I think it'd be better to keep this error message; it helps debugging.
>> Ok I will add it back, but it should be a dev_dbg().
> Fine for me.
>
> Could you address especially the author vs. SoB line difference in the set,
> and re-post to the list, please?

Will do!

>
> I've pushed the latest set including my fwnode patches (which you can
> ignore) to my linuxtv.org tree v4l2-fwnode branch; feel free to use these
> as the basis. I've fixed a few conflicts in there in rebasing on current
> media tree master.

Yes in drivers/media/platform/ti-vpe/cal.c, due to

58513d4849 (" media: platform: remove redundant null pointer check 
before of_node_put")

I fixed that conflict too, but in a different way that retains the above 
change.

Since my conflict fix is different from yours, I will push v7 against 
current
media tree master. Let me know if the fixup looks ok to you.

Steve


^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2018-09-29 17:40 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1531175957-1973-1-git-send-email-steve_longerbeam@mentor.com>
2018-07-09 22:39 ` [PATCH v6 01/17] media: v4l2-fwnode: ignore endpoints that have no remote port parent Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 02/17] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
2018-09-24 17:06   ` Mauro Carvalho Chehab
2018-09-25 21:04     ` Steve Longerbeam
2018-09-25 22:20       ` Mauro Carvalho Chehab
2018-09-26  1:05         ` Steve Longerbeam
2018-09-26  9:33           ` Mauro Carvalho Chehab
2018-09-26 10:40             ` Sakari Ailus
2018-09-26 17:49               ` Steve Longerbeam
2018-09-28 12:16                 ` Sakari Ailus
2018-09-29 17:40                   ` Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 03/17] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
2018-08-03 15:13   ` jacopo mondi
2018-08-04 16:39     ` Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 04/17] media: v4l2: async: Add convenience functions to allocate and add asd's Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 05/17] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 06/17] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
2018-09-13 10:37   ` jacopo mondi
2018-09-13 12:44     ` Sakari Ailus
2018-09-13 12:58       ` jacopo mondi
2018-09-14  0:57         ` Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 07/17] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 08/17] media: imx: csi: " Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 09/17] media: imx: mipi csi-2: " Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 10/17] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 11/17] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 12/17] media: staging/imx: Rename root notifier Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 13/17] media: staging/imx: Switch to v4l2_async_notifier_add_*_subdev Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 14/17] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 16/17] media: v4l2: async: Remove notifier subdevs array Steve Longerbeam
2018-07-23 12:35   ` Sakari Ailus
2018-07-23 16:44     ` Steve Longerbeam
2018-07-23 17:24       ` Sakari Ailus
2018-08-04 10:33       ` jacopo mondi
2018-08-04 17:20         ` Steve Longerbeam
2018-07-09 22:39 ` [PATCH v6 17/17] [media] v4l2-subdev.rst: Update doc regarding subdev descriptors Steve Longerbeam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).