All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] media: imx: Switch to subdev notifiers
@ 2018-02-22  1:39 Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error Steve Longerbeam
                   ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

This patchset converts the imx-media driver and its dependent
subdevs to use subdev notifiers.

There are a couple shortcomings in v4l2-core that prevented
subdev notifiers from working correctly in imx-media:

1. v4l2_async_notifier_fwnode_parse_endpoint() treats a fwnode
   endpoint that is not connected to a remote device as an error.
   But in the case of the video-mux subdev, this is not an error, it's
   ok if some of the muxes inputs have no connection. So the first
   patch is a small modification to allow the parse_endpoint callback
   to decide whether an unconnected endpoint is an error.

2. In the imx-media graph, multiple subdevs will encounter the same
   upstream subdev (such as the imx6-mipi-csi2 receiver), and so
   v4l2_async_notifier_parse_fwnode_endpoints() will add imx6-mipi-csi2
   multiple times. This is treated as an error by
   v4l2_async_notifier_register() later.

   To get around this problem, add an v4l2_async_notifier_add_subdev()
   which first verifies the provided asd does not already exist in the
   given notifier asd list or in other registered notifiers. If the asd
   exists, the function returns -EEXIST and it's up to the caller to
   decide if that is an error (in imx-media case it is never an error).

   Patches 2-4 deal with adding that support.

3. Patch 5 adds v4l2_async_register_fwnode_subdev(), which is a
   convenience function for parsing a subdev's fwnode port endpoints
   for connected remote subdevs, registering a subdev notifier, and
   then registering the sub-device itself.

The remaining patches update the subdev drivers to register a
subdev notifier with endpoint parsing, and the changes to imx-media
to support that.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>


Steve Longerbeam (13):
  media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is
    error
  media: v4l2: async: Allow searching for asd of any type
  media: v4l2: async: Add v4l2_async_notifier_add_subdev
  media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
  media: v4l2-fwnode: Add a convenience function for registering subdevs
    with notifiers
  media: platform: video-mux: Register a subdev notifier
  media: imx: csi: Register a subdev notifier
  media: imx: mipi csi-2: Register a subdev notifier
  media: staging/imx: of: Remove recursive graph walk
  media: staging/imx: Loop through all registered subdevs for media
    links
  media: staging/imx: Rename root notifier
  media: staging/imx: Switch to v4l2_async_notifier_add_subdev
  media: staging/imx: TODO: Remove one assumption about OF graph parsing

 drivers/media/pci/intel/ipu3/ipu3-cio2.c          |  13 +-
 drivers/media/platform/omap3isp/isp.c             |   3 +
 drivers/media/platform/rcar-vin/rcar-core.c       |   3 +
 drivers/media/platform/video-mux.c                |  35 ++-
 drivers/media/v4l2-core/v4l2-async.c              | 275 ++++++++++++++++------
 drivers/media/v4l2-core/v4l2-fwnode.c             | 230 ++++++++++--------
 drivers/staging/media/imx/TODO                    |  29 +--
 drivers/staging/media/imx/imx-media-csi.c         |  11 +-
 drivers/staging/media/imx/imx-media-dev.c         | 134 +++--------
 drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media-of.c          | 106 +--------
 drivers/staging/media/imx/imx-media.h             |   6 +-
 drivers/staging/media/imx/imx6-mipi-csi2.c        |  31 ++-
 include/media/v4l2-async.h                        |  24 +-
 include/media/v4l2-fwnode.h                       |  64 ++++-
 15 files changed, 546 insertions(+), 423 deletions(-)

-- 
2.7.4

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

* [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-23  9:29   ` Laurent Pinchart
  2018-02-22  1:39 ` [PATCH 02/13] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

For some subdevices, a fwnode endpoint that has no connection to a remote
endpoint may not be an error. Let the parse_endpoint callback make that
decision in v4l2_async_notifier_fwnode_parse_endpoint(). If the callback
indicates that is not an error, skip adding the asd to the notifier and
return 0.

For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
(omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
unavailable remote fwnodes to maintain the previous behavior.

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/media/pci/intel/ipu3/ipu3-cio2.c    | 3 +++
 drivers/media/platform/omap3isp/isp.c       | 3 +++
 drivers/media/platform/rcar-vin/rcar-core.c | 3 +++
 drivers/media/v4l2-core/v4l2-fwnode.c       | 4 ++--
 4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 6c4444b..2323151 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -1477,6 +1477,9 @@ static int cio2_fwnode_parse(struct device *dev,
 	struct sensor_async_subdev *s_asd =
 			container_of(asd, struct sensor_async_subdev, asd);
 
+	if (!fwnode_device_is_available(asd->match.fwnode))
+		return -EINVAL;
+
 	if (vep->bus_type != V4L2_MBUS_CSI2) {
 		dev_err(dev, "Only CSI2 bus type is currently supported\n");
 		return -EINVAL;
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 8eb000e..4a302f2 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2025,6 +2025,9 @@ static int isp_fwnode_parse(struct device *dev,
 	dev_dbg(dev, "parsing endpoint %pOF, interface %u\n",
 		to_of_node(vep->base.local_fwnode), vep->base.port);
 
+	if (!fwnode_device_is_available(asd->match.fwnode))
+		return -EINVAL;
+
 	switch (vep->base.port) {
 	case ISP_OF_PHY_PARALLEL:
 		buscfg->interface = ISP_INTERFACE_PARALLEL;
diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c
index f1fc797..51bb8f1 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -149,6 +149,9 @@ static int rvin_digital_parse_v4l2(struct device *dev,
 	struct rvin_graph_entity *rvge =
 		container_of(asd, struct rvin_graph_entity, asd);
 
+	if (!fwnode_device_is_available(asd->match.fwnode))
+		return -EINVAL;
+
 	if (vep->base.port || vep->base.id)
 		return -ENOTCONN;
 
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index d630640..446646b 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -361,7 +361,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 	asd->match.fwnode =
 		fwnode_graph_get_remote_port_parent(endpoint);
-	if (!asd->match.fwnode) {
+	if (!asd->match.fwnode && !parse_endpoint) {
 		dev_warn(dev, "bad remote port parent\n");
 		ret = -EINVAL;
 		goto out_err;
@@ -384,7 +384,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
 			 "driver could not parse port@%u/endpoint@%u (%d)\n",
 			 vep->base.port, vep->base.id, ret);
 	v4l2_fwnode_endpoint_free(vep);
-	if (ret < 0)
+	if (ret < 0 || !asd->match.fwnode)
 		goto out_err;
 
 	notifier->subdevs[notifier->num_subdevs] = asd;
-- 
2.7.4

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

* [PATCH 02/13] media: v4l2: async: Allow searching for asd of any type
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 03/13] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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.

TODO: support asd compare with CUSTOM match type in asd_equal().

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
---
 drivers/media/v4l2-core/v4l2-async.c | 86 +++++++++++++++++++++++-------------
 1 file changed, 56 insertions(+), 30 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 2b08d03..c083efa 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -124,6 +124,42 @@ 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)
+{
+	bool ret = false;
+
+	if (!asd_x || !asd_y)
+		return false;
+
+	switch (asd_x->match_type) {
+	case V4L2_ASYNC_MATCH_DEVNAME:
+		if (asd_y->match_type == V4L2_ASYNC_MATCH_DEVNAME)
+			ret = !strcmp(asd_x->match.device_name,
+				      asd_y->match.device_name);
+		break;
+	case V4L2_ASYNC_MATCH_I2C:
+		if (asd_y->match_type == V4L2_ASYNC_MATCH_I2C)
+			ret = (asd_x->match.i2c.adapter_id ==
+			       asd_y->match.i2c.adapter_id &&
+			       asd_x->match.i2c.address ==
+			       asd_y->match.i2c.address);
+		break;
+	case V4L2_ASYNC_MATCH_FWNODE:
+		if (asd_y->match_type == V4L2_ASYNC_MATCH_FWNODE)
+			ret = (asd_x->match.fwnode == asd_y->match.fwnode);
+		break;
+	case V4L2_ASYNC_MATCH_CUSTOM:
+		/* TODO */
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
 /* 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,18 +344,15 @@ 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;
 	}
 
@@ -327,10 +360,7 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev(
 		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,33 +368,30 @@ 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. */
-	list_for_each_entry(notifier, &notifier_list, list)
-		if (__v4l2_async_notifier_fwnode_has_async_subdev(
-			    notifier, fwnode))
+	/* Check that an asd does not exist in other notifiers. */
+	list_for_each_entry(notifier, &notifier_list, list) {
+		if (__v4l2_async_notifier_has_async_subdev(notifier, asd))
 			return true;
+	}
 
 	return false;
 }
@@ -392,12 +419,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] 27+ messages in thread

* [PATCH 03/13] media: v4l2: async: Add v4l2_async_notifier_add_subdev
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 02/13] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 04/13] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

v4l2_async_notifier_add_subdev() adds an asd to the notifier. It checks
that the asd's match_type is valid and 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 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.

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

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

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index c083efa..8896498 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -375,16 +375,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. */
@@ -396,10 +406,43 @@ 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;
+
+	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;
+}
+
+static void __v4l2_async_notifier_init(struct v4l2_async_notifier *notifier)
+{
+	lockdep_assert_held(&list_lock);
+
+	INIT_LIST_HEAD(&notifier->asd_list);
+	INIT_LIST_HEAD(&notifier->waiting);
+	INIT_LIST_HEAD(&notifier->done);
+	notifier->lists_initialized = true;
+}
+
+static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
+{
 	struct v4l2_async_subdev *asd;
 	int ret;
 	int i;
@@ -407,34 +450,40 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
 	if (notifier->num_subdevs > V4L2_MAX_SUBDEVS)
 		return -EINVAL;
 
-	INIT_LIST_HEAD(&notifier->waiting);
-	INIT_LIST_HEAD(&notifier->done);
-
 	mutex_lock(&list_lock);
 
-	for (i = 0; i < notifier->num_subdevs; i++) {
-		asd = notifier->subdevs[i];
+	if (!notifier->lists_initialized)
+		__v4l2_async_notifier_init(notifier);
 
-		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;
-				goto err_unlock;
-			}
-			break;
-		default:
-			dev_err(dev, "Invalid match type %u on %p\n",
-				asd->match_type, asd);
+	if (!list_empty(&notifier->asd_list)) {
+		/*
+		 * Caller must have either used v4l2_async_notifier_add_subdev
+		 * to add asd's to notifier->asd_list, or provided the
+		 * notifier->subdevs array, but not both.
+		 */
+		if (WARN_ON(notifier->subdevs)) {
 			ret = -EINVAL;
 			goto err_unlock;
 		}
-		list_add_tail(&asd->list, &notifier->waiting);
+
+		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);
+		}
+	} else 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_add_tail(&asd->list, &notifier->waiting);
+		}
 	}
 
 	ret = v4l2_async_notifier_try_all_subdevs(notifier);
@@ -524,36 +573,102 @@ 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 if (notifier->lists_initialized) {
+		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 = 0;
+
+	mutex_lock(&list_lock);
+
+	if (notifier->num_subdevs >= V4L2_MAX_SUBDEVS) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (!notifier->lists_initialized)
+		__v4l2_async_notifier_init(notifier);
+
+	/*
+	 * 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;
@@ -627,7 +742,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..fa05905 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,9 +130,11 @@ 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
+ * @lists_initialized: list_head's have been initialized
  */
 struct v4l2_async_notifier {
 	const struct v4l2_async_notifier_operations *ops;
@@ -139,12 +144,29 @@ 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;
+	bool lists_initialized;
 };
 
 /**
+ * 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 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.
+ */
+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
-- 
2.7.4

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

* [PATCH 04/13] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (2 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 03/13] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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.

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>
---
 drivers/media/pci/intel/ipu3/ipu3-cio2.c |  10 +--
 drivers/media/v4l2-core/v4l2-async.c     |   4 -
 drivers/media/v4l2-core/v4l2-fwnode.c    | 128 ++++++++-----------------------
 include/media/v4l2-async.h               |   2 -
 include/media/v4l2-fwnode.h              |  22 +++---
 5 files changed, 51 insertions(+), 115 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 2323151..903813a 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -1428,13 +1428,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++)
@@ -1456,7 +1456,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;
 		}
 	}
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 8896498..2dc2221 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -582,9 +582,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];
 
@@ -599,7 +596,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 if (notifier->lists_initialized) {
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 446646b..2fe2e14 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 || !asd->match.fwnode)
 		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,32 @@ 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 = 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++;
+
+		ret = v4l2_async_notifier_add_subdev(notifier, asd);
+		if (ret < 0) {
+			kfree(asd);
+
+			/* not an error if asd already exists */
+			if (ret == -EEXIST) {
+				fwnode_handle_put(args.fwnode);
+				continue;
+			}
+
+			goto error;
+		}
 	}
 
 	return 0;
@@ -831,31 +770,32 @@ static int v4l2_fwnode_reference_parse_int_props(
 	if (PTR_ERR(fwnode) != -ENOENT && PTR_ERR(fwnode) != -ENODATA)
 		return PTR_ERR(fwnode);
 
-	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 = 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++;
+
+		ret = v4l2_async_notifier_add_subdev(notifier, asd);
+		if (ret < 0) {
+			kfree(asd);
+
+			/* not an error if asd already exists */
+			if (ret == -EEXIST) {
+				fwnode_handle_put(fwnode);
+				continue;
+			}
+
+			goto error;
+		}
 	}
 
 	return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index fa05905..1cafa33 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
@@ -139,7 +138,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 c228ec1..9a4b3f8 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] 27+ messages in thread

* [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (3 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 04/13] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-23  6:47   ` kbuild test robot
  2018-02-22  1:39 ` [PATCH 06/13] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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>
---
 drivers/media/v4l2-core/v4l2-fwnode.c | 98 +++++++++++++++++++++++++++++++++++
 include/media/v4l2-fwnode.h           | 42 +++++++++++++++
 2 files changed, 140 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 2fe2e14..07b8817 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -880,6 +880,104 @@ 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;
+	unsigned int subdev_port;
+	bool is_port;
+	int ret;
+
+	if (WARN_ON(!dev))
+		return -ENODEV;
+
+	fwnode = dev_fwnode(dev);
+	if (!fwnode_device_is_available(fwnode))
+		return -ENODEV;
+
+	is_port = (is_of_node(fwnode) &&
+		   of_node_cmp(to_of_node(fwnode)->name, "port") == 0);
+
+	/*
+	 * If the sub-device is a port, only parse fwnode endpoints from
+	 * this sub-device's single port id.
+	 */
+	if (is_port) {
+		/* verify the caller did not provide a ports array */
+		if (ports)
+			return -EINVAL;
+
+		ret = fwnode_property_read_u32(fwnode, "reg", &subdev_port);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * the device given to the fwnode endpoint parsing
+		 * must be the port sub-device's parent.
+		 */
+		dev = get_device(sd->dev->parent);
+
+		if (WARN_ON(!dev))
+			return -ENODEV;
+
+		ports = &subdev_port;
+		num_ports = 1;
+	}
+
+	notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
+	if (!notifier)
+		return -ENOMEM;
+
+	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;
+
+	if (is_port)
+		put_device(dev);
+
+	return 0;
+
+out_unregister:
+	v4l2_async_notifier_unregister(notifier);
+out_cleanup:
+	if (is_port)
+		put_device(dev);
+	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 9a4b3f8..764bb70 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -360,4 +360,46 @@ 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 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
+ * async sub-devices. The sub-device is similarly unregistered by calling
+ * v4l2_async_unregister_subdev().
+ *
+ * This function will work as expected if the sub-device fwnode is
+ * itself a port. The endpoints of this single port are parsed using
+ * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), passing the
+ * parent of the sub-device as the port's owner. The caller must not
+ * provide a @ports array, since the sub-device owns only this port.
+ *
+ * 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] 27+ messages in thread

* [PATCH 06/13] media: platform: video-mux: Register a subdev notifier
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (4 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-23  4:55   ` kbuild test robot
  2018-02-22  1:39 ` [PATCH 07/13] media: imx: csi: " Steve Longerbeam
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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>
---
 drivers/media/platform/video-mux.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index ee89ad7..7996bd4 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
 struct video_mux {
@@ -193,6 +194,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_pads)
+{
+	unsigned int i, *ports;
+	int ret;
+
+	ports = kcalloc(num_pads - 1, sizeof(*ports), GFP_KERNEL);
+	if (!ports)
+		return -ENOMEM;
+	for (i = 0; i < num_pads - 1; i++)
+		ports[i] = i;
+
+	ret = v4l2_async_register_fwnode_subdev(
+		&vmux->subdev, sizeof(struct v4l2_async_subdev),
+		ports, num_pads - 1, 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;
@@ -258,7 +291,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);
 }
 
 static int video_mux_remove(struct platform_device *pdev)
-- 
2.7.4

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

* [PATCH 07/13] media: imx: csi: Register a subdev notifier
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (5 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 06/13] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 08/13] media: imx: mipi csi-2: " Steve Longerbeam
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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

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

diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index eb7be50..f9232fc 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1736,6 +1736,13 @@ 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_probe(struct platform_device *pdev)
 {
 	struct ipu_client_platformdata *pdata;
@@ -1798,7 +1805,9 @@ static int imx_csi_probe(struct platform_device *pdev)
 	priv->dev->of_node = pdata->of_node;
 	pinctrl = devm_pinctrl_get_select_default(priv->dev);
 
-	ret = v4l2_async_register_subdev(&priv->sd);
+	ret = v4l2_async_register_fwnode_subdev(
+		&priv->sd, sizeof(struct v4l2_async_subdev),
+		NULL, 0, imx_csi_parse_endpoint);
 	if (ret)
 		goto free;
 
-- 
2.7.4

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

* [PATCH 08/13] media: imx: mipi csi-2: Register a subdev notifier
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (6 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 07/13] media: imx: csi: " Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 09/13] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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 477d191..9a0c569 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -544,35 +544,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;
@@ -594,10 +593,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");
@@ -647,7 +642,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] 27+ messages in thread

* [PATCH 09/13] media: staging/imx: of: Remove recursive graph walk
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (7 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 08/13] media: imx: mipi csi-2: " Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 10/13] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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] 27+ messages in thread

* [PATCH 10/13] media: staging/imx: Loop through all registered subdevs for media links
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (8 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 09/13] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 11/13] media: staging/imx: Rename root notifier Steve Longerbeam
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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 289d775..4d00ed3 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] 27+ messages in thread

* [PATCH 11/13] media: staging/imx: Rename root notifier
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (9 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 10/13] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 12/13] media: staging/imx: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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 4d00ed3..dd4702a 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 2fd6dfd..44931fe 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -148,7 +148,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] 27+ messages in thread

* [PATCH 12/13] media: staging/imx: Switch to v4l2_async_notifier_add_subdev
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (10 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 11/13] media: staging/imx: Rename root notifier Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-02-22  1:39 ` [PATCH 13/13] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
  2018-03-09 12:57 ` [PATCH 00/13] media: imx: Switch to subdev notifiers Hans Verkuil
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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>
---
 drivers/staging/media/imx/imx-media-dev.c         | 110 ++++++----------------
 drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media.h             |   4 +-
 3 files changed, 32 insertions(+), 87 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index dd4702a..f67ec8e 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,28 +47,17 @@ 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;
+	int ret;
 
-	mutex_lock(&imxmd->mutex);
+	imxasd = kzalloc(sizeof(*imxasd), GFP_KERNEL);
+	if (!imxasd)
+		return -ENOMEM;
+
+	asd = &imxasd->asd;
 
 	if (pdev)
 		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;
-	}
-
-	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;
@@ -111,16 +67,19 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd,
 		imxasd->pdev = pdev;
 	}
 
-	list_add_tail(&imxasd->list, &imxmd->asd_list);
-
-	imxmd->notifier.num_subdevs++;
+	ret = v4l2_async_notifier_add_subdev(&imxmd->notifier, asd);
+	if (ret < 0) {
+		if (ret == -EEXIST)
+			dev_dbg(imxmd->md.dev, "%s: already added %s\n",
+				__func__, np ? np->name : devname);
+		kfree(imxasd);
+		return ret;
+	}
 
 	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 +442,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 +472,29 @@ 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);
 
 	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 (imxmd->notifier.num_subdevs == 0) {
 		ret = -ENODEV;
-		goto unreg_dev;
+		goto notifier_cleanup;
 	}
 
-	subdevs = devm_kzalloc(imxmd->md.dev, sizeof(*subdevs) * num_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 +508,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 +525,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 70833fe..9d3f32b 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 44931fe..5d6c074 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -117,12 +117,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 *
@@ -147,7 +146,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] 27+ messages in thread

* [PATCH 13/13] media: staging/imx: TODO: Remove one assumption about OF graph parsing
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (11 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 12/13] media: staging/imx: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
@ 2018-02-22  1:39 ` Steve Longerbeam
  2018-03-09 12:57 ` [PATCH 00/13] media: imx: Switch to subdev notifiers Hans Verkuil
  13 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-22  1:39 UTC (permalink / raw)
  To: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, Laurent Pinchart,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

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] 27+ messages in thread

* Re: [PATCH 06/13] media: platform: video-mux: Register a subdev notifier
  2018-02-22  1:39 ` [PATCH 06/13] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
@ 2018-02-23  4:55   ` kbuild test robot
  0 siblings, 0 replies; 27+ messages in thread
From: kbuild test robot @ 2018-02-23  4:55 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: kbuild-all, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	Laurent Pinchart, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, Philipp Zabel, linux-media, Steve Longerbeam

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

Hi Steve,

I love your patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on v4.16-rc2 next-20180222]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Steve-Longerbeam/media-imx-Switch-to-subdev-notifiers/20180223-120401
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-n0-201807 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   drivers/media//platform/video-mux.c: In function 'video_mux_async_register':
>> drivers/media//platform/video-mux.c:215:10: error: implicit declaration of function 'kcalloc'; did you mean 'd_alloc'? [-Werror=implicit-function-declaration]
     ports = kcalloc(num_pads - 1, sizeof(*ports), GFP_KERNEL);
             ^~~~~~~
             d_alloc
>> drivers/media//platform/video-mux.c:215:8: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     ports = kcalloc(num_pads - 1, sizeof(*ports), GFP_KERNEL);
           ^
>> drivers/media//platform/video-mux.c:225:2: error: implicit declaration of function 'kfree'; did you mean 'vfree'? [-Werror=implicit-function-declaration]
     kfree(ports);
     ^~~~~
     vfree
   cc1: some warnings being treated as errors

vim +215 drivers/media//platform/video-mux.c

   208	
   209	static int video_mux_async_register(struct video_mux *vmux,
   210					    unsigned int num_pads)
   211	{
   212		unsigned int i, *ports;
   213		int ret;
   214	
 > 215		ports = kcalloc(num_pads - 1, sizeof(*ports), GFP_KERNEL);
   216		if (!ports)
   217			return -ENOMEM;
   218		for (i = 0; i < num_pads - 1; i++)
   219			ports[i] = i;
   220	
   221		ret = v4l2_async_register_fwnode_subdev(
   222			&vmux->subdev, sizeof(struct v4l2_async_subdev),
   223			ports, num_pads - 1, video_mux_parse_endpoint);
   224	
 > 225		kfree(ports);
   226		return ret;
   227	}
   228	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31349 bytes --]

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

* Re: [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers
  2018-02-22  1:39 ` [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
@ 2018-02-23  6:47   ` kbuild test robot
  0 siblings, 0 replies; 27+ messages in thread
From: kbuild test robot @ 2018-02-23  6:47 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: kbuild-all, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	Laurent Pinchart, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, Philipp Zabel, linux-media, Steve Longerbeam

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

Hi Steve,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on v4.16-rc2 next-20180223]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Steve-Longerbeam/media-imx-Switch-to-subdev-notifiers/20180223-120401
base:   git://linuxtv.org/media_tree.git master
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sh 

All warnings (new ones prefixed by >>):

   In file included from drivers/media/platform/ti-vpe/cal.c:24:0:
>> include/media/v4l2-fwnode.h:399:9: warning: 'struct v4l2_subdev' declared inside parameter list will not be visible outside of this definition or declaration
     struct v4l2_subdev *sd, size_t asd_struct_size,
            ^~~~~~~~~~~
--
   In file included from drivers/media/platform/davinci/vpif_capture.c:25:0:
>> include/media/v4l2-fwnode.h:399:9: warning: 'struct v4l2_subdev' declared inside parameter list will not be visible outside of this definition or declaration
     struct v4l2_subdev *sd, size_t asd_struct_size,
            ^~~~~~~~~~~
   In file included from arch/sh/include/asm/string.h:3:0,
                    from include/linux/string.h:20,
                    from include/linux/bitmap.h:9,
                    from include/linux/nodemask.h:95,
                    from include/linux/mmzone.h:17,
                    from include/linux/gfp.h:6,
                    from include/linux/umh.h:4,
                    from include/linux/kmod.h:22,
                    from include/linux/module.h:13,
                    from drivers/media/platform/davinci/vpif_capture.c:19:
   drivers/media/platform/davinci/vpif_capture.c: In function 'vpif_s_dv_timings':
   arch/sh/include/asm/string_32.h:50:42: warning: array subscript is above array bounds [-Warray-bounds]
      : "0" (__dest), "1" (__src), "r" (__src+__n)
                                        ~~~~~^~~~

vim +399 include/media/v4l2-fwnode.h

   215	
   216	
   217	/**
   218	 * typedef parse_endpoint_func - Driver's callback function to be called on
   219	 *	each V4L2 fwnode endpoint.
   220	 *
   221	 * @dev: pointer to &struct device
   222	 * @vep: pointer to &struct v4l2_fwnode_endpoint
   223	 * @asd: pointer to &struct v4l2_async_subdev
   224	 *
   225	 * Return:
   226	 * * %0 on success
   227	 * * %-ENOTCONN if the endpoint is to be skipped but this
   228	 *   should not be considered as an error
   229	 * * %-EINVAL if the endpoint configuration is invalid
   230	 */
   231	typedef int (*parse_endpoint_func)(struct device *dev,
   232					  struct v4l2_fwnode_endpoint *vep,
   233					  struct v4l2_async_subdev *asd);
   234	
   235	
   236	/**
   237	 * v4l2_async_notifier_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a
   238	 *						device node
   239	 * @dev: the device the endpoints of which are to be parsed
   240	 * @notifier: notifier for @dev
   241	 * @asd_struct_size: size of the driver's async sub-device struct, including
   242	 *		     sizeof(struct v4l2_async_subdev). The &struct
   243	 *		     v4l2_async_subdev shall be the first member of
   244	 *		     the driver's async sub-device struct, i.e. both
   245	 *		     begin at the same memory address.
   246	 * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
   247	 *		    endpoint. Optional.
   248	 *
   249	 * Parse the fwnode endpoints of the @dev device and populate the async sub-
   250	 * devices list in the notifier. The @parse_endpoint callback function is
   251	 * called for each endpoint with the corresponding async sub-device pointer to
   252	 * let the caller initialize the driver-specific part of the async sub-device
   253	 * structure.
   254	 *
   255	 * The notifier memory shall be zeroed before this function is called on the
   256	 * notifier.
   257	 *
   258	 * This function may not be called on a registered notifier and may be called on
   259	 * a notifier only once.
   260	 *
   261	 * Do not allocate the notifier's subdevs array, or change the notifier's
   262	 * num_subdevs field. This is because this function uses
   263	 * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
   264	 * which is in-place-of the subdevs array which must remain unallocated
   265	 * and unused.
   266	 *
   267	 * The &struct v4l2_fwnode_endpoint passed to the callback function
   268	 * @parse_endpoint is released once the function is finished. If there is a need
   269	 * to retain that configuration, the user needs to allocate memory for it.
   270	 *
   271	 * Any notifier populated using this function must be released with a call to
   272	 * v4l2_async_notifier_cleanup() after it has been unregistered and the async
   273	 * sub-devices are no longer in use, even if the function returned an error.
   274	 *
   275	 * Return: %0 on success, including when no async sub-devices are found
   276	 *	   %-ENOMEM if memory allocation failed
   277	 *	   %-EINVAL if graph or endpoint parsing failed
   278	 *	   Other error codes as returned by @parse_endpoint
   279	 */
   280	int v4l2_async_notifier_parse_fwnode_endpoints(
   281		struct device *dev, struct v4l2_async_notifier *notifier,
   282		size_t asd_struct_size,
   283		parse_endpoint_func parse_endpoint);
   284	
   285	/**
   286	 * v4l2_async_notifier_parse_fwnode_endpoints_by_port - Parse V4L2 fwnode
   287	 *							endpoints of a port in a
   288	 *							device node
   289	 * @dev: the device the endpoints of which are to be parsed
   290	 * @notifier: notifier for @dev
   291	 * @asd_struct_size: size of the driver's async sub-device struct, including
   292	 *		     sizeof(struct v4l2_async_subdev). The &struct
   293	 *		     v4l2_async_subdev shall be the first member of
   294	 *		     the driver's async sub-device struct, i.e. both
   295	 *		     begin at the same memory address.
   296	 * @port: port number where endpoints are to be parsed
   297	 * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
   298	 *		    endpoint. Optional.
   299	 *
   300	 * This function is just like v4l2_async_notifier_parse_fwnode_endpoints() with
   301	 * the exception that it only parses endpoints in a given port. This is useful
   302	 * on devices that have both sinks and sources: the async sub-devices connected
   303	 * to sources have already been configured by another driver (on capture
   304	 * devices). In this case the driver must know which ports to parse.
   305	 *
   306	 * Parse the fwnode endpoints of the @dev device on a given @port and populate
   307	 * the async sub-devices list of the notifier. The @parse_endpoint callback
   308	 * function is called for each endpoint with the corresponding async sub-device
   309	 * pointer to let the caller initialize the driver-specific part of the async
   310	 * sub-device structure.
   311	 *
   312	 * The notifier memory shall be zeroed before this function is called on the
   313	 * notifier the first time.
   314	 *
   315	 * This function may not be called on a registered notifier and may be called on
   316	 * a notifier only once per port.
   317	 *
   318	 * Do not allocate the notifier's subdevs array, or change the notifier's
   319	 * num_subdevs field. This is because this function uses
   320	 * @v4l2_async_notifier_add_subdev to populate the notifier's asd_list,
   321	 * which is in-place-of the subdevs array which must remain unallocated
   322	 * and unused.
   323	 *
   324	 * The &struct v4l2_fwnode_endpoint passed to the callback function
   325	 * @parse_endpoint is released once the function is finished. If there is a need
   326	 * to retain that configuration, the user needs to allocate memory for it.
   327	 *
   328	 * Any notifier populated using this function must be released with a call to
   329	 * v4l2_async_notifier_cleanup() after it has been unregistered and the async
   330	 * sub-devices are no longer in use, even if the function returned an error.
   331	 *
   332	 * Return: %0 on success, including when no async sub-devices are found
   333	 *	   %-ENOMEM if memory allocation failed
   334	 *	   %-EINVAL if graph or endpoint parsing failed
   335	 *	   Other error codes as returned by @parse_endpoint
   336	 */
   337	int v4l2_async_notifier_parse_fwnode_endpoints_by_port(
   338		struct device *dev, struct v4l2_async_notifier *notifier,
   339		size_t asd_struct_size, unsigned int port,
   340		parse_endpoint_func parse_endpoint);
   341	
   342	/**
   343	 * v4l2_fwnode_reference_parse_sensor_common - parse common references on
   344	 *					       sensors for async sub-devices
   345	 * @dev: the device node the properties of which are parsed for references
   346	 * @notifier: the async notifier where the async subdevs will be added
   347	 *
   348	 * Parse common sensor properties for remote devices related to the
   349	 * sensor and set up async sub-devices for them.
   350	 *
   351	 * Any notifier populated using this function must be released with a call to
   352	 * v4l2_async_notifier_release() after it has been unregistered and the async
   353	 * sub-devices are no longer in use, even in the case the function returned an
   354	 * error.
   355	 *
   356	 * Return: 0 on success
   357	 *	   -ENOMEM if memory allocation failed
   358	 *	   -EINVAL if property parsing failed
   359	 */
   360	int v4l2_async_notifier_parse_fwnode_sensor_common(
   361		struct device *dev, struct v4l2_async_notifier *notifier);
   362	
   363	/**
   364	 * v4l2_async_register_fwnode_subdev - registers a sub-device to the
   365	 *					asynchronous sub-device framework
   366	 *					and parses fwnode endpoints
   367	 *
   368	 * @sd: pointer to struct &v4l2_subdev
   369	 * @asd_struct_size: size of the driver's async sub-device struct, including
   370	 *		     sizeof(struct v4l2_async_subdev). The &struct
   371	 *		     v4l2_async_subdev shall be the first member of
   372	 *		     the driver's async sub-device struct, i.e. both
   373	 *		     begin at the same memory address.
   374	 * @ports: array of port id's to parse for fwnode endpoints. If NULL, will
   375	 *	   parse all ports owned by the sub-device.
   376	 * @num_ports: number of ports in @ports array. Ignored if @ports is NULL.
   377	 * @parse_endpoint: Driver's callback function called on each V4L2 fwnode
   378	 *		    endpoint. Optional.
   379	 *
   380	 * This function is just like v4l2_async_register_subdev() with the exception
   381	 * that calling it will also parse the sub-device's firmware node endpoints
   382	 * using v4l2_async_notifier_parse_fwnode_endpoints() or
   383	 * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and registers the
   384	 * async sub-devices. The sub-device is similarly unregistered by calling
   385	 * v4l2_async_unregister_subdev().
   386	 *
   387	 * This function will work as expected if the sub-device fwnode is
   388	 * itself a port. The endpoints of this single port are parsed using
   389	 * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), passing the
   390	 * parent of the sub-device as the port's owner. The caller must not
   391	 * provide a @ports array, since the sub-device owns only this port.
   392	 *
   393	 * While registered, the subdev module is marked as in-use.
   394	 *
   395	 * An error is returned if the module is no longer loaded on any attempts
   396	 * to register it.
   397	 */
   398	int v4l2_async_register_fwnode_subdev(
 > 399		struct v4l2_subdev *sd, size_t asd_struct_size,
   400		unsigned int *ports, unsigned int num_ports,
   401		int (*parse_endpoint)(struct device *dev,
   402				      struct v4l2_fwnode_endpoint *vep,
   403				      struct v4l2_async_subdev *asd));
   404	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 48089 bytes --]

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-22  1:39 ` [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error Steve Longerbeam
@ 2018-02-23  9:29   ` Laurent Pinchart
  2018-02-23  9:56     ` Philipp Zabel
  0 siblings, 1 reply; 27+ messages in thread
From: Laurent Pinchart @ 2018-02-23  9:29 UTC (permalink / raw)
  To: Steve Longerbeam
  Cc: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, niklas.soderlund,
	Sebastian Reichel, Hans Verkuil, Philipp Zabel, linux-media,
	Steve Longerbeam

Hi Steve,

Thank you for the patch.

On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> For some subdevices, a fwnode endpoint that has no connection to a remote
> endpoint may not be an error. Let the parse_endpoint callback make that
> decision in v4l2_async_notifier_fwnode_parse_endpoint(). If the callback
> indicates that is not an error, skip adding the asd to the notifier and
> return 0.
> 
> For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> unavailable remote fwnodes to maintain the previous behavior.

I'm not sure this should be a per-driver decision.

Generally speaking, if an endpoint node has no remote-endpoint property, the 
endpoint node is not needed. I've always considered such an endpoint node as 
invalid. The OF graphs DT bindings are however not clear on this subject. I 
have either failed to notice when they got merged, or they slowly evolved over 
time to contain contradictory information. In any case, I think we should 
decide on whether such a situation is valid or not from an OF graph point of 
view, and then always reject or always accept and ignore those endpoints.

> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
>  drivers/media/pci/intel/ipu3/ipu3-cio2.c    | 3 +++
>  drivers/media/platform/omap3isp/isp.c       | 3 +++
>  drivers/media/platform/rcar-vin/rcar-core.c | 3 +++
>  drivers/media/v4l2-core/v4l2-fwnode.c       | 4 ++--
>  4 files changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 6c4444b..2323151 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> @@ -1477,6 +1477,9 @@ static int cio2_fwnode_parse(struct device *dev,
>  	struct sensor_async_subdev *s_asd =
>  			container_of(asd, struct sensor_async_subdev, asd);
> 
> +	if (!fwnode_device_is_available(asd->match.fwnode))
> +		return -EINVAL;
> +
>  	if (vep->bus_type != V4L2_MBUS_CSI2) {
>  		dev_err(dev, "Only CSI2 bus type is currently supported\n");
>  		return -EINVAL;
> diff --git a/drivers/media/platform/omap3isp/isp.c
> b/drivers/media/platform/omap3isp/isp.c index 8eb000e..4a302f2 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -2025,6 +2025,9 @@ static int isp_fwnode_parse(struct device *dev,
>  	dev_dbg(dev, "parsing endpoint %pOF, interface %u\n",
>  		to_of_node(vep->base.local_fwnode), vep->base.port);
> 
> +	if (!fwnode_device_is_available(asd->match.fwnode))
> +		return -EINVAL;
> +
>  	switch (vep->base.port) {
>  	case ISP_OF_PHY_PARALLEL:
>  		buscfg->interface = ISP_INTERFACE_PARALLEL;
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index f1fc797..51bb8f1 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -149,6 +149,9 @@ static int rvin_digital_parse_v4l2(struct device *dev,
>  	struct rvin_graph_entity *rvge =
>  		container_of(asd, struct rvin_graph_entity, asd);
> 
> +	if (!fwnode_device_is_available(asd->match.fwnode))
> +		return -EINVAL;
> +
>  	if (vep->base.port || vep->base.id)
>  		return -ENOTCONN;
> 
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c
> b/drivers/media/v4l2-core/v4l2-fwnode.c index d630640..446646b 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -361,7 +361,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
>  	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
>  	asd->match.fwnode =
>  		fwnode_graph_get_remote_port_parent(endpoint);
> -	if (!asd->match.fwnode) {
> +	if (!asd->match.fwnode && !parse_endpoint) {
>  		dev_warn(dev, "bad remote port parent\n");
>  		ret = -EINVAL;
>  		goto out_err;
> @@ -384,7 +384,7 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
>  			 "driver could not parse port@%u/endpoint@%u (%d)\n",
>  			 vep->base.port, vep->base.id, ret);
>  	v4l2_fwnode_endpoint_free(vep);
> -	if (ret < 0)
> +	if (ret < 0 || !asd->match.fwnode)
>  		goto out_err;
> 
>  	notifier->subdevs[notifier->num_subdevs] = asd;


-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23  9:29   ` Laurent Pinchart
@ 2018-02-23  9:56     ` Philipp Zabel
  2018-02-23 10:05       ` Laurent Pinchart
  0 siblings, 1 reply; 27+ messages in thread
From: Philipp Zabel @ 2018-02-23  9:56 UTC (permalink / raw)
  To: Laurent Pinchart, Steve Longerbeam
  Cc: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, niklas.soderlund,
	Sebastian Reichel, Hans Verkuil, linux-media, Steve Longerbeam

Hi Laurent,

On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> Hi Steve,
> 
> Thank you for the patch.
> 
> On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> > For some subdevices, a fwnode endpoint that has no connection to a remote
> > endpoint may not be an error. Let the parse_endpoint callback make that
> > decision in v4l2_async_notifier_fwnode_parse_endpoint(). If the callback
> > indicates that is not an error, skip adding the asd to the notifier and
> > return 0.
> > 
> > For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> > (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> > unavailable remote fwnodes to maintain the previous behavior.
> 
> I'm not sure this should be a per-driver decision.
> 
> Generally speaking, if an endpoint node has no remote-endpoint property, the 
> endpoint node is not needed. I've always considered such an endpoint node as 
> invalid. The OF graphs DT bindings are however not clear on this subject.

Documentation/devicetree/bindings/graph.txt says:

  Each endpoint should contain a 'remote-endpoint' phandle property
  that points to the corresponding endpoint in the port of the remote
  device.

("should", not "must"). Later, the remote-node property explicitly lists
the remote-endpoint property as optional.

> I have either failed to notice when they got merged, or they slowly evolved over 
> time to contain contradictory information. In any case, I think we should 
> decide on whether such a situation is valid or not from an OF graph point of 
> view, and then always reject or always accept and ignore those endpoints.

We are currently using this on i.MX6 to provide empty labeled endpoints
in the dtsi files for board DT writers to link to, both for the display
output and video capture ports.
See for example the endpoints with the labels ipu1_di0_disp0 and
ipu1_csi0_mux_from_parallel_sensor in arch/arm/boot/dts/imx6q.dtsi.

regards
Philipp

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23  9:56     ` Philipp Zabel
@ 2018-02-23 10:05       ` Laurent Pinchart
  2018-02-23 10:14         ` Sakari Ailus
  2018-02-23 11:16         ` Philipp Zabel
  0 siblings, 2 replies; 27+ messages in thread
From: Laurent Pinchart @ 2018-02-23 10:05 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Steve Longerbeam, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, linux-media,
	Steve Longerbeam

Hi Philipp,

On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> > On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> >> For some subdevices, a fwnode endpoint that has no connection to a
> >> remote endpoint may not be an error. Let the parse_endpoint callback
> > make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
> >> the callback indicates that is not an error, skip adding the asd to the
> >> notifier and return 0.
> >> 
> >> For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> >> (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> >> unavailable remote fwnodes to maintain the previous behavior.
> > 
> > I'm not sure this should be a per-driver decision.
> > 
> > Generally speaking, if an endpoint node has no remote-endpoint property,
> > the endpoint node is not needed. I've always considered such an endpoint
> > node as invalid. The OF graphs DT bindings are however not clear on this
> > subject.
> 
> Documentation/devicetree/bindings/graph.txt says:
> 
>   Each endpoint should contain a 'remote-endpoint' phandle property
>   that points to the corresponding endpoint in the port of the remote
>   device.
> 
> ("should", not "must").

The DT bindings documentation has historically used "should" to mean "must" in 
many places :-( That was a big mistake.

> Later, the remote-node property explicitly lists the remote-endpoint
> property as optional.

I've seen that too, and that's why I mentioned that the documentation isn't 
clear on the subject.

> > I have either failed to notice when they got merged, or they slowly
> > evolved over time to contain contradictory information. In any case, I
> > think we should decide on whether such a situation is valid or not from
> > an OF graph point of view, and then always reject or always accept and
> > ignore those endpoints.
> 
> We are currently using this on i.MX6 to provide empty labeled endpoints
> in the dtsi files for board DT writers to link to, both for the display
> output and video capture ports.
> See for example the endpoints with the labels ipu1_di0_disp0 and
> ipu1_csi0_mux_from_parallel_sensor in arch/arm/boot/dts/imx6q.dtsi.

This could also be achieved by adding the endpoints in the board DT files. See 
for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
salvator-x.dts. On the other hand, I also have empty endpoints in the 
display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.

I think we should first decide what we want to do going forward (allowing for 
empty endpoints or not), clarify the documentation, and then update the code. 
In any case I don't think it should be a per-device decision.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23 10:05       ` Laurent Pinchart
@ 2018-02-23 10:14         ` Sakari Ailus
  2018-02-23 11:16         ` Philipp Zabel
  1 sibling, 0 replies; 27+ messages in thread
From: Sakari Ailus @ 2018-02-23 10:14 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Philipp Zabel, Steve Longerbeam, Yong Zhi, Sakari Ailus,
	Mauro Carvalho Chehab, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, linux-media, Steve Longerbeam, devicetree

Hi guys,

On Fri, Feb 23, 2018 at 12:05:38PM +0200, Laurent Pinchart wrote:
> Hi Philipp,
> 
> On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> > On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> > > On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> > >> For some subdevices, a fwnode endpoint that has no connection to a
> > >> remote endpoint may not be an error. Let the parse_endpoint callback
> > > make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
> > >> the callback indicates that is not an error, skip adding the asd to the
> > >> notifier and return 0.
> > >> 
> > >> For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> > >> (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> > >> unavailable remote fwnodes to maintain the previous behavior.
> > > 
> > > I'm not sure this should be a per-driver decision.
> > > 
> > > Generally speaking, if an endpoint node has no remote-endpoint property,
> > > the endpoint node is not needed. I've always considered such an endpoint
> > > node as invalid. The OF graphs DT bindings are however not clear on this
> > > subject.
> > 
> > Documentation/devicetree/bindings/graph.txt says:
> > 
> >   Each endpoint should contain a 'remote-endpoint' phandle property
> >   that points to the corresponding endpoint in the port of the remote
> >   device.
> > 
> > ("should", not "must").
> 
> The DT bindings documentation has historically used "should" to mean "must" in 
> many places :-( That was a big mistake.

"Shall", not "must".

Indeed, there's hardly use for an endpoint without the remote-endpoint
property. My understanding is that such nodes might be best ignored, that's
been at least the practice in a lot of DT parsing code. There are arguments
both ways I guess.

What comes to this patch is that I'd rather not burden individual drivers
with such checks.

> 
> > Later, the remote-node property explicitly lists the remote-endpoint
> > property as optional.
> 
> I've seen that too, and that's why I mentioned that the documentation isn't 
> clear on the subject.
> 
> > > I have either failed to notice when they got merged, or they slowly
> > > evolved over time to contain contradictory information. In any case, I
> > > think we should decide on whether such a situation is valid or not from
> > > an OF graph point of view, and then always reject or always accept and
> > > ignore those endpoints.
> > 
> > We are currently using this on i.MX6 to provide empty labeled endpoints
> > in the dtsi files for board DT writers to link to, both for the display
> > output and video capture ports.
> > See for example the endpoints with the labels ipu1_di0_disp0 and
> > ipu1_csi0_mux_from_parallel_sensor in arch/arm/boot/dts/imx6q.dtsi.
> 
> This could also be achieved by adding the endpoints in the board DT files. See 
> for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
> r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
> salvator-x.dts. On the other hand, I also have empty endpoints in the 
> display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.
> 
> I think we should first decide what we want to do going forward (allowing for 
> empty endpoints or not), clarify the documentation, and then update the code. 
> In any case I don't think it should be a per-device decision.

I don't think they should be allowed in the documentation. The
implementation could still simply ignore them.

Cc the devicetree list.

-- 
Regards,

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

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23 10:05       ` Laurent Pinchart
  2018-02-23 10:14         ` Sakari Ailus
@ 2018-02-23 11:16         ` Philipp Zabel
  2018-02-23 12:47           ` Sakari Ailus
  2018-02-23 18:22           ` Steve Longerbeam
  1 sibling, 2 replies; 27+ messages in thread
From: Philipp Zabel @ 2018-02-23 11:16 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Steve Longerbeam, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, linux-media,
	Steve Longerbeam

Hi Laurent,

On Fri, 2018-02-23 at 12:05 +0200, Laurent Pinchart wrote:
> Hi Philipp,
> 
> On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> > On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> > > On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> > > > For some subdevices, a fwnode endpoint that has no connection to a
> > > > remote endpoint may not be an error. Let the parse_endpoint callback
> > > 
> > > make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
> > > > the callback indicates that is not an error, skip adding the asd to the
> > > > notifier and return 0.
> > > > 
> > > > For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> > > > (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> > > > unavailable remote fwnodes to maintain the previous behavior.
> > > 
> > > I'm not sure this should be a per-driver decision.
> > > 
> > > Generally speaking, if an endpoint node has no remote-endpoint property,
> > > the endpoint node is not needed. I've always considered such an endpoint
> > > node as invalid. The OF graphs DT bindings are however not clear on this
> > > subject.
> > 
> > Documentation/devicetree/bindings/graph.txt says:
> > 
> >   Each endpoint should contain a 'remote-endpoint' phandle property
> >   that points to the corresponding endpoint in the port of the remote
> >   device.
> > 
> > ("should", not "must").
> 
> The DT bindings documentation has historically used "should" to mean "must" in 
> many places :-( That was a big mistake.

Maybe I could have worded that better? The intention was to let "should"
be read as a strong suggestion, like "it is recommended", but not as a
requirement.

> > Later, the remote-node property explicitly lists the remote-endpoint
> > property as optional.
> 
> I've seen that too, and that's why I mentioned that the documentation isn't 
> clear on the subject.

Do you have a suggestion how to improve the documentation? I thought
listing the remote-endpoint property under a header called "Optional
endpoint properties" was pretty clear.

> This could also be achieved by adding the endpoints in the board DT files. See 
> for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
> r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
> salvator-x.dts. On the other hand, I also have empty endpoints in the 
> display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.

Right, that would be possible.

> I think we should first decide what we want to do going forward (allowing for 
> empty endpoints or not), clarify the documentation, and then update the code. 
> In any case I don't think it should be a per-device decision.

There are device trees in the wild that have those empty endpoints, so I
don't think retroactively declaring the remote-endpoint property
required is a good idea.

Is there any driver that currently benefits from throwing an error on
empty endpoints in any way? I'd prefer to just let the core ignore empty
endpoints for all drivers.

regards
Philipp

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23 11:16         ` Philipp Zabel
@ 2018-02-23 12:47           ` Sakari Ailus
  2018-02-27  9:13             ` Philipp Zabel
  2018-02-23 18:22           ` Steve Longerbeam
  1 sibling, 1 reply; 27+ messages in thread
From: Sakari Ailus @ 2018-02-23 12:47 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Laurent Pinchart, Steve Longerbeam, Yong Zhi,
	Mauro Carvalho Chehab, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, linux-media, Steve Longerbeam

Hi Philipp,

On Fri, Feb 23, 2018 at 12:16:17PM +0100, Philipp Zabel wrote:
> Hi Laurent,
> 
> On Fri, 2018-02-23 at 12:05 +0200, Laurent Pinchart wrote:
> > Hi Philipp,
> > 
> > On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> > > On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> > > > On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> > > > > For some subdevices, a fwnode endpoint that has no connection to a
> > > > > remote endpoint may not be an error. Let the parse_endpoint callback
> > > > 
> > > > make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
> > > > > the callback indicates that is not an error, skip adding the asd to the
> > > > > notifier and return 0.
> > > > > 
> > > > > For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> > > > > (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> > > > > unavailable remote fwnodes to maintain the previous behavior.
> > > > 
> > > > I'm not sure this should be a per-driver decision.
> > > > 
> > > > Generally speaking, if an endpoint node has no remote-endpoint property,
> > > > the endpoint node is not needed. I've always considered such an endpoint
> > > > node as invalid. The OF graphs DT bindings are however not clear on this
> > > > subject.
> > > 
> > > Documentation/devicetree/bindings/graph.txt says:
> > > 
> > >   Each endpoint should contain a 'remote-endpoint' phandle property
> > >   that points to the corresponding endpoint in the port of the remote
> > >   device.
> > > 
> > > ("should", not "must").
> > 
> > The DT bindings documentation has historically used "should" to mean "must" in 
> > many places :-( That was a big mistake.
> 
> Maybe I could have worded that better? The intention was to let "should"
> be read as a strong suggestion, like "it is recommended", but not as a
> requirement.

Is there a reason for have an endpoint without a remote-endpoint property?

The problem with should (in general when it is used when the intention is
"shall") is that it lets the developer to write broken DT source that is
still conforming to the spec.

I don't have a strong preference to change should to shall in this
particular case now but I would have used "shall" to begin with.

> 
> > > Later, the remote-node property explicitly lists the remote-endpoint
> > > property as optional.
> > 
> > I've seen that too, and that's why I mentioned that the documentation isn't 
> > clear on the subject.
> 
> Do you have a suggestion how to improve the documentation? I thought
> listing the remote-endpoint property under a header called "Optional
> endpoint properties" was pretty clear.
> 
> > This could also be achieved by adding the endpoints in the board DT files. See 
> > for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
> > r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
> > salvator-x.dts. On the other hand, I also have empty endpoints in the 
> > display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.
> 
> Right, that would be possible.
> 
> > I think we should first decide what we want to do going forward (allowing for 
> > empty endpoints or not), clarify the documentation, and then update the code. 
> > In any case I don't think it should be a per-device decision.
> 
> There are device trees in the wild that have those empty endpoints, so I
> don't think retroactively declaring the remote-endpoint property
> required is a good idea.

You could IMO, but the kernel (and existing drivers) would still need to
work with DT binaries without those bits. And leave comments in the code
why it's there.

> 
> Is there any driver that currently benefits from throwing an error on
> empty endpoints in any way? I'd prefer to just let the core ignore empty
> endpoints for all drivers.

Not necessarily, but it's overhead in parsing the DT as well as in the
DT source and in the DT binary.

-- 
Regards,

Sakari Ailus
sakari.ailus@linux.intel.com

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23 11:16         ` Philipp Zabel
  2018-02-23 12:47           ` Sakari Ailus
@ 2018-02-23 18:22           ` Steve Longerbeam
  1 sibling, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-02-23 18:22 UTC (permalink / raw)
  To: Philipp Zabel, Laurent Pinchart
  Cc: Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab, niklas.soderlund,
	Sebastian Reichel, Hans Verkuil, linux-media

Hi all,


On 02/23/2018 03:16 AM, Philipp Zabel wrote:
> Hi Laurent,
>
> On Fri, 2018-02-23 at 12:05 +0200, Laurent Pinchart wrote:
>> Hi Philipp,
>>
>> On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
>>> On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
>>>> On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
>>>>> For some subdevices, a fwnode endpoint that has no connection to a
>>>>> remote endpoint may not be an error. Let the parse_endpoint callback
>>>> make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
>>>>> the callback indicates that is not an error, skip adding the asd to the
>>>>> notifier and return 0.
>>>>>
>>>>> For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
>>>>> (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
>>>>> unavailable remote fwnodes to maintain the previous behavior.
>>>> I'm not sure this should be a per-driver decision.
>>>>
>>>> Generally speaking, if an endpoint node has no remote-endpoint property,
>>>> the endpoint node is not needed. I've always considered such an endpoint
>>>> node as invalid. The OF graphs DT bindings are however not clear on this
>>>> subject.
>>> Documentation/devicetree/bindings/graph.txt says:
>>>
>>>    Each endpoint should contain a 'remote-endpoint' phandle property
>>>    that points to the corresponding endpoint in the port of the remote
>>>    device.
>>>
>>> ("should", not "must").
>> The DT bindings documentation has historically used "should" to mean "must" in
>> many places :-( That was a big mistake.
> Maybe I could have worded that better? The intention was to let "should"
> be read as a strong suggestion, like "it is recommended", but not as a
> requirement.
>
>>> Later, the remote-node property explicitly lists the remote-endpoint
>>> property as optional.
>> I've seen that too, and that's why I mentioned that the documentation isn't
>> clear on the subject.
> Do you have a suggestion how to improve the documentation? I thought
> listing the remote-endpoint property under a header called "Optional
> endpoint properties" was pretty clear.
>
>> This could also be achieved by adding the endpoints in the board DT files. See
>> for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
>> r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
>> salvator-x.dts. On the other hand, I also have empty endpoints in the
>> display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.
> Right, that would be possible.

Yes, I think this is doable in the specific case of the video mux device.

For example on the i.MX6 SabreAuto reference boards, only the parallel
bus mux input is connected to a device (to adv7180). The MIPI CSI-2 mux
input is left unconnected.

So probably the right approach is to not define any endpoint nodes under the
unused mux input ports.

The video-mux driver will need to be modified to enumerate ports, instead of
endpoints, to determine its number of mux inputs.

I will start looking into this change for v2.

The trick would be to do this while still remaining compatible with old
DTB's in the wild with unconnected endpoints. Unfortunately that might
not be possible, unless we were to let v4l2-core ignore empty endpoints.


>
>> I think we should first decide what we want to do going forward (allowing for
>> empty endpoints or not), clarify the documentation, and then update the code.
>> In any case I don't think it should be a per-device decision.
> There are device trees in the wild that have those empty endpoints, so I
> don't think retroactively declaring the remote-endpoint property
> required is a good idea.
>
> Is there any driver that currently benefits from throwing an error on
> empty endpoints in any way? I'd prefer to just let the core ignore empty
> endpoints for all drivers.

I tend to agree that, given the fuzziness of the DT binding docs regarding
unconnected endpoints, v4l2-core should ignore them.

In v2 I can modify this patch to ignore empty endpoints without error and
continue with endpoint parsing rather than pass the empty endpoint to the
caller's parse_endpoint callback.

Or this patch can be dropped altogether. It won't be needed for i.MX6 after
making the change described above, but again if this patch is dropped it 
will
break b/w compatibility with old i.MX6 DTB's.


Steve

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-23 12:47           ` Sakari Ailus
@ 2018-02-27  9:13             ` Philipp Zabel
  2018-02-27  9:53               ` Laurent Pinchart
  0 siblings, 1 reply; 27+ messages in thread
From: Philipp Zabel @ 2018-02-27  9:13 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Laurent Pinchart, Steve Longerbeam, Yong Zhi,
	Mauro Carvalho Chehab, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, linux-media, Steve Longerbeam, devicetree

Hi Sakari,

On Fri, 2018-02-23 at 14:47 +0200, Sakari Ailus wrote:
> Hi Philipp,
> 
> On Fri, Feb 23, 2018 at 12:16:17PM +0100, Philipp Zabel wrote:
> > Hi Laurent,
> > 
> > On Fri, 2018-02-23 at 12:05 +0200, Laurent Pinchart wrote:
> > > Hi Philipp,
> > > 
> > > On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> > > > On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> > > > > On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> > > > > > For some subdevices, a fwnode endpoint that has no connection to a
> > > > > > remote endpoint may not be an error. Let the parse_endpoint callback
> > > > > 
> > > > > make that decision in v4l2_async_notifier_fwnode_parse_endpoint(). If
> > > > > > the callback indicates that is not an error, skip adding the asd to the
> > > > > > notifier and return 0.
> > > > > > 
> > > > > > For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> > > > > > (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback for
> > > > > > unavailable remote fwnodes to maintain the previous behavior.
> > > > > 
> > > > > I'm not sure this should be a per-driver decision.
> > > > > 
> > > > > Generally speaking, if an endpoint node has no remote-endpoint property,
> > > > > the endpoint node is not needed. I've always considered such an endpoint
> > > > > node as invalid. The OF graphs DT bindings are however not clear on this
> > > > > subject.
> > > > 
> > > > Documentation/devicetree/bindings/graph.txt says:
> > > > 
> > > >   Each endpoint should contain a 'remote-endpoint' phandle property
> > > >   that points to the corresponding endpoint in the port of the remote
> > > >   device.
> > > > 
> > > > ("should", not "must").
> > > 
> > > The DT bindings documentation has historically used "should" to mean "must" in 
> > > many places :-( That was a big mistake.
> > 
> > Maybe I could have worded that better? The intention was to let "should"
> > be read as a strong suggestion, like "it is recommended", but not as a
> > requirement.
> 
> Is there a reason for have an endpoint without a remote-endpoint property?

It allows to slightly reduce boilerplate in board device trees at the
cost of empty endpoint nodes included from the dtsi in board DTs that
don't use them.

> The problem with should (in general when it is used when the intention is
> "shall") is that it lets the developer to write broken DT source that is
> still conforming to the spec.
>
> I don't have a strong preference to change should to shall in this
> particular case now but I would have used "shall" to begin with.

I used "should" on purpose, but I'd be fine with giving up on it when
all current users of this loophole are transitioned away from it:

  git grep -A1 "endpoint {" arch/ | grep -B1 "};"

I'm very much against enforcing a required remote-endpoint property in
core DT parsing code, though.

> > > > Later, the remote-node property explicitly lists the remote-endpoint
> > > > property as optional.
> > > 
> > > I've seen that too, and that's why I mentioned that the documentation isn't 
> > > clear on the subject.
> > 
> > Do you have a suggestion how to improve the documentation? I thought
> > listing the remote-endpoint property under a header called "Optional
> > endpoint properties" was pretty clear.
> > 
> > > This could also be achieved by adding the endpoints in the board DT files. See 
> > > for instance the hdmi@fead0000 node in arch/arm64/boot/dts/renesas/
> > > r8a7795.dtsi and how it gets extended in arch/arm64/boot/dts/renesas/r8a7795-
> > > salvator-x.dts. On the other hand, I also have empty endpoints in the 
> > > display@feb00000 node of arch/arm64/boot/dts/renesas/r8a7795.dtsi.
> > 
> > Right, that would be possible.
> > 
> > > I think we should first decide what we want to do going forward (allowing for 
> > > empty endpoints or not), clarify the documentation, and then update the code. 
> > > In any case I don't think it should be a per-device decision.
> > 
> > There are device trees in the wild that have those empty endpoints, so I
> > don't think retroactively declaring the remote-endpoint property
> > required is a good idea.
> 
> You could IMO, but the kernel (and existing drivers) would still need to
> work with DT binaries without those bits. And leave comments in the code
> why it's there.
>
> > 
> > Is there any driver that currently benefits from throwing an error on
> > empty endpoints in any way? I'd prefer to just let the core ignore empty
> > endpoints for all drivers.
> 
> Not necessarily, but it's overhead in parsing the DT as well as in the
> DT source and in the DT binary.

True. I suppose whether or not that is enough reason to change the
wording in the existing of-graph bindings is something to be decided on
the devicetree list (in Cc).

regards
Philipp

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

* Re: [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error
  2018-02-27  9:13             ` Philipp Zabel
@ 2018-02-27  9:53               ` Laurent Pinchart
  0 siblings, 0 replies; 27+ messages in thread
From: Laurent Pinchart @ 2018-02-27  9:53 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: Sakari Ailus, Steve Longerbeam, Yong Zhi, Mauro Carvalho Chehab,
	niklas.soderlund, Sebastian Reichel, Hans Verkuil, linux-media,
	Steve Longerbeam, devicetree

Hi Philipp,

On Tuesday, 27 February 2018 11:13:04 EET Philipp Zabel wrote:
> On Fri, 2018-02-23 at 14:47 +0200, Sakari Ailus wrote:
> > On Fri, Feb 23, 2018 at 12:16:17PM +0100, Philipp Zabel wrote:
> >> On Fri, 2018-02-23 at 12:05 +0200, Laurent Pinchart wrote:
> >>> On Friday, 23 February 2018 11:56:52 EET Philipp Zabel wrote:
> >>>> On Fri, 2018-02-23 at 11:29 +0200, Laurent Pinchart wrote:
> >>>>> On Thursday, 22 February 2018 03:39:37 EET Steve Longerbeam wrote:
> >>>>>> For some subdevices, a fwnode endpoint that has no connection to
> >>>>>> a remote endpoint may not be an error. Let the parse_endpoint
> >>>>>> callback
> >>>>> 
> >>>>> make that decision in v4l2_async_notifier_fwnode_parse_endpoint().
> >>>>> If
> >>>>> 
> >>>>>> the callback indicates that is not an error, skip adding the asd
> >>>>>> to the notifier and return 0.
> >>>>>> 
> >>>>>> For the current users of v4l2_async_notifier_parse_fwnode_endpoints()
> >>>>>> (omap3isp, rcar-vin, intel-ipu3), return -EINVAL in the callback
> >>>>>> for unavailable remote fwnodes to maintain the previous behavior.
> >>>>> 
> >>>>> I'm not sure this should be a per-driver decision.
> >>>>> 
> >>>>> Generally speaking, if an endpoint node has no remote-endpoint
> >>>>> property, the endpoint node is not needed. I've always considered such
> >>>>> an endpoint node as invalid. The OF graphs DT bindings are however not
> >>>>> clear on this subject.
> >>>> 
> >>>> Documentation/devicetree/bindings/graph.txt says:
> >>>>   Each endpoint should contain a 'remote-endpoint' phandle property
> >>>>   that points to the corresponding endpoint in the port of the
> >>>>   remote device.
> >>>> 
> >>>> ("should", not "must").
> >>> 
> >>> The DT bindings documentation has historically used "should" to mean
> >>> "must" in many places :-( That was a big mistake.
> >> 
> >> Maybe I could have worded that better? The intention was to let "should"
> >> be read as a strong suggestion, like "it is recommended", but not as a
> >> requirement.
> > 
> > Is there a reason for have an endpoint without a remote-endpoint property?
> 
> It allows to slightly reduce boilerplate in board device trees at the
> cost of empty endpoint nodes included from the dtsi in board DTs that
> don't use them.
> 
> > The problem with should (in general when it is used when the intention is
> > "shall") is that it lets the developer to write broken DT source that is
> > still conforming to the spec.
> > 
> > I don't have a strong preference to change should to shall in this
> > particular case now but I would have used "shall" to begin with.
> 
> I used "should" on purpose, but I'd be fine with giving up on it when
> all current users of this loophole are transitioned away from it:
> 
>   git grep -A1 "endpoint {" arch/ | grep -B1 "};"
> 
> I'm very much against enforcing a required remote-endpoint property in
> core DT parsing code, though.

Just to make it clear, I'm fine with making the property either optional or 
mandatory, but I would like the rule to be global, not per-bindings. When the 
OF graphs bindings were developed we reasoned that there was no use for empty 
endpoints and that they should thus be forbidden. Now, if we have good use 
cases for empty endpoints, I don't object them.

Regardless of what we decide I agree that we need to support existing device 
trees and must thus not reject empty endpoints as invalid. We could, however, 
if we decide to forbid empty endpoints, print a warning to encourage DT 
authors to fix the problem.

> >>>> Later, the remote-node property explicitly lists the remote-endpoint
> >>>> property as optional.
> >>> 
> >>> I've seen that too, and that's why I mentioned that the documentation
> >>> isn't clear on the subject.
> >> 
> >> Do you have a suggestion how to improve the documentation? I thought
> >> listing the remote-endpoint property under a header called "Optional
> >> endpoint properties" was pretty clear.
> >> 
> >>> This could also be achieved by adding the endpoints in the board DT
> >>> files. See for instance the hdmi@fead0000 node in
> >>> arch/arm64/boot/dts/renesas/ r8a7795.dtsi and how it gets extended in
> >>> arch/arm64/boot/dts/renesas/r8a7795- salvator-x.dts. On the other
> >>> hand, I also have empty endpoints in the display@feb00000 node of
> >>> arch/arm64/boot/dts/renesas/r8a7795.dtsi.
> >> 
> >> Right, that would be possible.
> >> 
> >>> I think we should first decide what we want to do going forward
> >>> (allowing for empty endpoints or not), clarify the documentation, and
> >>> then update the code. In any case I don't think it should be a
> >>> per-device decision.
> >> 
> >> There are device trees in the wild that have those empty endpoints, so I
> >> don't think retroactively declaring the remote-endpoint property
> >> required is a good idea.
> > 
> > You could IMO, but the kernel (and existing drivers) would still need to
> > work with DT binaries without those bits. And leave comments in the code
> > why it's there.
> > 
> >> Is there any driver that currently benefits from throwing an error on
> >> empty endpoints in any way? I'd prefer to just let the core ignore empty
> >> endpoints for all drivers.
> > 
> > Not necessarily, but it's overhead in parsing the DT as well as in the
> > DT source and in the DT binary.
> 
> True. I suppose whether or not that is enough reason to change the
> wording in the existing of-graph bindings is something to be decided on
> the devicetree list (in Cc).

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 00/13] media: imx: Switch to subdev notifiers
  2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
                   ` (12 preceding siblings ...)
  2018-02-22  1:39 ` [PATCH 13/13] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
@ 2018-03-09 12:57 ` Hans Verkuil
  2018-03-09 17:26   ` Steve Longerbeam
  13 siblings, 1 reply; 27+ messages in thread
From: Hans Verkuil @ 2018-03-09 12:57 UTC (permalink / raw)
  To: Steve Longerbeam, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	Laurent Pinchart, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

Hi Steve,

I understand there will be a v2 of this series? If so, then I can mark this
series as 'Changes Requested' in patchwork.

Regards,

	Hans

On 22/02/18 02:39, Steve Longerbeam wrote:
> This patchset converts the imx-media driver and its dependent
> subdevs to use subdev notifiers.
> 
> There are a couple shortcomings in v4l2-core that prevented
> subdev notifiers from working correctly in imx-media:
> 
> 1. v4l2_async_notifier_fwnode_parse_endpoint() treats a fwnode
>    endpoint that is not connected to a remote device as an error.
>    But in the case of the video-mux subdev, this is not an error, it's
>    ok if some of the muxes inputs have no connection. So the first
>    patch is a small modification to allow the parse_endpoint callback
>    to decide whether an unconnected endpoint is an error.
> 
> 2. In the imx-media graph, multiple subdevs will encounter the same
>    upstream subdev (such as the imx6-mipi-csi2 receiver), and so
>    v4l2_async_notifier_parse_fwnode_endpoints() will add imx6-mipi-csi2
>    multiple times. This is treated as an error by
>    v4l2_async_notifier_register() later.
> 
>    To get around this problem, add an v4l2_async_notifier_add_subdev()
>    which first verifies the provided asd does not already exist in the
>    given notifier asd list or in other registered notifiers. If the asd
>    exists, the function returns -EEXIST and it's up to the caller to
>    decide if that is an error (in imx-media case it is never an error).
> 
>    Patches 2-4 deal with adding that support.
> 
> 3. Patch 5 adds v4l2_async_register_fwnode_subdev(), which is a
>    convenience function for parsing a subdev's fwnode port endpoints
>    for connected remote subdevs, registering a subdev notifier, and
>    then registering the sub-device itself.
> 
> The remaining patches update the subdev drivers to register a
> subdev notifier with endpoint parsing, and the changes to imx-media
> to support that.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> 
> 
> Steve Longerbeam (13):
>   media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is
>     error
>   media: v4l2: async: Allow searching for asd of any type
>   media: v4l2: async: Add v4l2_async_notifier_add_subdev
>   media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
>   media: v4l2-fwnode: Add a convenience function for registering subdevs
>     with notifiers
>   media: platform: video-mux: Register a subdev notifier
>   media: imx: csi: Register a subdev notifier
>   media: imx: mipi csi-2: Register a subdev notifier
>   media: staging/imx: of: Remove recursive graph walk
>   media: staging/imx: Loop through all registered subdevs for media
>     links
>   media: staging/imx: Rename root notifier
>   media: staging/imx: Switch to v4l2_async_notifier_add_subdev
>   media: staging/imx: TODO: Remove one assumption about OF graph parsing
> 
>  drivers/media/pci/intel/ipu3/ipu3-cio2.c          |  13 +-
>  drivers/media/platform/omap3isp/isp.c             |   3 +
>  drivers/media/platform/rcar-vin/rcar-core.c       |   3 +
>  drivers/media/platform/video-mux.c                |  35 ++-
>  drivers/media/v4l2-core/v4l2-async.c              | 275 ++++++++++++++++------
>  drivers/media/v4l2-core/v4l2-fwnode.c             | 230 ++++++++++--------
>  drivers/staging/media/imx/TODO                    |  29 +--
>  drivers/staging/media/imx/imx-media-csi.c         |  11 +-
>  drivers/staging/media/imx/imx-media-dev.c         | 134 +++--------
>  drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
>  drivers/staging/media/imx/imx-media-of.c          | 106 +--------
>  drivers/staging/media/imx/imx-media.h             |   6 +-
>  drivers/staging/media/imx/imx6-mipi-csi2.c        |  31 ++-
>  include/media/v4l2-async.h                        |  24 +-
>  include/media/v4l2-fwnode.h                       |  64 ++++-
>  15 files changed, 546 insertions(+), 423 deletions(-)
> 

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

* Re: [PATCH 00/13] media: imx: Switch to subdev notifiers
  2018-03-09 12:57 ` [PATCH 00/13] media: imx: Switch to subdev notifiers Hans Verkuil
@ 2018-03-09 17:26   ` Steve Longerbeam
  0 siblings, 0 replies; 27+ messages in thread
From: Steve Longerbeam @ 2018-03-09 17:26 UTC (permalink / raw)
  To: Hans Verkuil, Yong Zhi, Sakari Ailus, Mauro Carvalho Chehab,
	Laurent Pinchart, niklas.soderlund, Sebastian Reichel,
	Hans Verkuil, Philipp Zabel
  Cc: linux-media, Steve Longerbeam

Hi Hans,


On 03/09/2018 04:57 AM, Hans Verkuil wrote:
> Hi Steve,
>
> I understand there will be a v2 of this series?

Yes. I'm mulling what to do about the empty endpoints issue.
My initial thought was to modify the i.mx6 DTS to remove the
empty endpoints in the video-mux input ports, which would also
require a change to the video-mux driver. But that would also
introduce a kernel incompatibility with previously built / existing
DTBs.

But it sounds like there is agreement between Laurent, Philipp, and
Sakari that it would be acceptable for media/v4l2 core to ignore empty
endpoints, as long as that is done consistently throughout, and that
the binding docs are updated to be more explicitly clear that the
remote-endpoint property is optional (but recommended).
Is that correct?

I prefer this approach, since it doesn't introduce an incompatibility
with existing DTBs.

So I am leaning towards modifying only the first patch in this
series ("media: v4l2-fwnode: Let parse_endpoint callback decide
if no remote is error"), to simply ignore empty endpoints in
v4l2_async_notifier_fwnode_parse_endpoint() and return success.


>   If so, then I can mark this
> series as 'Changes Requested' in patchwork.

Yep, that's fine.

Steve


>
>
>
> On 22/02/18 02:39, Steve Longerbeam wrote:
>> This patchset converts the imx-media driver and its dependent
>> subdevs to use subdev notifiers.
>>
>> There are a couple shortcomings in v4l2-core that prevented
>> subdev notifiers from working correctly in imx-media:
>>
>> 1. v4l2_async_notifier_fwnode_parse_endpoint() treats a fwnode
>>     endpoint that is not connected to a remote device as an error.
>>     But in the case of the video-mux subdev, this is not an error, it's
>>     ok if some of the muxes inputs have no connection. So the first
>>     patch is a small modification to allow the parse_endpoint callback
>>     to decide whether an unconnected endpoint is an error.
>>
>> 2. In the imx-media graph, multiple subdevs will encounter the same
>>     upstream subdev (such as the imx6-mipi-csi2 receiver), and so
>>     v4l2_async_notifier_parse_fwnode_endpoints() will add imx6-mipi-csi2
>>     multiple times. This is treated as an error by
>>     v4l2_async_notifier_register() later.
>>
>>     To get around this problem, add an v4l2_async_notifier_add_subdev()
>>     which first verifies the provided asd does not already exist in the
>>     given notifier asd list or in other registered notifiers. If the asd
>>     exists, the function returns -EEXIST and it's up to the caller to
>>     decide if that is an error (in imx-media case it is never an error).
>>
>>     Patches 2-4 deal with adding that support.
>>
>> 3. Patch 5 adds v4l2_async_register_fwnode_subdev(), which is a
>>     convenience function for parsing a subdev's fwnode port endpoints
>>     for connected remote subdevs, registering a subdev notifier, and
>>     then registering the sub-device itself.
>>
>> The remaining patches update the subdev drivers to register a
>> subdev notifier with endpoint parsing, and the changes to imx-media
>> to support that.
>>
>> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
>> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
>>
>>
>> Steve Longerbeam (13):
>>    media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is
>>      error
>>    media: v4l2: async: Allow searching for asd of any type
>>    media: v4l2: async: Add v4l2_async_notifier_add_subdev
>>    media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
>>    media: v4l2-fwnode: Add a convenience function for registering subdevs
>>      with notifiers
>>    media: platform: video-mux: Register a subdev notifier
>>    media: imx: csi: Register a subdev notifier
>>    media: imx: mipi csi-2: Register a subdev notifier
>>    media: staging/imx: of: Remove recursive graph walk
>>    media: staging/imx: Loop through all registered subdevs for media
>>      links
>>    media: staging/imx: Rename root notifier
>>    media: staging/imx: Switch to v4l2_async_notifier_add_subdev
>>    media: staging/imx: TODO: Remove one assumption about OF graph parsing
>>
>>   drivers/media/pci/intel/ipu3/ipu3-cio2.c          |  13 +-
>>   drivers/media/platform/omap3isp/isp.c             |   3 +
>>   drivers/media/platform/rcar-vin/rcar-core.c       |   3 +
>>   drivers/media/platform/video-mux.c                |  35 ++-
>>   drivers/media/v4l2-core/v4l2-async.c              | 275 ++++++++++++++++------
>>   drivers/media/v4l2-core/v4l2-fwnode.c             | 230 ++++++++++--------
>>   drivers/staging/media/imx/TODO                    |  29 +--
>>   drivers/staging/media/imx/imx-media-csi.c         |  11 +-
>>   drivers/staging/media/imx/imx-media-dev.c         | 134 +++--------
>>   drivers/staging/media/imx/imx-media-internal-sd.c |   5 +-
>>   drivers/staging/media/imx/imx-media-of.c          | 106 +--------
>>   drivers/staging/media/imx/imx-media.h             |   6 +-
>>   drivers/staging/media/imx/imx6-mipi-csi2.c        |  31 ++-
>>   include/media/v4l2-async.h                        |  24 +-
>>   include/media/v4l2-fwnode.h                       |  64 ++++-
>>   15 files changed, 546 insertions(+), 423 deletions(-)
>>

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

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

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-22  1:39 [PATCH 00/13] media: imx: Switch to subdev notifiers Steve Longerbeam
2018-02-22  1:39 ` [PATCH 01/13] media: v4l2-fwnode: Let parse_endpoint callback decide if no remote is error Steve Longerbeam
2018-02-23  9:29   ` Laurent Pinchart
2018-02-23  9:56     ` Philipp Zabel
2018-02-23 10:05       ` Laurent Pinchart
2018-02-23 10:14         ` Sakari Ailus
2018-02-23 11:16         ` Philipp Zabel
2018-02-23 12:47           ` Sakari Ailus
2018-02-27  9:13             ` Philipp Zabel
2018-02-27  9:53               ` Laurent Pinchart
2018-02-23 18:22           ` Steve Longerbeam
2018-02-22  1:39 ` [PATCH 02/13] media: v4l2: async: Allow searching for asd of any type Steve Longerbeam
2018-02-22  1:39 ` [PATCH 03/13] media: v4l2: async: Add v4l2_async_notifier_add_subdev Steve Longerbeam
2018-02-22  1:39 ` [PATCH 04/13] media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
2018-02-22  1:39 ` [PATCH 05/13] media: v4l2-fwnode: Add a convenience function for registering subdevs with notifiers Steve Longerbeam
2018-02-23  6:47   ` kbuild test robot
2018-02-22  1:39 ` [PATCH 06/13] media: platform: video-mux: Register a subdev notifier Steve Longerbeam
2018-02-23  4:55   ` kbuild test robot
2018-02-22  1:39 ` [PATCH 07/13] media: imx: csi: " Steve Longerbeam
2018-02-22  1:39 ` [PATCH 08/13] media: imx: mipi csi-2: " Steve Longerbeam
2018-02-22  1:39 ` [PATCH 09/13] media: staging/imx: of: Remove recursive graph walk Steve Longerbeam
2018-02-22  1:39 ` [PATCH 10/13] media: staging/imx: Loop through all registered subdevs for media links Steve Longerbeam
2018-02-22  1:39 ` [PATCH 11/13] media: staging/imx: Rename root notifier Steve Longerbeam
2018-02-22  1:39 ` [PATCH 12/13] media: staging/imx: Switch to v4l2_async_notifier_add_subdev Steve Longerbeam
2018-02-22  1:39 ` [PATCH 13/13] media: staging/imx: TODO: Remove one assumption about OF graph parsing Steve Longerbeam
2018-03-09 12:57 ` [PATCH 00/13] media: imx: Switch to subdev notifiers Hans Verkuil
2018-03-09 17:26   ` Steve Longerbeam

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