All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] V4L2 Async notifier API cleanup
@ 2021-01-12 13:23 Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics Ezequiel Garcia
                   ` (12 more replies)
  0 siblings, 13 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The goal of this series is to make the API more consistent,
also fixing all the drivers which are currently misusing the API.

With this change, the v4l2-async functions that add subdevices
to a notifier have the same semantics, that is they all
allocate a struct v4l2_async_subdev, and take a size argument
for drivers to embed struct v4l2_async_subdev in a larger
struct.

This makes the struct v4l2_async_subdev allocation model
more consistent, simpler to understand, and harder to misuse.

The V4L2 sub-devices documentation, as well as the kernel-doc
are also improved a bit, clarifying the API.

Finally, all the drivers previously using v4l2_async_notifier_add_subdev
are converted to proper helpers,

I have tried to convert the drivers in the least invasive way,
keeping the original code as much as possible. In many cases,
specially the old drivers, there is some bitrot and some room
for more cleanups, which is beyond the scope of this patchset.

I'd like to make v4l2_async_notifier_add_subdev() internal, which
might be possible once the (currently deprecated)
v4l2_async_notifier_parse_fwnode_endpoints() function
is removed. For the time being, I'm proposing to rename
v4l2_async_notifier_add_subdev to __v4l2_async_notifier_add_subdev,
so it's clearer the function is not really meant for drivers to use.

Ezequiel Garcia (13):
  media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev
  media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  media: atmel: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  media: cdns-csi2rx: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  media: pxa-camera: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  media: davinci: vpif_display: Remove unused v4l2-async code
  media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention
  media: Clarify v4l2-async subdevice addition API
  media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev

 .../driver-api/media/v4l2-subdev.rst          | 38 ++++++--
 drivers/media/i2c/st-mipid02.c                | 16 ++--
 drivers/media/pci/intel/ipu3/ipu3-cio2.c      | 17 ++--
 drivers/media/platform/atmel/atmel-isc.h      |  1 +
 drivers/media/platform/atmel/atmel-isi.c      | 46 +++-------
 .../media/platform/atmel/atmel-sama5d2-isc.c  | 44 ++++-----
 drivers/media/platform/cadence/cdns-csi2rx.c  | 16 ++--
 drivers/media/platform/davinci/vpif_display.c | 86 ++++--------------
 drivers/media/platform/davinci/vpif_display.h |  1 -
 drivers/media/platform/exynos4-is/media-dev.c | 25 +++---
 drivers/media/platform/exynos4-is/media-dev.h |  2 +-
 .../media/platform/marvell-ccic/cafe-driver.c | 14 ++-
 .../media/platform/marvell-ccic/mcam-core.c   | 10 ---
 .../media/platform/marvell-ccic/mcam-core.h   |  1 -
 .../media/platform/marvell-ccic/mmp-driver.c  | 11 ++-
 drivers/media/platform/omap3isp/isp.c         | 78 +++++++---------
 drivers/media/platform/pxa_camera.c           | 53 +++++------
 drivers/media/platform/renesas-ceu.c          | 89 +++++++------------
 .../platform/rockchip/rkisp1/rkisp1-dev.c     | 15 ++--
 drivers/media/platform/stm32/stm32-dcmi.c     | 86 +++++++-----------
 .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  9 +-
 .../platform/sunxi/sun4i-csi/sun4i_csi.h      |  1 -
 drivers/media/platform/video-mux.c            | 14 +--
 drivers/media/v4l2-core/v4l2-async.c          | 34 +++----
 drivers/media/v4l2-core/v4l2-fwnode.c         |  2 +-
 drivers/staging/media/imx/imx-media-csi.c     | 14 +--
 drivers/staging/media/imx/imx6-mipi-csi2.c    | 19 ++--
 drivers/staging/media/imx/imx7-media-csi.c    | 16 ++--
 drivers/staging/media/imx/imx7-mipi-csis.c    | 15 +---
 include/media/davinci/vpif_types.h            |  2 -
 include/media/v4l2-async.h                    | 40 ++++++---
 31 files changed, 323 insertions(+), 492 deletions(-)

-- 
2.29.2


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

* [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-14  1:59   ` Laurent Pinchart
  2021-01-12 13:23 ` [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

Change v4l2_async_notifier_add_fwnode_remote_subdev semantics
so it allocates the struct v4l2_async_subdev pointer.

This makes the API consistent: the v4l2-async subdevice addition
functions have now a unified usage model. This model is simpler,
as it makes v4l2-async responsible for the allocation and release
of the subdevice descriptor, and no longer something the driver
has to worry about.

On the user side, the change makes the API simpler for the drivers
to use and less error-prone.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/pci/intel/ipu3/ipu3-cio2.c      | 17 ++--
 drivers/media/platform/omap3isp/isp.c         | 78 ++++++++-----------
 .../platform/rockchip/rkisp1/rkisp1-dev.c     | 15 ++--
 .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  9 ++-
 .../platform/sunxi/sun4i-csi/sun4i_csi.h      |  1 -
 drivers/media/platform/video-mux.c            | 14 +---
 drivers/media/v4l2-core/v4l2-async.c          | 24 +++---
 drivers/staging/media/imx/imx-media-csi.c     | 14 +---
 drivers/staging/media/imx/imx6-mipi-csi2.c    | 19 ++---
 drivers/staging/media/imx/imx7-media-csi.c    | 16 ++--
 drivers/staging/media/imx/imx7-mipi-csis.c    | 15 +---
 include/media/v4l2-async.h                    | 15 ++--
 12 files changed, 93 insertions(+), 144 deletions(-)

diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 36e354ecf71e..c1d42cbecbc1 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -1467,7 +1467,8 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
 		struct v4l2_fwnode_endpoint vep = {
 			.bus_type = V4L2_MBUS_CSI2_DPHY
 		};
-		struct sensor_async_subdev *s_asd = NULL;
+		struct sensor_async_subdev *s_asd;
+		struct v4l2_async_subdev *asd;
 		struct fwnode_handle *ep;
 
 		ep = fwnode_graph_get_endpoint_by_id(
@@ -1481,27 +1482,23 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
 		if (ret)
 			goto err_parse;
 
-		s_asd = kzalloc(sizeof(*s_asd), GFP_KERNEL);
-		if (!s_asd) {
-			ret = -ENOMEM;
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+				&cio2->notifier, ep, sizeof(*s_asd));
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			goto err_parse;
 		}
 
+		s_asd = container_of(asd, struct sensor_async_subdev, asd);
 		s_asd->csi2.port = vep.base.port;
 		s_asd->csi2.lanes = vep.bus.mipi_csi2.num_data_lanes;
 
-		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-			&cio2->notifier, ep, &s_asd->asd);
-		if (ret)
-			goto err_parse;
-
 		fwnode_handle_put(ep);
 
 		continue;
 
 err_parse:
 		fwnode_handle_put(ep);
-		kfree(s_asd);
 		return ret;
 	}
 
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index b1fc4518e275..51c35f42773f 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2126,21 +2126,6 @@ static void isp_parse_of_csi1_endpoint(struct device *dev,
 	buscfg->bus.ccp2.crc = 1;
 }
 
-static int isp_alloc_isd(struct isp_async_subdev **isd,
-			 struct isp_bus_cfg **buscfg)
-{
-	struct isp_async_subdev *__isd;
-
-	__isd = kzalloc(sizeof(*__isd), GFP_KERNEL);
-	if (!__isd)
-		return -ENOMEM;
-
-	*isd = __isd;
-	*buscfg = &__isd->bus;
-
-	return 0;
-}
-
 static struct {
 	u32 phy;
 	u32 csi2_if;
@@ -2156,7 +2141,7 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
 {
 	struct fwnode_handle *ep;
 	struct isp_async_subdev *isd = NULL;
-	struct isp_bus_cfg *buscfg;
+	struct v4l2_async_subdev *asd;
 	unsigned int i;
 
 	ep = fwnode_graph_get_endpoint_by_id(
@@ -2174,20 +2159,15 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
 		ret = v4l2_fwnode_endpoint_parse(ep, &vep);
 
 		if (!ret) {
-			ret = isp_alloc_isd(&isd, &buscfg);
-			if (ret)
-				return ret;
-		}
-
-		if (!ret) {
-			isp_parse_of_parallel_endpoint(isp->dev, &vep, buscfg);
-			ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-				&isp->notifier, ep, &isd->asd);
+			asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+				&isp->notifier, ep, sizeof(*isd));
+			if (!IS_ERR(asd)) {
+				isd = container_of(asd, struct isp_async_subdev, asd);
+				isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus);
+			}
 		}
 
 		fwnode_handle_put(ep);
-		if (ret)
-			kfree(isd);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) {
@@ -2206,15 +2186,8 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
 		dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i,
 			to_of_node(ep));
 
-		ret = isp_alloc_isd(&isd, &buscfg);
-		if (ret)
-			return ret;
-
 		ret = v4l2_fwnode_endpoint_parse(ep, &vep);
-		if (!ret) {
-			buscfg->interface = isp_bus_interfaces[i].csi2_if;
-			isp_parse_of_csi2_endpoint(isp->dev, &vep, buscfg);
-		} else if (ret == -ENXIO) {
+		if (ret == -ENXIO) {
 			vep = (struct v4l2_fwnode_endpoint)
 				{ .bus_type = V4L2_MBUS_CSI1 };
 			ret = v4l2_fwnode_endpoint_parse(ep, &vep);
@@ -2224,21 +2197,34 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
 					{ .bus_type = V4L2_MBUS_CCP2 };
 				ret = v4l2_fwnode_endpoint_parse(ep, &vep);
 			}
-			if (!ret) {
-				buscfg->interface =
-					isp_bus_interfaces[i].csi1_if;
-				isp_parse_of_csi1_endpoint(isp->dev, &vep,
-							   buscfg);
-			}
 		}
 
-		if (!ret)
-			ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-				&isp->notifier, ep, &isd->asd);
+		if (!ret) {
+			asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+				&isp->notifier, ep, sizeof(*isd));
+
+			if (!IS_ERR(asd)) {
+				isd = container_of(asd, struct isp_async_subdev, asd);
+				switch (vep.bus_type) {
+				case V4L2_MBUS_CSI2_DPHY:
+					isd->bus.interface =
+						isp_bus_interfaces[i].csi2_if;
+					isp_parse_of_csi2_endpoint(isp->dev, &vep, &isd->bus);
+					break;
+				case V4L2_MBUS_CSI1:
+				case V4L2_MBUS_CCP2:
+					isd->bus.interface =
+						isp_bus_interfaces[i].csi1_if;
+					isp_parse_of_csi1_endpoint(isp->dev, &vep,
+								   &isd->bus);
+					break;
+				default:
+					break;
+				}
+			}
+		}
 
 		fwnode_handle_put(ep);
-		if (ret)
-			kfree(isd);
 	}
 
 	return 0;
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index 68da1eed753d..235dcf0c4122 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
 			.bus_type = V4L2_MBUS_CSI2_DPHY
 		};
 		struct rkisp1_sensor_async *rk_asd = NULL;
+		struct v4l2_async_subdev *asd;
 		struct fwnode_handle *ep;
 
 		ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
@@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
 		if (ret)
 			goto err_parse;
 
-		rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
-		if (!rk_asd) {
-			ret = -ENOMEM;
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
+							sizeof(*rk_asd));
+		if (IS_ERR(asd))
 			goto err_parse;
-		}
 
+		rk_asd = container_of(asd, struct rkisp1_sensor_async, asd);
 		rk_asd->mbus_type = vep.bus_type;
 		rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;
 		rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;
 
-		ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
-								   &rk_asd->asd);
-		if (ret)
-			goto err_parse;
-
 		dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n",
 			vep.base.id, rk_asd->lanes);
 
@@ -289,7 +285,6 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
 		continue;
 err_parse:
 		fwnode_handle_put(ep);
-		kfree(rk_asd);
 		v4l2_async_notifier_cleanup(ntf);
 		return ret;
 	}
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
index ec46cff80fdb..3f94b8c966f3 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -118,6 +118,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_PARALLEL,
 	};
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -134,10 +135,12 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
 
 	csi->bus = vep.bus.parallel;
 
-	ret = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
-							   ep, &csi->asd);
-	if (ret)
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
+							   ep, sizeof(*asd));
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
 		goto out;
+	}
 
 	csi->notifier.ops = &sun4i_csi_notify_ops;
 
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
index 0f67ff652c2e..a5f61ee0ec4d 100644
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
@@ -139,7 +139,6 @@ struct sun4i_csi {
 	struct v4l2_mbus_framefmt	subdev_fmt;
 
 	/* V4L2 Async variables */
-	struct v4l2_async_subdev	asd;
 	struct v4l2_async_notifier	notifier;
 	struct v4l2_subdev		*src_subdev;
 	int				src_pad;
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
index 53570250a25d..7b280dfca727 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -370,19 +370,13 @@ static int video_mux_async_register(struct video_mux *vmux,
 		if (!ep)
 			continue;
 
-		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-		if (!asd) {
-			fwnode_handle_put(ep);
-			return -ENOMEM;
-		}
-
-		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-			&vmux->notifier, ep, asd);
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+			&vmux->notifier, ep, sizeof(*asd));
 
 		fwnode_handle_put(ep);
 
-		if (ret) {
-			kfree(asd);
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			/* OK if asd already exists */
 			if (ret != -EEXIST)
 				return ret;
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 32cd1ecced97..b325bacddff4 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -675,26 +675,26 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
 }
 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
 
-int
+struct v4l2_async_subdev *
 v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
 					     struct fwnode_handle *endpoint,
-					     struct v4l2_async_subdev *asd)
+					     unsigned int asd_struct_size)
 {
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *remote;
-	int ret;
 
 	remote = fwnode_graph_get_remote_port_parent(endpoint);
 	if (!remote)
-		return -ENOTCONN;
+		return ERR_PTR(ENOTCONN);
 
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode = remote;
-
-	ret = v4l2_async_notifier_add_subdev(notif, asd);
-	if (ret)
-		fwnode_handle_put(remote);
-
-	return ret;
+	asd = v4l2_async_notifier_add_fwnode_subdev(notif,
+						    remote, asd_struct_size);
+	/*
+	 * Calling v4l2_async_notifier_add_fwnode_subdev grabs a refcount,
+	 * so drop then one we got in fwnode_graph_get_remote_port_parent.
+	 */
+	fwnode_handle_put(remote);
+	return asd;
 }
 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev);
 
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index db77fef07654..6344389e6afa 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1922,19 +1922,13 @@ static int imx_csi_async_register(struct csi_priv *priv)
 					     port, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
 	if (ep) {
-		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-		if (!asd) {
-			fwnode_handle_put(ep);
-			return -ENOMEM;
-		}
-
-		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-			&priv->notifier, ep, asd);
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+			&priv->notifier, ep, sizeof(*asd));
 
 		fwnode_handle_put(ep);
 
-		if (ret) {
-			kfree(asd);
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			/* OK if asd already exists */
 			if (ret != -EEXIST)
 				return ret;
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index bf6a61dd34c2..807d0dcbd6fd 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -636,7 +636,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd = NULL;
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -656,19 +656,13 @@ static int csi2_async_register(struct csi2_dev *csi2)
 	dev_dbg(csi2->dev, "data lanes: %d\n", vep.bus.mipi_csi2.num_data_lanes);
 	dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags);
 
-	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-	if (!asd) {
-		ret = -ENOMEM;
-		goto err_parse;
-	}
-
-	ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-		&csi2->notifier, ep, asd);
-	if (ret)
-		goto err_parse;
-
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+		&csi2->notifier, ep, sizeof(*asd));
 	fwnode_handle_put(ep);
 
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
+
 	csi2->notifier.ops = &csi2_notify_ops;
 
 	ret = v4l2_async_subdev_notifier_register(&csi2->sd,
@@ -680,7 +674,6 @@ static int csi2_async_register(struct csi2_dev *csi2)
 
 err_parse:
 	fwnode_handle_put(ep);
-	kfree(asd);
 	return ret;
 }
 
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
index a3f3df901704..4ea6e0bb274d 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1180,7 +1180,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
 
 static int imx7_csi_async_register(struct imx7_csi *csi)
 {
-	struct v4l2_async_subdev *asd = NULL;
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -1189,19 +1189,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
 	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
 					     FWNODE_GRAPH_ENDPOINT_NEXT);
 	if (ep) {
-		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-		if (!asd) {
-			fwnode_handle_put(ep);
-			return -ENOMEM;
-		}
-
-		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-			&csi->notifier, ep, asd);
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+			&csi->notifier, ep, sizeof(*asd));
 
 		fwnode_handle_put(ep);
 
-		if (ret) {
-			kfree(asd);
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			/* OK if asd already exists */
 			if (ret != -EEXIST)
 				return ret;
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
index 7612993cc1d6..32d8e7a824d4 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -1004,7 +1004,7 @@ static int mipi_csis_async_register(struct csi_state *state)
 	struct v4l2_fwnode_endpoint vep = {
 		.bus_type = V4L2_MBUS_CSI2_DPHY,
 	};
-	struct v4l2_async_subdev *asd = NULL;
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *ep;
 	int ret;
 
@@ -1024,15 +1024,9 @@ static int mipi_csis_async_register(struct csi_state *state)
 	dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
 	dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
 
-	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
-	if (!asd) {
-		ret = -ENOMEM;
-		goto err_parse;
-	}
-
-	ret = v4l2_async_notifier_add_fwnode_remote_subdev(
-		&state->notifier, ep, asd);
-	if (ret)
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+		&state->notifier, ep, sizeof(*asd));
+	if (IS_ERR(asd))
 		goto err_parse;
 
 	fwnode_handle_put(ep);
@@ -1048,7 +1042,6 @@ static int mipi_csis_async_register(struct csi_state *state)
 
 err_parse:
 	fwnode_handle_put(ep);
-	kfree(asd);
 
 	return ret;
 }
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index a5dc4a74d42d..76be1e01222e 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -197,9 +197,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
  *
  * @notif: pointer to &struct v4l2_async_notifier
  * @endpoint: local endpoint pointing to the remote sub-device to be matched
- * @asd: Async sub-device struct allocated by the caller. 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.
+ * @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.
  *
  * Gets the remote endpoint of a given local endpoint, set it up for fwnode
  * matching and adds the async sub-device to the notifier's @asd_list. The
@@ -207,13 +209,12 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
  * notifier cleanup time.
  *
  * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
- * exception that the fwnode refers to a local endpoint, not the remote one, and
- * the function relies on the caller to allocate the async sub-device struct.
+ * exception that the fwnode refers to a local endpoint, not the remote one.
  */
-int
+struct v4l2_async_subdev *
 v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
 					     struct fwnode_handle *endpoint,
-					     struct v4l2_async_subdev *asd);
+					     unsigned int asd_struct_size);
 
 /**
  * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
-- 
2.29.2


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

* [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 15:35   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
which handles the needed setup, instead of open-coding it.

This results in removal of the now unneeded driver-specific state
struct dcmi_graph_entity, keeping track of just the source
subdevice.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/stm32/stm32-dcmi.c | 86 ++++++++---------------
 1 file changed, 30 insertions(+), 56 deletions(-)

diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index b745f1342c2e..142f63d07dcd 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -99,13 +99,6 @@ enum state {
 
 #define OVERRUN_ERROR_THRESHOLD	3
 
-struct dcmi_graph_entity {
-	struct v4l2_async_subdev asd;
-
-	struct device_node *remote_node;
-	struct v4l2_subdev *source;
-};
-
 struct dcmi_format {
 	u32	fourcc;
 	u32	mbus_code;
@@ -139,7 +132,7 @@ struct stm32_dcmi {
 	struct v4l2_device		v4l2_dev;
 	struct video_device		*vdev;
 	struct v4l2_async_notifier	notifier;
-	struct dcmi_graph_entity	entity;
+	struct v4l2_subdev		*source;
 	struct v4l2_format		fmt;
 	struct v4l2_rect		crop;
 	bool				do_crop;
@@ -610,7 +603,7 @@ static int dcmi_pipeline_s_fmt(struct stm32_dcmi *dcmi,
 			       struct v4l2_subdev_pad_config *pad_cfg,
 			       struct v4l2_subdev_format *format)
 {
-	struct media_entity *entity = &dcmi->entity.source->entity;
+	struct media_entity *entity = &dcmi->source->entity;
 	struct v4l2_subdev *subdev;
 	struct media_pad *sink_pad = NULL;
 	struct media_pad *src_pad = NULL;
@@ -1018,7 +1011,7 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
 	}
 
 	v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
-	ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
+	ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
 			       &pad_cfg, &format);
 	if (ret < 0)
 		return ret;
@@ -1152,7 +1145,7 @@ static int dcmi_get_sensor_format(struct stm32_dcmi *dcmi,
 	};
 	int ret;
 
-	ret = v4l2_subdev_call(dcmi->entity.source, pad, get_fmt, NULL, &fmt);
+	ret = v4l2_subdev_call(dcmi->source, pad, get_fmt, NULL, &fmt);
 	if (ret)
 		return ret;
 
@@ -1181,7 +1174,7 @@ static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi,
 	}
 
 	v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
-	ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
+	ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
 			       &pad_cfg, &format);
 	if (ret < 0)
 		return ret;
@@ -1204,7 +1197,7 @@ static int dcmi_get_sensor_bounds(struct stm32_dcmi *dcmi,
 	/*
 	 * Get sensor bounds first
 	 */
-	ret = v4l2_subdev_call(dcmi->entity.source, pad, get_selection,
+	ret = v4l2_subdev_call(dcmi->source, pad, get_selection,
 			       NULL, &bounds);
 	if (!ret)
 		*r = bounds.r;
@@ -1385,7 +1378,7 @@ static int dcmi_enum_framesizes(struct file *file, void *fh,
 
 	fse.code = sd_fmt->mbus_code;
 
-	ret = v4l2_subdev_call(dcmi->entity.source, pad, enum_frame_size,
+	ret = v4l2_subdev_call(dcmi->source, pad, enum_frame_size,
 			       NULL, &fse);
 	if (ret)
 		return ret;
@@ -1402,7 +1395,7 @@ static int dcmi_g_parm(struct file *file, void *priv,
 {
 	struct stm32_dcmi *dcmi = video_drvdata(file);
 
-	return v4l2_g_parm_cap(video_devdata(file), dcmi->entity.source, p);
+	return v4l2_g_parm_cap(video_devdata(file), dcmi->source, p);
 }
 
 static int dcmi_s_parm(struct file *file, void *priv,
@@ -1410,7 +1403,7 @@ static int dcmi_s_parm(struct file *file, void *priv,
 {
 	struct stm32_dcmi *dcmi = video_drvdata(file);
 
-	return v4l2_s_parm_cap(video_devdata(file), dcmi->entity.source, p);
+	return v4l2_s_parm_cap(video_devdata(file), dcmi->source, p);
 }
 
 static int dcmi_enum_frameintervals(struct file *file, void *fh,
@@ -1432,7 +1425,7 @@ static int dcmi_enum_frameintervals(struct file *file, void *fh,
 
 	fie.code = sd_fmt->mbus_code;
 
-	ret = v4l2_subdev_call(dcmi->entity.source, pad,
+	ret = v4l2_subdev_call(dcmi->source, pad,
 			       enum_frame_interval, NULL, &fie);
 	if (ret)
 		return ret;
@@ -1452,7 +1445,7 @@ MODULE_DEVICE_TABLE(of, stm32_dcmi_of_match);
 static int dcmi_open(struct file *file)
 {
 	struct stm32_dcmi *dcmi = video_drvdata(file);
-	struct v4l2_subdev *sd = dcmi->entity.source;
+	struct v4l2_subdev *sd = dcmi->source;
 	int ret;
 
 	if (mutex_lock_interruptible(&dcmi->lock))
@@ -1483,7 +1476,7 @@ static int dcmi_open(struct file *file)
 static int dcmi_release(struct file *file)
 {
 	struct stm32_dcmi *dcmi = video_drvdata(file);
-	struct v4l2_subdev *sd = dcmi->entity.source;
+	struct v4l2_subdev *sd = dcmi->source;
 	bool fh_singular;
 	int ret;
 
@@ -1616,7 +1609,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
 {
 	const struct dcmi_format *sd_fmts[ARRAY_SIZE(dcmi_formats)];
 	unsigned int num_fmts = 0, i, j;
-	struct v4l2_subdev *subdev = dcmi->entity.source;
+	struct v4l2_subdev *subdev = dcmi->source;
 	struct v4l2_subdev_mbus_code_enum mbus_code = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
@@ -1675,7 +1668,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
 static int dcmi_framesizes_init(struct stm32_dcmi *dcmi)
 {
 	unsigned int num_fsize = 0;
-	struct v4l2_subdev *subdev = dcmi->entity.source;
+	struct v4l2_subdev *subdev = dcmi->source;
 	struct v4l2_subdev_frame_size_enum fse = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 		.code = dcmi->sd_format->mbus_code,
@@ -1727,14 +1720,13 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
 	 * we search for the source subdevice
 	 * in order to expose it through V4L2 interface
 	 */
-	dcmi->entity.source =
-		media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
-	if (!dcmi->entity.source) {
+	dcmi->source = media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
+	if (!dcmi->source) {
 		dev_err(dcmi->dev, "Source subdevice not found\n");
 		return -ENODEV;
 	}
 
-	dcmi->vdev->ctrl_handler = dcmi->entity.source->ctrl_handler;
+	dcmi->vdev->ctrl_handler = dcmi->source->ctrl_handler;
 
 	ret = dcmi_formats_init(dcmi);
 	if (ret) {
@@ -1813,46 +1805,28 @@ static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = {
 	.complete = dcmi_graph_notify_complete,
 };
 
-static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
-{
-	struct device_node *ep = NULL;
-	struct device_node *remote;
-
-	ep = of_graph_get_next_endpoint(node, ep);
-	if (!ep)
-		return -EINVAL;
-
-	remote = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!remote)
-		return -EINVAL;
-
-	/* Remote node to connect */
-	dcmi->entity.remote_node = remote;
-	dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
-	return 0;
-}
-
 static int dcmi_graph_init(struct stm32_dcmi *dcmi)
 {
+	struct v4l2_async_subdev *asd;
+	struct device_node *ep;
 	int ret;
 
-	/* Parse the graph to extract a list of subdevice DT nodes. */
-	ret = dcmi_graph_parse(dcmi, dcmi->dev->of_node);
-	if (ret < 0) {
-		dev_err(dcmi->dev, "Failed to parse graph\n");
-		return ret;
+	ep = of_graph_get_next_endpoint(dcmi->dev->of_node, NULL);
+	if (!ep) {
+		dev_err(dcmi->dev, "Failed to get next endpoint\n");
+		return -EINVAL;
 	}
 
 	v4l2_async_notifier_init(&dcmi->notifier);
 
-	ret = v4l2_async_notifier_add_subdev(&dcmi->notifier,
-					     &dcmi->entity.asd);
-	if (ret) {
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+		&dcmi->notifier, of_fwnode_handle(ep), sizeof(*asd));
+
+	of_node_put(ep);
+
+	if (IS_ERR(asd)) {
 		dev_err(dcmi->dev, "Failed to add subdev notifier\n");
-		of_node_put(dcmi->entity.remote_node);
-		return ret;
+		return PTR_ERR(asd);
 	}
 
 	dcmi->notifier.ops = &dcmi_graph_notify_ops;
-- 
2.29.2


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

* [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-14  2:06   ` Laurent Pinchart
  2021-01-16 15:56   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev Ezequiel Garcia
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_i2c_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
the needed setup, instead of open-coding it.

Using v4l2-async to allocate the driver-specific structs,
requires to change struct ceu_subdev so the embedded
struct v4l2_async_subdev is now the first element.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/renesas-ceu.c | 89 ++++++++++------------------
 1 file changed, 31 insertions(+), 58 deletions(-)

diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
index 4a633ad0e8fa..18485812a21e 100644
--- a/drivers/media/platform/renesas-ceu.c
+++ b/drivers/media/platform/renesas-ceu.c
@@ -152,8 +152,8 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
  * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
  */
 struct ceu_subdev {
-	struct v4l2_subdev *v4l2_sd;
 	struct v4l2_async_subdev asd;
+	struct v4l2_subdev *v4l2_sd;
 
 	/* per-subdevice mbus configuration options */
 	unsigned int mbus_flags;
@@ -174,7 +174,7 @@ struct ceu_device {
 	struct v4l2_device	v4l2_dev;
 
 	/* subdevices descriptors */
-	struct ceu_subdev	*subdevs;
+	struct ceu_subdev	**subdevs;
 	/* the subdevice currently in use */
 	struct ceu_subdev	*sd;
 	unsigned int		sd_index;
@@ -1195,7 +1195,7 @@ static int ceu_enum_input(struct file *file, void *priv,
 	if (inp->index >= ceudev->num_sd)
 		return -EINVAL;
 
-	ceusd = &ceudev->subdevs[inp->index];
+	ceusd = ceudev->subdevs[inp->index];
 
 	inp->type = V4L2_INPUT_TYPE_CAMERA;
 	inp->std = 0;
@@ -1230,7 +1230,7 @@ static int ceu_s_input(struct file *file, void *priv, unsigned int i)
 		return 0;
 
 	ceu_sd_old = ceudev->sd;
-	ceudev->sd = &ceudev->subdevs[i];
+	ceudev->sd = ceudev->subdevs[i];
 
 	/*
 	 * Make sure we can generate output image formats and apply
@@ -1423,7 +1423,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
 	 * ceu formats.
 	 */
 	if (!ceudev->sd) {
-		ceudev->sd = &ceudev->subdevs[0];
+		ceudev->sd = ceudev->subdevs[0];
 		ceudev->sd_index = 0;
 	}
 
@@ -1465,28 +1465,6 @@ static const struct v4l2_async_notifier_operations ceu_notify_ops = {
 	.complete	= ceu_notify_complete,
 };
 
-/*
- * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
- *			      ceu device. Both DT and platform data parsing use
- *			      this routine.
- *
- * Returns 0 for success, -ENOMEM for failure.
- */
-static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
-{
-	/* Reserve memory for 'n_sd' ceu_subdev descriptors. */
-	ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
-				       sizeof(*ceudev->subdevs), GFP_KERNEL);
-	if (!ceudev->subdevs)
-		return -ENOMEM;
-
-	ceudev->sd = NULL;
-	ceudev->sd_index = 0;
-	ceudev->num_sd = 0;
-
-	return 0;
-}
-
 /*
  * ceu_parse_platform_data() - Initialize async_subdevices using platform
  *			       device provided data.
@@ -1495,6 +1473,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
 				   const struct ceu_platform_data *pdata)
 {
 	const struct ceu_async_subdev *async_sd;
+	struct v4l2_async_subdev *asd;
 	struct ceu_subdev *ceu_sd;
 	unsigned int i;
 	int ret;
@@ -1502,29 +1481,26 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
 	if (pdata->num_subdevs == 0)
 		return -ENODEV;
 
-	ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs);
-	if (ret)
-		return ret;
+	ceudev->sd = NULL;
+	ceudev->sd_index = 0;
+	ceudev->num_sd = 0;
 
 	for (i = 0; i < pdata->num_subdevs; i++) {
 
 		/* Setup the ceu subdevice and the async subdevice. */
 		async_sd = &pdata->subdevs[i];
-		ceu_sd = &ceudev->subdevs[i];
-
-		INIT_LIST_HEAD(&ceu_sd->asd.list);
-
-		ceu_sd->mbus_flags	= async_sd->flags;
-		ceu_sd->asd.match_type	= V4L2_ASYNC_MATCH_I2C;
-		ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
-		ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
-
-		ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
-						     &ceu_sd->asd);
-		if (ret) {
+		asd = v4l2_async_notifier_add_i2c_subdev(&ceudev->notifier,
+				async_sd->i2c_adapter_id,
+				async_sd->i2c_address,
+				sizeof(*ceu_sd));
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			v4l2_async_notifier_cleanup(&ceudev->notifier);
 			return ret;
 		}
+		ceu_sd = to_ceu_subdev(asd);
+		ceu_sd->mbus_flags = async_sd->flags;
+		ceudev->subdevs[i] = ceu_sd;
 	}
 
 	return pdata->num_subdevs;
@@ -1536,7 +1512,8 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
 static int ceu_parse_dt(struct ceu_device *ceudev)
 {
 	struct device_node *of = ceudev->dev->of_node;
-	struct device_node *ep, *remote;
+	struct device_node *ep;
+	struct v4l2_async_subdev *asd;
 	struct ceu_subdev *ceu_sd;
 	unsigned int i;
 	int num_ep;
@@ -1546,9 +1523,9 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
 	if (!num_ep)
 		return -ENODEV;
 
-	ret = ceu_init_async_subdevs(ceudev, num_ep);
-	if (ret)
-		return ret;
+	ceudev->sd = NULL;
+	ceudev->sd_index = 0;
+	ceudev->num_sd = 0;
 
 	for (i = 0; i < num_ep; i++) {
 		struct v4l2_fwnode_endpoint fw_ep = {
@@ -1578,20 +1555,16 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
 		}
 
 		/* Setup the ceu subdevice and the async subdevice. */
-		ceu_sd = &ceudev->subdevs[i];
-		INIT_LIST_HEAD(&ceu_sd->asd.list);
-
-		remote = of_graph_get_remote_port_parent(ep);
-		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
-		ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-		ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
-
-		ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
-						     &ceu_sd->asd);
-		if (ret) {
-			of_node_put(remote);
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+				&ceudev->notifier, of_fwnode_handle(ep),
+				sizeof(*ceu_sd));
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			goto error_cleanup;
 		}
+		ceu_sd = to_ceu_subdev(asd);
+		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
+		ceudev->subdevs[i] = ceu_sd;
 
 		of_node_put(ep);
 	}
-- 
2.29.2


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

* [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (2 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 16:07   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
which handles the needed setup, instead of open-coding it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/exynos4-is/media-dev.c | 25 +++++++++----------
 drivers/media/platform/exynos4-is/media-dev.h |  2 +-
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index e636c33e847b..196166a9a4e5 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -401,6 +401,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 	int index = fmd->num_sensors;
 	struct fimc_source_info *pd = &fmd->sensor[index].pdata;
 	struct device_node *rem, *np;
+	struct v4l2_async_subdev *asd;
 	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
 	int ret;
 
@@ -418,7 +419,6 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 	pd->mux_id = (endpoint.base.port - 1) & 0x1;
 
 	rem = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
 	if (rem == NULL) {
 		v4l2_info(&fmd->v4l2_dev, "Remote device at %pOF not found\n",
 							ep);
@@ -450,6 +450,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 	 * checking parent's node name.
 	 */
 	np = of_get_parent(rem);
+	of_node_put(rem);
 
 	if (of_node_name_eq(np, "i2c-isp"))
 		pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
@@ -457,21 +458,18 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
 		pd->fimc_bus_type = pd->sensor_bus_type;
 	of_node_put(np);
 
-	if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {
-		of_node_put(rem);
+	if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
 		return -EINVAL;
-	}
 
-	fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+		&fmd->subdev_notifier, of_fwnode_handle(ep), sizeof(*asd));
 
-	ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier,
-					     &fmd->sensor[index].asd);
-	if (ret) {
-		of_node_put(rem);
-		return ret;
-	}
+	of_node_put(ep);
+
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
 
+	fmd->sensor[index].asd = asd;
 	fmd->num_sensors++;
 
 	return 0;
@@ -1381,7 +1379,8 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
 
 	/* Find platform data for this sensor subdev */
 	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
-		if (fmd->sensor[i].asd.match.fwnode ==
+		if (fmd->sensor[i].asd &&
+		    fmd->sensor[i].asd->match.fwnode ==
 		    of_fwnode_handle(subdev->dev->of_node))
 			si = &fmd->sensor[i];
 
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 9447fafe23c6..a3876d668ea6 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -83,7 +83,7 @@ struct fimc_camclk_info {
  */
 struct fimc_sensor_info {
 	struct fimc_source_info pdata;
-	struct v4l2_async_subdev asd;
+	struct v4l2_async_subdev *asd;
 	struct v4l2_subdev *subdev;
 	struct fimc_dev *host;
 };
-- 
2.29.2


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

* [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (3 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 16:23   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 06/13] media: atmel: " Ezequiel Garcia
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
which handles the needed setup, instead of open-coding it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/i2c/st-mipid02.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
index 003ba22334cd..9e04ff02257c 100644
--- a/drivers/media/i2c/st-mipid02.c
+++ b/drivers/media/i2c/st-mipid02.c
@@ -92,7 +92,6 @@ struct mipid02_dev {
 	u64 link_frequency;
 	struct v4l2_fwnode_endpoint tx;
 	/* remote source */
-	struct v4l2_async_subdev asd;
 	struct v4l2_async_notifier notifier;
 	struct v4l2_subdev *s_subdev;
 	/* registers */
@@ -844,6 +843,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 {
 	struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
 	struct i2c_client *client = bridge->i2c_client;
+	struct v4l2_async_subdev *asd;
 	struct device_node *ep_node;
 	int ret;
 
@@ -875,17 +875,17 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
 	bridge->rx = ep;
 
 	/* register async notifier so we get noticed when sensor is connected */
-	bridge->asd.match.fwnode =
-		fwnode_graph_get_remote_port_parent(of_fwnode_handle(ep_node));
-	bridge->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
+	v4l2_async_notifier_init(&bridge->notifier);
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+					&bridge->notifier,
+					of_fwnode_handle(ep_node),
+					sizeof(*asd));
 	of_node_put(ep_node);
 
-	v4l2_async_notifier_init(&bridge->notifier);
-	ret = v4l2_async_notifier_add_subdev(&bridge->notifier, &bridge->asd);
-	if (ret) {
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
 		dev_err(&client->dev, "fail to register asd to notifier %d",
 			ret);
-		fwnode_handle_put(bridge->asd.match.fwnode);
 		return ret;
 	}
 	bridge->notifier.ops = &mipid02_notifier_ops;
-- 
2.29.2


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

* [PATCH 06/13] media: atmel: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (4 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 17:21   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 07/13] media: cdns-csi2rx: " Ezequiel Garcia
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/atmel/atmel-isc.h      |  1 +
 drivers/media/platform/atmel/atmel-isi.c      | 46 ++++++-------------
 .../media/platform/atmel/atmel-sama5d2-isc.c  | 44 ++++++------------
 3 files changed, 29 insertions(+), 62 deletions(-)

diff --git a/drivers/media/platform/atmel/atmel-isc.h b/drivers/media/platform/atmel/atmel-isc.h
index 24b784b893d6..fab8eca58d93 100644
--- a/drivers/media/platform/atmel/atmel-isc.h
+++ b/drivers/media/platform/atmel/atmel-isc.h
@@ -41,6 +41,7 @@ struct isc_buffer {
 struct isc_subdev_entity {
 	struct v4l2_subdev		*sd;
 	struct v4l2_async_subdev	*asd;
+	struct device_node		*epn;
 	struct v4l2_async_notifier      notifier;
 
 	u32 pfe_cfg0;
diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c
index d74aa73f26be..c1a6dd7af002 100644
--- a/drivers/media/platform/atmel/atmel-isi.c
+++ b/drivers/media/platform/atmel/atmel-isi.c
@@ -70,7 +70,6 @@ struct frame_buffer {
 struct isi_graph_entity {
 	struct device_node *node;
 
-	struct v4l2_async_subdev asd;
 	struct v4l2_subdev *subdev;
 };
 
@@ -1136,45 +1135,26 @@ static const struct v4l2_async_notifier_operations isi_graph_notify_ops = {
 	.complete = isi_graph_notify_complete,
 };
 
-static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node)
-{
-	struct device_node *ep = NULL;
-	struct device_node *remote;
-
-	ep = of_graph_get_next_endpoint(node, ep);
-	if (!ep)
-		return -EINVAL;
-
-	remote = of_graph_get_remote_port_parent(ep);
-	of_node_put(ep);
-	if (!remote)
-		return -EINVAL;
-
-	/* Remote node to connect */
-	isi->entity.node = remote;
-	isi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	isi->entity.asd.match.fwnode = of_fwnode_handle(remote);
-	return 0;
-}
-
 static int isi_graph_init(struct atmel_isi *isi)
 {
+	struct v4l2_async_subdev *asd;
+	struct device_node *ep;
 	int ret;
 
-	/* Parse the graph to extract a list of subdevice DT nodes. */
-	ret = isi_graph_parse(isi, isi->dev->of_node);
-	if (ret < 0) {
-		dev_err(isi->dev, "Graph parsing failed\n");
-		return ret;
-	}
+	ep = of_graph_get_next_endpoint(isi->dev->of_node, NULL);
+	if (!ep)
+		return -EINVAL;
 
 	v4l2_async_notifier_init(&isi->notifier);
 
-	ret = v4l2_async_notifier_add_subdev(&isi->notifier, &isi->entity.asd);
-	if (ret) {
-		of_node_put(isi->entity.node);
-		return ret;
-	}
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+						&isi->notifier,
+						of_fwnode_handle(ep),
+						sizeof(*asd));
+	of_node_put(ep);
+
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
 
 	isi->notifier.ops = &isi_graph_notify_ops;
 
diff --git a/drivers/media/platform/atmel/atmel-sama5d2-isc.c b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
index a3304f49e499..9ee2cd194f93 100644
--- a/drivers/media/platform/atmel/atmel-sama5d2-isc.c
+++ b/drivers/media/platform/atmel/atmel-sama5d2-isc.c
@@ -57,7 +57,7 @@
 static int isc_parse_dt(struct device *dev, struct isc_device *isc)
 {
 	struct device_node *np = dev->of_node;
-	struct device_node *epn = NULL, *rem;
+	struct device_node *epn = NULL;
 	struct isc_subdev_entity *subdev_entity;
 	unsigned int flags;
 	int ret;
@@ -71,17 +71,9 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
 		if (!epn)
 			return 0;
 
-		rem = of_graph_get_remote_port_parent(epn);
-		if (!rem) {
-			dev_notice(dev, "Remote device at %pOF not found\n",
-				   epn);
-			continue;
-		}
-
 		ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(epn),
 						 &v4l2_epn);
 		if (ret) {
-			of_node_put(rem);
 			ret = -EINVAL;
 			dev_err(dev, "Could not parse the endpoint\n");
 			break;
@@ -90,21 +82,10 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
 		subdev_entity = devm_kzalloc(dev, sizeof(*subdev_entity),
 					     GFP_KERNEL);
 		if (!subdev_entity) {
-			of_node_put(rem);
-			ret = -ENOMEM;
-			break;
-		}
-
-		/* asd will be freed by the subsystem once it's added to the
-		 * notifier list
-		 */
-		subdev_entity->asd = kzalloc(sizeof(*subdev_entity->asd),
-					     GFP_KERNEL);
-		if (!subdev_entity->asd) {
-			of_node_put(rem);
 			ret = -ENOMEM;
 			break;
 		}
+		subdev_entity->epn = epn;
 
 		flags = v4l2_epn.bus.parallel.flags;
 
@@ -121,12 +102,10 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc)
 			subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC |
 					ISC_PFE_CFG0_CCIR656;
 
-		subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-		subdev_entity->asd->match.fwnode = of_fwnode_handle(rem);
 		list_add_tail(&subdev_entity->list, &isc->subdev_entities);
 	}
-
 	of_node_put(epn);
+
 	return ret;
 }
 
@@ -228,13 +207,20 @@ static int atmel_isc_probe(struct platform_device *pdev)
 	}
 
 	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
+		struct v4l2_async_subdev *asd;
+
 		v4l2_async_notifier_init(&subdev_entity->notifier);
 
-		ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier,
-						     subdev_entity->asd);
-		if (ret) {
-			fwnode_handle_put(subdev_entity->asd->match.fwnode);
-			kfree(subdev_entity->asd);
+		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+					&subdev_entity->notifier,
+					of_fwnode_handle(subdev_entity->epn),
+					sizeof(*asd));
+
+		of_node_put(subdev_entity->epn);
+		subdev_entity->epn = NULL;
+
+		if (IS_ERR(asd)) {
+			ret = PTR_ERR(asd);
 			goto cleanup_subdev;
 		}
 
-- 
2.29.2


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

* [PATCH 07/13] media: cdns-csi2rx: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (5 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 06/13] media: atmel: " Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 17:23   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
which handles the needed setup, instead of open-coding it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/cadence/cdns-csi2rx.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
index be9ec59774d6..7d299cacef8c 100644
--- a/drivers/media/platform/cadence/cdns-csi2rx.c
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -81,7 +81,6 @@ struct csi2rx_priv {
 	struct media_pad		pads[CSI2RX_PAD_MAX];
 
 	/* Remote source */
-	struct v4l2_async_subdev	asd;
 	struct v4l2_subdev		*source_subdev;
 	int				source_pad;
 };
@@ -362,6 +361,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx,
 static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 {
 	struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
+	struct v4l2_async_subdev *asd;
 	struct fwnode_handle *fwh;
 	struct device_node *ep;
 	int ret;
@@ -395,17 +395,13 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
 		return -EINVAL;
 	}
 
-	csi2rx->asd.match.fwnode = fwnode_graph_get_remote_port_parent(fwh);
-	csi2rx->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	of_node_put(ep);
-
 	v4l2_async_notifier_init(&csi2rx->notifier);
 
-	ret = v4l2_async_notifier_add_subdev(&csi2rx->notifier, &csi2rx->asd);
-	if (ret) {
-		fwnode_handle_put(csi2rx->asd.match.fwnode);
-		return ret;
-	}
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi2rx->notifier,
+							   fwh, sizeof(*asd));
+	of_node_put(ep);
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
 
 	csi2rx->notifier.ops = &csi2rx_notifier_ops;
 
-- 
2.29.2


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

* [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (6 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 07/13] media: cdns-csi2rx: " Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-16 17:36   ` Jacopo Mondi
  2021-01-12 13:23 ` [PATCH 09/13] media: pxa-camera: " Ezequiel Garcia
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev,
removing some boilerplate code while at it.

Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
the needed setup, instead of open-coding it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/marvell-ccic/cafe-driver.c | 14 +++++++++++---
 drivers/media/platform/marvell-ccic/mcam-core.c   | 10 ----------
 drivers/media/platform/marvell-ccic/mcam-core.h   |  1 -
 drivers/media/platform/marvell-ccic/mmp-driver.c  | 11 ++++++++---
 4 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
index 00f623d62c96..91d65f71be96 100644
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -489,6 +489,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 	int ret;
 	struct cafe_camera *cam;
 	struct mcam_camera *mcam;
+	struct v4l2_async_subdev *asd;
 
 	/*
 	 * Start putting together one of our big camera structures.
@@ -546,9 +547,16 @@ static int cafe_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto out_pdown;
 
-	mcam->asd.match_type = V4L2_ASYNC_MATCH_I2C;
-	mcam->asd.match.i2c.adapter_id = i2c_adapter_id(cam->i2c_adapter);
-	mcam->asd.match.i2c.address = ov7670_info.addr;
+	v4l2_async_notifier_init(&mcam->notifier);
+
+	asd = v4l2_async_notifier_add_i2c_subdev(&mcam->notifier,
+					i2c_adapter_id(cam->i2c_adapter),
+					ov7670_info.addr,
+					sizeof(*asd));
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
+		goto out_smbus_shutdown;
+	}
 
 	ret = mccic_register(mcam);
 	if (ret)
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index c012fd2e1d29..153277e4fe80 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1866,16 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
 	cam->pix_format = mcam_def_pix_format;
 	cam->mbus_code = mcam_def_mbus_code;
 
-	/*
-	 * Register sensor notifier.
-	 */
-	v4l2_async_notifier_init(&cam->notifier);
-	ret = v4l2_async_notifier_add_subdev(&cam->notifier, &cam->asd);
-	if (ret) {
-		cam_warn(cam, "failed to add subdev to a notifier");
-		goto out;
-	}
-
 	cam->notifier.ops = &mccic_notify_ops;
 	ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier);
 	if (ret < 0) {
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index b55545822fd2..f324d808d737 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -151,7 +151,6 @@ struct mcam_camera {
 	 */
 	struct video_device vdev;
 	struct v4l2_async_notifier notifier;
-	struct v4l2_async_subdev asd;
 	struct v4l2_subdev *sensor;
 
 	/* Videobuf2 stuff */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 032fdddbbecc..40d9fc4a731a 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -180,6 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct fwnode_handle *ep;
 	struct mmp_camera_platform_data *pdata;
+	struct v4l2_async_subdev *asd;
 	int ret;
 
 	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
@@ -238,10 +239,15 @@ static int mmpcam_probe(struct platform_device *pdev)
 	if (!ep)
 		return -ENODEV;
 
-	mcam->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	mcam->asd.match.fwnode = fwnode_graph_get_remote_port_parent(ep);
+	v4l2_async_notifier_init(&mcam->notifier);
 
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&mcam->notifier,
+							   ep, sizeof(*asd));
 	fwnode_handle_put(ep);
+	if (IS_ERR(asd)) {
+		ret = PTR_ERR(asd);
+		goto out;
+	}
 
 	/*
 	 * Register the device with the core.
@@ -278,7 +284,6 @@ static int mmpcam_probe(struct platform_device *pdev)
 	pm_runtime_enable(&pdev->dev);
 	return 0;
 out:
-	fwnode_handle_put(mcam->asd.match.fwnode);
 	mccic_shutdown(mcam);
 
 	return ret;
-- 
2.29.2


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

* [PATCH 09/13] media: pxa-camera: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (7 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 10/13] media: davinci: vpif_display: Remove unused v4l2-async code Ezequiel Garcia
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The use of v4l2_async_notifier_add_subdev is discouraged.
Drivers are instead encouraged to use a helper such as
v4l2_async_notifier_add_fwnode_remote_subdev.

This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
should get a kmalloc'ed struct v4l2_async_subdev.

Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
the needed setup, instead of open-coding it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/pxa_camera.c | 53 ++++++++++++-----------------
 1 file changed, 21 insertions(+), 32 deletions(-)

diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index 8cfa39108162..6d39a0aca99c 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -655,8 +655,6 @@ struct pxa_camera_dev {
 	const struct pxa_camera_format_xlate *current_fmt;
 	struct v4l2_pix_format	current_pix;
 
-	struct v4l2_async_subdev asd;
-
 	/*
 	 * PXA27x is only supposed to handle one camera on its Quick Capture
 	 * interface. If anyone ever builds hardware to enable more than
@@ -2189,11 +2187,11 @@ static int pxa_camera_resume(struct device *dev)
 }
 
 static int pxa_camera_pdata_from_dt(struct device *dev,
-				    struct pxa_camera_dev *pcdev,
-				    struct v4l2_async_subdev *asd)
+				    struct pxa_camera_dev *pcdev)
 {
 	u32 mclk_rate;
-	struct device_node *remote, *np = dev->of_node;
+	struct v4l2_async_subdev *asd;
+	struct device_node *np = dev->of_node;
 	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
 	int err = of_property_read_u32(np, "clock-frequency",
 				       &mclk_rate);
@@ -2245,13 +2243,12 @@ static int pxa_camera_pdata_from_dt(struct device *dev,
 	if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 		pcdev->platform_flags |= PXA_CAMERA_PCLK_EN;
 
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	remote = of_graph_get_remote_port_parent(np);
-	if (remote)
-		asd->match.fwnode = of_fwnode_handle(remote);
-	else
-		dev_notice(dev, "no remote for %pOF\n", np);
-
+	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+				&pcdev->notifier,
+				of_fwnode_handle(np),
+				sizeof(*asd));
+	if (IS_ERR(asd))
+		err = PTR_ERR(asd);
 out:
 	of_node_put(np);
 
@@ -2286,18 +2283,23 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	if (IS_ERR(pcdev->clk))
 		return PTR_ERR(pcdev->clk);
 
+	v4l2_async_notifier_init(&pcdev->notifier);
 	pcdev->res = res;
-
 	pcdev->pdata = pdev->dev.platform_data;
 	if (pcdev->pdata) {
+		struct v4l2_async_subdev *asd;
+
 		pcdev->platform_flags = pcdev->pdata->flags;
 		pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
-		pcdev->asd.match_type = V4L2_ASYNC_MATCH_I2C;
-		pcdev->asd.match.i2c.adapter_id =
-			pcdev->pdata->sensor_i2c_adapter_id;
-		pcdev->asd.match.i2c.address = pcdev->pdata->sensor_i2c_address;
+		asd = v4l2_async_notifier_add_i2c_subdev(
+				&pcdev->notifier,
+				pcdev->pdata->sensor_i2c_adapter_id,
+				pcdev->pdata->sensor_i2c_address,
+				sizeof(*asd));
+		if (IS_ERR(asd))
+			err = PTR_ERR(asd);
 	} else if (pdev->dev.of_node) {
-		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd);
+		err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev);
 	} else {
 		return -ENODEV;
 	}
@@ -2389,23 +2391,11 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	if (err)
 		goto exit_deactivate;
 
-	v4l2_async_notifier_init(&pcdev->notifier);
-
-	err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd);
-	if (err) {
-		fwnode_handle_put(pcdev->asd.match.fwnode);
-		goto exit_free_v4l2dev;
-	}
-
-	pcdev->notifier.ops = &pxa_camera_sensor_ops;
-
-	if (!of_have_populated_dt())
-		pcdev->asd.match_type = V4L2_ASYNC_MATCH_I2C;
-
 	err = pxa_camera_init_videobuf2(pcdev);
 	if (err)
 		goto exit_notifier_cleanup;
 
+	pcdev->notifier.ops = &pxa_camera_sensor_ops;
 	err = v4l2_async_notifier_register(&pcdev->v4l2_dev, &pcdev->notifier);
 	if (err)
 		goto exit_notifier_cleanup;
@@ -2413,7 +2403,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
 	return 0;
 exit_notifier_cleanup:
 	v4l2_async_notifier_cleanup(&pcdev->notifier);
-exit_free_v4l2dev:
 	v4l2_device_unregister(&pcdev->v4l2_dev);
 exit_deactivate:
 	pxa_camera_deactivate(pcdev);
-- 
2.29.2


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

* [PATCH 10/13] media: davinci: vpif_display: Remove unused v4l2-async code
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (8 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 09/13] media: pxa-camera: " Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention Ezequiel Garcia
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

There are no users for vpif_display_config.asd_sizes
and vpif_display_config.asd members, which means the v4l2-async
subdevices aren't being defined anywhere.

Remove the v4l2-async, leaving only the synchronous setup.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/platform/davinci/vpif_display.c | 86 ++++---------------
 drivers/media/platform/davinci/vpif_display.h |  1 -
 include/media/davinci/vpif_types.h            |  2 -
 3 files changed, 15 insertions(+), 74 deletions(-)

diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 46afc029138f..e5f61d9b221d 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1117,23 +1117,6 @@ static void free_vpif_objs(void)
 		kfree(vpif_obj.dev[i]);
 }
 
-static int vpif_async_bound(struct v4l2_async_notifier *notifier,
-			    struct v4l2_subdev *subdev,
-			    struct v4l2_async_subdev *asd)
-{
-	int i;
-
-	for (i = 0; i < vpif_obj.config->subdev_count; i++)
-		if (!strcmp(vpif_obj.config->subdevinfo[i].name,
-			    subdev->name)) {
-			vpif_obj.sd[i] = subdev;
-			vpif_obj.sd[i]->grp_id = 1 << i;
-			return 0;
-		}
-
-	return -EINVAL;
-}
-
 static int vpif_probe_complete(void)
 {
 	struct common_obj *common;
@@ -1230,16 +1213,6 @@ static int vpif_probe_complete(void)
 	return err;
 }
 
-static int vpif_async_complete(struct v4l2_async_notifier *notifier)
-{
-	return vpif_probe_complete();
-}
-
-static const struct v4l2_async_notifier_operations vpif_async_ops = {
-	.bound = vpif_async_bound,
-	.complete = vpif_async_complete,
-};
-
 /*
  * vpif_probe: This function creates device entries by register itself to the
  * V4L2 driver and initializes fields of each channel objects
@@ -1294,52 +1267,28 @@ static __init int vpif_probe(struct platform_device *pdev)
 		goto vpif_unregister;
 	}
 
-	v4l2_async_notifier_init(&vpif_obj.notifier);
-
-	if (!vpif_obj.config->asd_sizes) {
-		i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id);
-		for (i = 0; i < subdev_count; i++) {
-			vpif_obj.sd[i] =
-				v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-							  i2c_adap,
-							  &subdevdata[i].
-							  board_info,
-							  NULL);
-			if (!vpif_obj.sd[i]) {
-				vpif_err("Error registering v4l2 subdevice\n");
-				err = -ENODEV;
-				goto probe_subdev_out;
-			}
-
-			if (vpif_obj.sd[i])
-				vpif_obj.sd[i]->grp_id = 1 << i;
-		}
-		err = vpif_probe_complete();
-		if (err) {
+	i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id);
+	for (i = 0; i < subdev_count; i++) {
+		vpif_obj.sd[i] =
+			v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+						  i2c_adap,
+						  &subdevdata[i].board_info,
+						  NULL);
+		if (!vpif_obj.sd[i]) {
+			vpif_err("Error registering v4l2 subdevice\n");
+			err = -ENODEV;
 			goto probe_subdev_out;
 		}
-	} else {
-		for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) {
-			err = v4l2_async_notifier_add_subdev(
-				&vpif_obj.notifier, vpif_obj.config->asd[i]);
-			if (err)
-				goto probe_cleanup;
-		}
 
-		vpif_obj.notifier.ops = &vpif_async_ops;
-		err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
-						   &vpif_obj.notifier);
-		if (err) {
-			vpif_err("Error registering async notifier\n");
-			err = -EINVAL;
-			goto probe_cleanup;
-		}
+		if (vpif_obj.sd[i])
+			vpif_obj.sd[i]->grp_id = 1 << i;
 	}
+	err = vpif_probe_complete();
+	if (err)
+		goto probe_subdev_out;
 
 	return 0;
 
-probe_cleanup:
-	v4l2_async_notifier_cleanup(&vpif_obj.notifier);
 probe_subdev_out:
 	kfree(vpif_obj.sd);
 vpif_unregister:
@@ -1358,11 +1307,6 @@ static int vpif_remove(struct platform_device *device)
 	struct channel_obj *ch;
 	int i;
 
-	if (vpif_obj.config->asd_sizes) {
-		v4l2_async_notifier_unregister(&vpif_obj.notifier);
-		v4l2_async_notifier_cleanup(&vpif_obj.notifier);
-	}
-
 	v4l2_device_unregister(&vpif_obj.v4l2_dev);
 
 	kfree(vpif_obj.sd);
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index f731a65eefd6..f98062e79167 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -118,7 +118,6 @@ struct vpif_device {
 	struct v4l2_device v4l2_dev;
 	struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
 	struct v4l2_subdev **sd;
-	struct v4l2_async_notifier notifier;
 	struct vpif_display_config *config;
 };
 
diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h
index 8439e46fb993..d03e5c54347a 100644
--- a/include/media/davinci/vpif_types.h
+++ b/include/media/davinci/vpif_types.h
@@ -48,8 +48,6 @@ struct vpif_display_config {
 	int i2c_adapter_id;
 	struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
 	const char *card_name;
-	struct v4l2_async_subdev **asd;	/* Flat array, arranged in groups */
-	int *asd_sizes;		/* 0-terminated array of asd group sizes */
 };
 
 struct vpif_input {
-- 
2.29.2


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

* [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (9 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 10/13] media: davinci: vpif_display: Remove unused v4l2-async code Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-14  2:14   ` Laurent Pinchart
  2021-01-12 13:23 ` [PATCH 12/13] media: Clarify v4l2-async subdevice addition API Ezequiel Garcia
  2021-01-12 13:23 ` [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev Ezequiel Garcia
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

The v4l2_async_notifier_cleanup documentation mentions
v4l2_fwnode_reference_parse_sensor_common, which doesn't exist.
Drop it.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 include/media/v4l2-async.h | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 76be1e01222e..2429ac55be1c 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -290,9 +290,8 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
  * sub-devices allocated for the purposes of the notifier but not the notifier
  * itself. The user is responsible for calling this function to clean up the
  * notifier after calling
- * @v4l2_async_notifier_add_subdev,
- * @v4l2_async_notifier_parse_fwnode_endpoints or
- * @v4l2_fwnode_reference_parse_sensor_common.
+ * @v4l2_async_notifier_add_subdev or
+ * @v4l2_async_notifier_parse_fwnode_endpoints.
  *
  * There is no harm from calling v4l2_async_notifier_cleanup in other
  * cases as long as its memory has been zeroed after it has been
-- 
2.29.2


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

* [PATCH 12/13] media: Clarify v4l2-async subdevice addition API
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (10 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-14  2:21   ` Laurent Pinchart
  2021-01-12 13:23 ` [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev Ezequiel Garcia
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

Now that most users of v4l2_async_notifier_add_subdev have
been converted, let's fix the documentation so it's more clear
how the v4l2-async API should be used.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 .../driver-api/media/v4l2-subdev.rst          | 38 ++++++++++++++++---
 include/media/v4l2-async.h                    | 12 +++++-
 2 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
index bb5b1a7cdfd9..5ddf9de4fcf7 100644
--- a/Documentation/driver-api/media/v4l2-subdev.rst
+++ b/Documentation/driver-api/media/v4l2-subdev.rst
@@ -204,11 +204,39 @@ Before registering the notifier, bridge drivers must do two things:
 first, the notifier must be initialized using the
 :c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
 begin to form a list of subdevice descriptors that the bridge device
-needs for its operation. Subdevice descriptors are added to the notifier
-using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
-takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
-and a pointer to the subdevice descripter, which is of type struct
-:c:type:`v4l2_async_subdev`.
+needs for its operation. Several functions are available, to
+add subdevice descriptors to a notifier, depending on the type of device:
+:c:func:`v4l2_async_notifier_add_devname_subdev`,
+:c:func:`v4l2_async_notifier_add_fwnode_subdev` or
+:c:func:`v4l2_async_notifier_add_i2c_subdev`.
+
+These functions allocate a subdevice descriptor, which is of
+type struct :c:type:`v4l2_async_subdev`, and take a size argument
+which can be used to embed the descriptor in a driver-specific
+async subdevice struct. The &struct :c:type:`v4l2_async_subdev`
+shall be the first member of this struct:
+
+.. code-block:: c
+
+	struct my_async_subdev {
+		struct v4l2_async_subdev asd;
+		...
+	};
+
+	struct my_async_subdev *my_asd;
+	struct v4l2_async_subdev *asd;
+	struct fwnode_handle *ep;
+
+	...
+
+	asd = v4l2_async_notifier_add_fwnode_subdev(
+			&notifier, ep, sizeof(*my_asd));
+	fwnode_handle_put(ep);
+
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
+
+	my_asd = container_of(asd, struct my_async_subdev, asd);
 
 The V4L2 core will then use these descriptors to match asynchronously
 registered subdevices to them. If a match is detected the ``.bound()``
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 2429ac55be1c..1278f98355a7 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -151,7 +151,12 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
  * @notifier: pointer to &struct v4l2_async_notifier
  *
  * This function initializes the notifier @asd_list. It must be called
- * before the first call to @v4l2_async_notifier_add_subdev.
+ * before adding a subdevice to a notifier, using one of:
+ * @v4l2_async_notifier_add_fwnode_subdev,
+ * @v4l2_async_notifier_add_fwnode_remote_subdev,
+ * @v4l2_async_notifier_add_i2c_subdev,
+ * @v4l2_async_notifier_add_devname_subdev or
+ * @v4l2_async_notifier_parse_fwnode_endpoints.
  */
 void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
 
@@ -290,7 +295,10 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
  * sub-devices allocated for the purposes of the notifier but not the notifier
  * itself. The user is responsible for calling this function to clean up the
  * notifier after calling
- * @v4l2_async_notifier_add_subdev or
+ * @v4l2_async_notifier_add_fwnode_subdev,
+ * @v4l2_async_notifier_add_fwnode_remote_subdev,
+ * @v4l2_async_notifier_add_i2c_subdev,
+ * @v4l2_async_notifier_add_devname_subdev or
  * @v4l2_async_notifier_parse_fwnode_endpoints.
  *
  * There is no harm from calling v4l2_async_notifier_cleanup in other
-- 
2.29.2


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

* [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev
  2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
                   ` (11 preceding siblings ...)
  2021-01-12 13:23 ` [PATCH 12/13] media: Clarify v4l2-async subdevice addition API Ezequiel Garcia
@ 2021-01-12 13:23 ` Ezequiel Garcia
  2021-01-14  2:27   ` Laurent Pinchart
  12 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-12 13:23 UTC (permalink / raw)
  To: linux-media, Hans Verkuil
  Cc: kernel, Laurent Pinchart, Sakari Ailus, Ezequiel Garcia

Most -if not all- use-cases are expected to be covered by one of:
v4l2_async_notifier_add_fwnode_subdev,
v4l2_async_notifier_add_fwnode_remote_subdev,
v4l2_async_notifier_add_i2c_subdev or
v4l2_async_notifier_add_devname_subdev.

We'd like to discourage drivers from using v4l2_async_notifier_add_subdev,
so rename it as __v4l2_async_notifier_add_subdev. This is
typically a good hint for drivers to avoid using the function.

Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
---
 drivers/media/v4l2-core/v4l2-async.c  | 10 +++++-----
 drivers/media/v4l2-core/v4l2-fwnode.c |  2 +-
 include/media/v4l2-async.h            | 10 ++++++++--
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index b325bacddff4..e8e690280922 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -630,7 +630,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
 }
 EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
 
-int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd)
 {
 	int ret;
@@ -647,7 +647,7 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 	mutex_unlock(&list_lock);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
+EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_subdev);
 
 struct v4l2_async_subdev *
 v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
@@ -664,7 +664,7 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
 	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
 	asd->match.fwnode = fwnode_handle_get(fwnode);
 
-	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
 	if (ret) {
 		fwnode_handle_put(fwnode);
 		kfree(asd);
@@ -714,7 +714,7 @@ v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
 	asd->match.i2c.adapter_id = adapter_id;
 	asd->match.i2c.address = address;
 
-	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
 	if (ret) {
 		kfree(asd);
 		return ERR_PTR(ret);
@@ -739,7 +739,7 @@ v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
 	asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
 	asd->match.device_name = device_name;
 
-	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
 	if (ret) {
 		kfree(asd);
 		return ERR_PTR(ret);
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 5353e37eb950..919fde20032e 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -833,7 +833,7 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
 	if (ret < 0)
 		goto out_err;
 
-	ret = v4l2_async_notifier_add_subdev(notifier, asd);
+	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
 	if (ret < 0) {
 		/* not an error if asd already exists */
 		if (ret == -EEXIST)
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 1278f98355a7..9cf83f1ecca6 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -161,17 +161,23 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
 void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
 
 /**
- * v4l2_async_notifier_add_subdev - Add an async subdev to the
+ * __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
  *
+ * \warning: Drivers should avoid using this function and instead use one of:
+ * @v4l2_async_notifier_add_fwnode_subdev,
+ * @v4l2_async_notifier_add_fwnode_remote_subdev,
+ * @v4l2_async_notifier_add_i2c_subdev or
+ * @v4l2_async_notifier_add_devname_subdev.
+ *
  * Call this function before registering a notifier to link the provided @asd to
  * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
  * it will be freed by the framework when the notifier is destroyed.
  */
-int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
+int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
 				   struct v4l2_async_subdev *asd);
 
 /**
-- 
2.29.2


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

* Re: [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-12 13:23 ` [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics Ezequiel Garcia
@ 2021-01-14  1:59   ` Laurent Pinchart
  2021-01-14 13:47     ` Sakari Ailus
  0 siblings, 1 reply; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-14  1:59 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

Thank you for the patch.

On Tue, Jan 12, 2021 at 10:23:27AM -0300, Ezequiel Garcia wrote:
> Change v4l2_async_notifier_add_fwnode_remote_subdev semantics
> so it allocates the struct v4l2_async_subdev pointer.
> 
> This makes the API consistent: the v4l2-async subdevice addition
> functions have now a unified usage model. This model is simpler,
> as it makes v4l2-async responsible for the allocation and release
> of the subdevice descriptor, and no longer something the driver
> has to worry about.
> 
> On the user side, the change makes the API simpler for the drivers
> to use and less error-prone.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/pci/intel/ipu3/ipu3-cio2.c      | 17 ++--
>  drivers/media/platform/omap3isp/isp.c         | 78 ++++++++-----------
>  .../platform/rockchip/rkisp1/rkisp1-dev.c     | 15 ++--
>  .../platform/sunxi/sun4i-csi/sun4i_csi.c      |  9 ++-
>  .../platform/sunxi/sun4i-csi/sun4i_csi.h      |  1 -
>  drivers/media/platform/video-mux.c            | 14 +---
>  drivers/media/v4l2-core/v4l2-async.c          | 24 +++---
>  drivers/staging/media/imx/imx-media-csi.c     | 14 +---
>  drivers/staging/media/imx/imx6-mipi-csi2.c    | 19 ++---
>  drivers/staging/media/imx/imx7-media-csi.c    | 16 ++--
>  drivers/staging/media/imx/imx7-mipi-csis.c    | 15 +---
>  include/media/v4l2-async.h                    | 15 ++--
>  12 files changed, 93 insertions(+), 144 deletions(-)
> 
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> index 36e354ecf71e..c1d42cbecbc1 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
> @@ -1467,7 +1467,8 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
>  		struct v4l2_fwnode_endpoint vep = {
>  			.bus_type = V4L2_MBUS_CSI2_DPHY
>  		};
> -		struct sensor_async_subdev *s_asd = NULL;
> +		struct sensor_async_subdev *s_asd;
> +		struct v4l2_async_subdev *asd;
>  		struct fwnode_handle *ep;
>  
>  		ep = fwnode_graph_get_endpoint_by_id(
> @@ -1481,27 +1482,23 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
>  		if (ret)
>  			goto err_parse;
>  
> -		s_asd = kzalloc(sizeof(*s_asd), GFP_KERNEL);
> -		if (!s_asd) {
> -			ret = -ENOMEM;
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +				&cio2->notifier, ep, sizeof(*s_asd));
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			goto err_parse;
>  		}
>  
> +		s_asd = container_of(asd, struct sensor_async_subdev, asd);
>  		s_asd->csi2.port = vep.base.port;
>  		s_asd->csi2.lanes = vep.bus.mipi_csi2.num_data_lanes;
>  
> -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -			&cio2->notifier, ep, &s_asd->asd);
> -		if (ret)
> -			goto err_parse;
> -
>  		fwnode_handle_put(ep);
>  
>  		continue;
>  
>  err_parse:
>  		fwnode_handle_put(ep);
> -		kfree(s_asd);
>  		return ret;
>  	}
>  
> diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
> index b1fc4518e275..51c35f42773f 100644
> --- a/drivers/media/platform/omap3isp/isp.c
> +++ b/drivers/media/platform/omap3isp/isp.c
> @@ -2126,21 +2126,6 @@ static void isp_parse_of_csi1_endpoint(struct device *dev,
>  	buscfg->bus.ccp2.crc = 1;
>  }
>  
> -static int isp_alloc_isd(struct isp_async_subdev **isd,
> -			 struct isp_bus_cfg **buscfg)
> -{
> -	struct isp_async_subdev *__isd;
> -
> -	__isd = kzalloc(sizeof(*__isd), GFP_KERNEL);
> -	if (!__isd)
> -		return -ENOMEM;
> -
> -	*isd = __isd;
> -	*buscfg = &__isd->bus;
> -
> -	return 0;
> -}
> -
>  static struct {
>  	u32 phy;
>  	u32 csi2_if;
> @@ -2156,7 +2141,7 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
>  {
>  	struct fwnode_handle *ep;
>  	struct isp_async_subdev *isd = NULL;
> -	struct isp_bus_cfg *buscfg;
> +	struct v4l2_async_subdev *asd;
>  	unsigned int i;
>  
>  	ep = fwnode_graph_get_endpoint_by_id(
> @@ -2174,20 +2159,15 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
>  		ret = v4l2_fwnode_endpoint_parse(ep, &vep);
>  
>  		if (!ret) {
> -			ret = isp_alloc_isd(&isd, &buscfg);
> -			if (ret)
> -				return ret;
> -		}
> -
> -		if (!ret) {
> -			isp_parse_of_parallel_endpoint(isp->dev, &vep, buscfg);
> -			ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -				&isp->notifier, ep, &isd->asd);
> +			asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +				&isp->notifier, ep, sizeof(*isd));
> +			if (!IS_ERR(asd)) {
> +				isd = container_of(asd, struct isp_async_subdev, asd);
> +				isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus);
> +			}
>  		}
>  
>  		fwnode_handle_put(ep);
> -		if (ret)
> -			kfree(isd);
>  	}
>  
>  	for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) {
> @@ -2206,15 +2186,8 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
>  		dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i,
>  			to_of_node(ep));
>  
> -		ret = isp_alloc_isd(&isd, &buscfg);
> -		if (ret)
> -			return ret;
> -
>  		ret = v4l2_fwnode_endpoint_parse(ep, &vep);
> -		if (!ret) {
> -			buscfg->interface = isp_bus_interfaces[i].csi2_if;
> -			isp_parse_of_csi2_endpoint(isp->dev, &vep, buscfg);
> -		} else if (ret == -ENXIO) {
> +		if (ret == -ENXIO) {
>  			vep = (struct v4l2_fwnode_endpoint)
>  				{ .bus_type = V4L2_MBUS_CSI1 };
>  			ret = v4l2_fwnode_endpoint_parse(ep, &vep);
> @@ -2224,21 +2197,34 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
>  					{ .bus_type = V4L2_MBUS_CCP2 };
>  				ret = v4l2_fwnode_endpoint_parse(ep, &vep);
>  			}
> -			if (!ret) {
> -				buscfg->interface =
> -					isp_bus_interfaces[i].csi1_if;
> -				isp_parse_of_csi1_endpoint(isp->dev, &vep,
> -							   buscfg);
> -			}
>  		}
>  
> -		if (!ret)
> -			ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -				&isp->notifier, ep, &isd->asd);
> +		if (!ret) {
> +			asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +				&isp->notifier, ep, sizeof(*isd));
> +
> +			if (!IS_ERR(asd)) {
> +				isd = container_of(asd, struct isp_async_subdev, asd);

I'd add a blank line here.

> +				switch (vep.bus_type) {
> +				case V4L2_MBUS_CSI2_DPHY:
> +					isd->bus.interface =
> +						isp_bus_interfaces[i].csi2_if;
> +					isp_parse_of_csi2_endpoint(isp->dev, &vep, &isd->bus);
> +					break;
> +				case V4L2_MBUS_CSI1:
> +				case V4L2_MBUS_CCP2:
> +					isd->bus.interface =
> +						isp_bus_interfaces[i].csi1_if;
> +					isp_parse_of_csi1_endpoint(isp->dev, &vep,
> +								   &isd->bus);
> +					break;
> +				default:
> +					break;
> +				}
> +			}
> +		}
>  
>  		fwnode_handle_put(ep);
> -		if (ret)
> -			kfree(isd);
>  	}
>  
>  	return 0;
> diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> index 68da1eed753d..235dcf0c4122 100644
> --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
>  			.bus_type = V4L2_MBUS_CSI2_DPHY
>  		};
>  		struct rkisp1_sensor_async *rk_asd = NULL;
> +		struct v4l2_async_subdev *asd;
>  		struct fwnode_handle *ep;
>  
>  		ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
> @@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
>  		if (ret)
>  			goto err_parse;
>  
> -		rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
> -		if (!rk_asd) {
> -			ret = -ENOMEM;
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> +							sizeof(*rk_asd));
> +		if (IS_ERR(asd))
>  			goto err_parse;
> -		}
>  
> +		rk_asd = container_of(asd, struct rkisp1_sensor_async, asd);

It could be nice to turn v4l2_async_notifier_add_fwnode_remote_subdev()
into a macro that would take the asd structure type, and cast the
result, to avoid container_of() in the caller. That can be done on top
of this series.

>  		rk_asd->mbus_type = vep.bus_type;
>  		rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;
>  		rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;
>  
> -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> -								   &rk_asd->asd);
> -		if (ret)
> -			goto err_parse;
> -
>  		dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n",
>  			vep.base.id, rk_asd->lanes);
>  
> @@ -289,7 +285,6 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
>  		continue;
>  err_parse:
>  		fwnode_handle_put(ep);
> -		kfree(rk_asd);
>  		v4l2_async_notifier_cleanup(ntf);
>  		return ret;
>  	}
> diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> index ec46cff80fdb..3f94b8c966f3 100644
> --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
> @@ -118,6 +118,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
>  	struct v4l2_fwnode_endpoint vep = {
>  		.bus_type = V4L2_MBUS_PARALLEL,
>  	};
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> @@ -134,10 +135,12 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
>  
>  	csi->bus = vep.bus.parallel;
>  
> -	ret = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
> -							   ep, &csi->asd);
> -	if (ret)
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
> +							   ep, sizeof(*asd));
> +	if (IS_ERR(asd)) {
> +		ret = PTR_ERR(asd);
>  		goto out;
> +	}
>  
>  	csi->notifier.ops = &sun4i_csi_notify_ops;
>  
> diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
> index 0f67ff652c2e..a5f61ee0ec4d 100644
> --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
> +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
> @@ -139,7 +139,6 @@ struct sun4i_csi {
>  	struct v4l2_mbus_framefmt	subdev_fmt;
>  
>  	/* V4L2 Async variables */
> -	struct v4l2_async_subdev	asd;
>  	struct v4l2_async_notifier	notifier;
>  	struct v4l2_subdev		*src_subdev;
>  	int				src_pad;
> diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
> index 53570250a25d..7b280dfca727 100644
> --- a/drivers/media/platform/video-mux.c
> +++ b/drivers/media/platform/video-mux.c
> @@ -370,19 +370,13 @@ static int video_mux_async_register(struct video_mux *vmux,
>  		if (!ep)
>  			continue;
>  
> -		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
> -		if (!asd) {
> -			fwnode_handle_put(ep);
> -			return -ENOMEM;
> -		}
> -
> -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -			&vmux->notifier, ep, asd);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +			&vmux->notifier, ep, sizeof(*asd));
>  
>  		fwnode_handle_put(ep);
>  
> -		if (ret) {
> -			kfree(asd);
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			/* OK if asd already exists */
>  			if (ret != -EEXIST)
>  				return ret;
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 32cd1ecced97..b325bacddff4 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -675,26 +675,26 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
>  
> -int
> +struct v4l2_async_subdev *
>  v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
>  					     struct fwnode_handle *endpoint,
> -					     struct v4l2_async_subdev *asd)
> +					     unsigned int asd_struct_size)
>  {
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *remote;
> -	int ret;
>  
>  	remote = fwnode_graph_get_remote_port_parent(endpoint);
>  	if (!remote)
> -		return -ENOTCONN;
> +		return ERR_PTR(ENOTCONN);
>  
> -	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	asd->match.fwnode = remote;
> -
> -	ret = v4l2_async_notifier_add_subdev(notif, asd);
> -	if (ret)
> -		fwnode_handle_put(remote);
> -
> -	return ret;
> +	asd = v4l2_async_notifier_add_fwnode_subdev(notif,
> +						    remote, asd_struct_size);

Maybe

	asd = v4l2_async_notifier_add_fwnode_subdev(notif, remote,
						    asd_struct_size);

?

> +	/*
> +	 * Calling v4l2_async_notifier_add_fwnode_subdev grabs a refcount,
> +	 * so drop then one we got in fwnode_graph_get_remote_port_parent.
> +	 */
> +	fwnode_handle_put(remote);
> +	return asd;
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev);
>  
> diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
> index db77fef07654..6344389e6afa 100644
> --- a/drivers/staging/media/imx/imx-media-csi.c
> +++ b/drivers/staging/media/imx/imx-media-csi.c
> @@ -1922,19 +1922,13 @@ static int imx_csi_async_register(struct csi_priv *priv)
>  					     port, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
>  	if (ep) {
> -		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
> -		if (!asd) {
> -			fwnode_handle_put(ep);
> -			return -ENOMEM;
> -		}
> -
> -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -			&priv->notifier, ep, asd);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +			&priv->notifier, ep, sizeof(*asd));
>  
>  		fwnode_handle_put(ep);
>  
> -		if (ret) {
> -			kfree(asd);
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			/* OK if asd already exists */
>  			if (ret != -EEXIST)
>  				return ret;
> diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
> index bf6a61dd34c2..807d0dcbd6fd 100644
> --- a/drivers/staging/media/imx/imx6-mipi-csi2.c
> +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
> @@ -636,7 +636,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
>  	struct v4l2_fwnode_endpoint vep = {
>  		.bus_type = V4L2_MBUS_CSI2_DPHY,
>  	};
> -	struct v4l2_async_subdev *asd = NULL;
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> @@ -656,19 +656,13 @@ static int csi2_async_register(struct csi2_dev *csi2)
>  	dev_dbg(csi2->dev, "data lanes: %d\n", vep.bus.mipi_csi2.num_data_lanes);
>  	dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags);
>  
> -	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
> -	if (!asd) {
> -		ret = -ENOMEM;
> -		goto err_parse;
> -	}
> -
> -	ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -		&csi2->notifier, ep, asd);
> -	if (ret)
> -		goto err_parse;
> -
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +		&csi2->notifier, ep, sizeof(*asd));
>  	fwnode_handle_put(ep);
>  
> +	if (IS_ERR(asd))
> +		return PTR_ERR(asd);
> +
>  	csi2->notifier.ops = &csi2_notify_ops;
>  
>  	ret = v4l2_async_subdev_notifier_register(&csi2->sd,
> @@ -680,7 +674,6 @@ static int csi2_async_register(struct csi2_dev *csi2)
>  
>  err_parse:
>  	fwnode_handle_put(ep);
> -	kfree(asd);
>  	return ret;
>  }
>  
> diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
> index a3f3df901704..4ea6e0bb274d 100644
> --- a/drivers/staging/media/imx/imx7-media-csi.c
> +++ b/drivers/staging/media/imx/imx7-media-csi.c
> @@ -1180,7 +1180,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
>  
>  static int imx7_csi_async_register(struct imx7_csi *csi)
>  {
> -	struct v4l2_async_subdev *asd = NULL;
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> @@ -1189,19 +1189,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
>  	ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
>  					     FWNODE_GRAPH_ENDPOINT_NEXT);
>  	if (ep) {
> -		asd = kzalloc(sizeof(*asd), GFP_KERNEL);
> -		if (!asd) {
> -			fwnode_handle_put(ep);
> -			return -ENOMEM;
> -		}
> -
> -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -			&csi->notifier, ep, asd);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +			&csi->notifier, ep, sizeof(*asd));
>  
>  		fwnode_handle_put(ep);
>  
> -		if (ret) {
> -			kfree(asd);
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			/* OK if asd already exists */
>  			if (ret != -EEXIST)
>  				return ret;
> diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
> index 7612993cc1d6..32d8e7a824d4 100644
> --- a/drivers/staging/media/imx/imx7-mipi-csis.c
> +++ b/drivers/staging/media/imx/imx7-mipi-csis.c
> @@ -1004,7 +1004,7 @@ static int mipi_csis_async_register(struct csi_state *state)
>  	struct v4l2_fwnode_endpoint vep = {
>  		.bus_type = V4L2_MBUS_CSI2_DPHY,
>  	};
> -	struct v4l2_async_subdev *asd = NULL;
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *ep;
>  	int ret;
>  
> @@ -1024,15 +1024,9 @@ static int mipi_csis_async_register(struct csi_state *state)
>  	dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
>  	dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
>  
> -	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
> -	if (!asd) {
> -		ret = -ENOMEM;
> -		goto err_parse;
> -	}
> -
> -	ret = v4l2_async_notifier_add_fwnode_remote_subdev(
> -		&state->notifier, ep, asd);
> -	if (ret)
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +		&state->notifier, ep, sizeof(*asd));
> +	if (IS_ERR(asd))
>  		goto err_parse;
>  
>  	fwnode_handle_put(ep);
> @@ -1048,7 +1042,6 @@ static int mipi_csis_async_register(struct csi_state *state)
>  
>  err_parse:
>  	fwnode_handle_put(ep);
> -	kfree(asd);
>  
>  	return ret;
>  }
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index a5dc4a74d42d..76be1e01222e 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -197,9 +197,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
>   *
>   * @notif: pointer to &struct v4l2_async_notifier
>   * @endpoint: local endpoint pointing to the remote sub-device to be matched
> - * @asd: Async sub-device struct allocated by the caller. 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.
> + * @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.

Feel free to drop one indentation level (keeping just one tab after the
*).

>   *

Should we explain here that the returned as is allocated by this
function, like documented for the
v4l2_async_notifier_add_fwnode_subdev() documentation ?

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>   * Gets the remote endpoint of a given local endpoint, set it up for fwnode
>   * matching and adds the async sub-device to the notifier's @asd_list. The
> @@ -207,13 +209,12 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
>   * notifier cleanup time.
>   *
>   * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
> - * exception that the fwnode refers to a local endpoint, not the remote one, and
> - * the function relies on the caller to allocate the async sub-device struct.
> + * exception that the fwnode refers to a local endpoint, not the remote one.
>   */
> -int
> +struct v4l2_async_subdev *
>  v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
>  					     struct fwnode_handle *endpoint,
> -					     struct v4l2_async_subdev *asd);
> +					     unsigned int asd_struct_size);
>  
>  /**
>   * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 ` [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
@ 2021-01-14  2:06   ` Laurent Pinchart
  2021-01-14 13:36     ` Ezequiel Garcia
  2021-01-15 12:12     ` Ezequiel Garcia
  2021-01-16 15:56   ` Jacopo Mondi
  1 sibling, 2 replies; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-14  2:06 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

Thank you for the patch.

On Tue, Jan 12, 2021 at 10:23:29AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.

It's not yet, that only happens at the end of the series :-)

s/is discouraged/will be discouraged/

> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_i2c_subdev.
> 
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
> 
> Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
> or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
> the needed setup, instead of open-coding it.
> 
> Using v4l2-async to allocate the driver-specific structs,
> requires to change struct ceu_subdev so the embedded
> struct v4l2_async_subdev is now the first element.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/platform/renesas-ceu.c | 89 ++++++++++------------------
>  1 file changed, 31 insertions(+), 58 deletions(-)
> 
> diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
> index 4a633ad0e8fa..18485812a21e 100644
> --- a/drivers/media/platform/renesas-ceu.c
> +++ b/drivers/media/platform/renesas-ceu.c
> @@ -152,8 +152,8 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
>   * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
>   */
>  struct ceu_subdev {
> -	struct v4l2_subdev *v4l2_sd;
>  	struct v4l2_async_subdev asd;
> +	struct v4l2_subdev *v4l2_sd;
>  
>  	/* per-subdevice mbus configuration options */
>  	unsigned int mbus_flags;
> @@ -174,7 +174,7 @@ struct ceu_device {
>  	struct v4l2_device	v4l2_dev;
>  
>  	/* subdevices descriptors */
> -	struct ceu_subdev	*subdevs;
> +	struct ceu_subdev	**subdevs;
>  	/* the subdevice currently in use */
>  	struct ceu_subdev	*sd;
>  	unsigned int		sd_index;
> @@ -1195,7 +1195,7 @@ static int ceu_enum_input(struct file *file, void *priv,
>  	if (inp->index >= ceudev->num_sd)
>  		return -EINVAL;
>  
> -	ceusd = &ceudev->subdevs[inp->index];
> +	ceusd = ceudev->subdevs[inp->index];
>  
>  	inp->type = V4L2_INPUT_TYPE_CAMERA;
>  	inp->std = 0;
> @@ -1230,7 +1230,7 @@ static int ceu_s_input(struct file *file, void *priv, unsigned int i)
>  		return 0;
>  
>  	ceu_sd_old = ceudev->sd;
> -	ceudev->sd = &ceudev->subdevs[i];
> +	ceudev->sd = ceudev->subdevs[i];
>  
>  	/*
>  	 * Make sure we can generate output image formats and apply
> @@ -1423,7 +1423,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
>  	 * ceu formats.
>  	 */
>  	if (!ceudev->sd) {
> -		ceudev->sd = &ceudev->subdevs[0];
> +		ceudev->sd = ceudev->subdevs[0];
>  		ceudev->sd_index = 0;
>  	}
>  
> @@ -1465,28 +1465,6 @@ static const struct v4l2_async_notifier_operations ceu_notify_ops = {
>  	.complete	= ceu_notify_complete,
>  };
>  
> -/*
> - * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
> - *			      ceu device. Both DT and platform data parsing use
> - *			      this routine.
> - *
> - * Returns 0 for success, -ENOMEM for failure.
> - */
> -static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
> -{
> -	/* Reserve memory for 'n_sd' ceu_subdev descriptors. */
> -	ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
> -				       sizeof(*ceudev->subdevs), GFP_KERNEL);

I may be missing something, but it looks like the subdevs array isn't
allocated anymore. It turned to an array of pointers, but it still need
allocation.

> -	if (!ceudev->subdevs)
> -		return -ENOMEM;
> -
> -	ceudev->sd = NULL;
> -	ceudev->sd_index = 0;
> -	ceudev->num_sd = 0;
> -
> -	return 0;
> -}
> -
>  /*
>   * ceu_parse_platform_data() - Initialize async_subdevices using platform
>   *			       device provided data.
> @@ -1495,6 +1473,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
>  				   const struct ceu_platform_data *pdata)
>  {
>  	const struct ceu_async_subdev *async_sd;
> +	struct v4l2_async_subdev *asd;
>  	struct ceu_subdev *ceu_sd;
>  	unsigned int i;
>  	int ret;
> @@ -1502,29 +1481,26 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
>  	if (pdata->num_subdevs == 0)
>  		return -ENODEV;
>  
> -	ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs);
> -	if (ret)
> -		return ret;
> +	ceudev->sd = NULL;
> +	ceudev->sd_index = 0;
> +	ceudev->num_sd = 0;

ceudev is kzalloc()ed, so I think you could skip this.

>  
>  	for (i = 0; i < pdata->num_subdevs; i++) {
>  
>  		/* Setup the ceu subdevice and the async subdevice. */
>  		async_sd = &pdata->subdevs[i];
> -		ceu_sd = &ceudev->subdevs[i];
> -
> -		INIT_LIST_HEAD(&ceu_sd->asd.list);
> -
> -		ceu_sd->mbus_flags	= async_sd->flags;
> -		ceu_sd->asd.match_type	= V4L2_ASYNC_MATCH_I2C;
> -		ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
> -		ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
> -
> -		ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
> -						     &ceu_sd->asd);
> -		if (ret) {
> +		asd = v4l2_async_notifier_add_i2c_subdev(&ceudev->notifier,
> +				async_sd->i2c_adapter_id,
> +				async_sd->i2c_address,
> +				sizeof(*ceu_sd));
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			v4l2_async_notifier_cleanup(&ceudev->notifier);
>  			return ret;
>  		}
> +		ceu_sd = to_ceu_subdev(asd);
> +		ceu_sd->mbus_flags = async_sd->flags;
> +		ceudev->subdevs[i] = ceu_sd;
>  	}
>  
>  	return pdata->num_subdevs;
> @@ -1536,7 +1512,8 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
>  static int ceu_parse_dt(struct ceu_device *ceudev)
>  {
>  	struct device_node *of = ceudev->dev->of_node;
> -	struct device_node *ep, *remote;
> +	struct device_node *ep;
> +	struct v4l2_async_subdev *asd;
>  	struct ceu_subdev *ceu_sd;
>  	unsigned int i;
>  	int num_ep;
> @@ -1546,9 +1523,9 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
>  	if (!num_ep)
>  		return -ENODEV;
>  
> -	ret = ceu_init_async_subdevs(ceudev, num_ep);
> -	if (ret)
> -		return ret;
> +	ceudev->sd = NULL;
> +	ceudev->sd_index = 0;
> +	ceudev->num_sd = 0;

Same here, I think this could be skipped.

>  
>  	for (i = 0; i < num_ep; i++) {
>  		struct v4l2_fwnode_endpoint fw_ep = {
> @@ -1578,20 +1555,16 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
>  		}
>  
>  		/* Setup the ceu subdevice and the async subdevice. */
> -		ceu_sd = &ceudev->subdevs[i];
> -		INIT_LIST_HEAD(&ceu_sd->asd.list);
> -
> -		remote = of_graph_get_remote_port_parent(ep);
> -		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
> -		ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
> -
> -		ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
> -						     &ceu_sd->asd);
> -		if (ret) {
> -			of_node_put(remote);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +				&ceudev->notifier, of_fwnode_handle(ep),
> +				sizeof(*ceu_sd));
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			goto error_cleanup;
>  		}
> +		ceu_sd = to_ceu_subdev(asd);
> +		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
> +		ceudev->subdevs[i] = ceu_sd;
>  
>  		of_node_put(ep);
>  	}

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention
  2021-01-12 13:23 ` [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention Ezequiel Garcia
@ 2021-01-14  2:14   ` Laurent Pinchart
  2021-01-14 13:36     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-14  2:14 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

Thank you for the patch.

On Tue, Jan 12, 2021 at 10:23:37AM -0300, Ezequiel Garcia wrote:
> The v4l2_async_notifier_cleanup documentation mentions
> v4l2_fwnode_reference_parse_sensor_common, which doesn't exist.
> Drop it.

The function is actually called
v4l2_async_notifier_parse_fwnode_sensor_common(). It was introduced in
commit 7a9ec808ad46 ("media: v4l: fwnode: Add convenience function for
parsing common external refs") with an incorrect name in the
documentation. Commit b064945517ee ("media: fix kernel-doc markups")
fixed the kerneldoc header for the function, but forgot to address this
location.

> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  include/media/v4l2-async.h | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 76be1e01222e..2429ac55be1c 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -290,9 +290,8 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
>   * sub-devices allocated for the purposes of the notifier but not the notifier
>   * itself. The user is responsible for calling this function to clean up the
>   * notifier after calling
> - * @v4l2_async_notifier_add_subdev,
> - * @v4l2_async_notifier_parse_fwnode_endpoints or
> - * @v4l2_fwnode_reference_parse_sensor_common.
> + * @v4l2_async_notifier_add_subdev or
> + * @v4l2_async_notifier_parse_fwnode_endpoints.
>   *
>   * There is no harm from calling v4l2_async_notifier_cleanup in other
>   * cases as long as its memory has been zeroed after it has been

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/13] media: Clarify v4l2-async subdevice addition API
  2021-01-12 13:23 ` [PATCH 12/13] media: Clarify v4l2-async subdevice addition API Ezequiel Garcia
@ 2021-01-14  2:21   ` Laurent Pinchart
  2021-01-14 13:39     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-14  2:21 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

Thank you for the patch.

On Tue, Jan 12, 2021 at 10:23:38AM -0300, Ezequiel Garcia wrote:
> Now that most users of v4l2_async_notifier_add_subdev have
> been converted, let's fix the documentation so it's more clear
> how the v4l2-async API should be used.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  .../driver-api/media/v4l2-subdev.rst          | 38 ++++++++++++++++---
>  include/media/v4l2-async.h                    | 12 +++++-
>  2 files changed, 43 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> index bb5b1a7cdfd9..5ddf9de4fcf7 100644
> --- a/Documentation/driver-api/media/v4l2-subdev.rst
> +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> @@ -204,11 +204,39 @@ Before registering the notifier, bridge drivers must do two things:
>  first, the notifier must be initialized using the
>  :c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
>  begin to form a list of subdevice descriptors that the bridge device
> -needs for its operation. Subdevice descriptors are added to the notifier
> -using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
> -takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
> -and a pointer to the subdevice descripter, which is of type struct
> -:c:type:`v4l2_async_subdev`.
> +needs for its operation. Several functions are available, to
> +add subdevice descriptors to a notifier, depending on the type of device:

You could reflow this to

needs for its operation. Several functions are available, to add subdevice
descriptors to a notifier, depending on the type of device:

> +:c:func:`v4l2_async_notifier_add_devname_subdev`,
> +:c:func:`v4l2_async_notifier_add_fwnode_subdev` or
> +:c:func:`v4l2_async_notifier_add_i2c_subdev`.

Should you also list v4l2_async_notifier_add_fwnode_remote_subdev() (and
possibly v4l2_async_notifier_parse_fwnode_endpoints()) here ?

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +
> +These functions allocate a subdevice descriptor, which is of
> +type struct :c:type:`v4l2_async_subdev`, and take a size argument
> +which can be used to embed the descriptor in a driver-specific
> +async subdevice struct. The &struct :c:type:`v4l2_async_subdev`
> +shall be the first member of this struct:
> +
> +.. code-block:: c
> +
> +	struct my_async_subdev {
> +		struct v4l2_async_subdev asd;
> +		...
> +	};
> +
> +	struct my_async_subdev *my_asd;
> +	struct v4l2_async_subdev *asd;
> +	struct fwnode_handle *ep;
> +
> +	...
> +
> +	asd = v4l2_async_notifier_add_fwnode_subdev(
> +			&notifier, ep, sizeof(*my_asd));
> +	fwnode_handle_put(ep);
> +
> +	if (IS_ERR(asd))
> +		return PTR_ERR(asd);
> +
> +	my_asd = container_of(asd, struct my_async_subdev, asd);
>  
>  The V4L2 core will then use these descriptors to match asynchronously
>  registered subdevices to them. If a match is detected the ``.bound()``
> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 2429ac55be1c..1278f98355a7 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -151,7 +151,12 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>   * @notifier: pointer to &struct v4l2_async_notifier
>   *
>   * This function initializes the notifier @asd_list. It must be called
> - * before the first call to @v4l2_async_notifier_add_subdev.
> + * before adding a subdevice to a notifier, using one of:
> + * @v4l2_async_notifier_add_fwnode_subdev,
> + * @v4l2_async_notifier_add_fwnode_remote_subdev,
> + * @v4l2_async_notifier_add_i2c_subdev,
> + * @v4l2_async_notifier_add_devname_subdev or
> + * @v4l2_async_notifier_parse_fwnode_endpoints.
>   */
>  void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
>  
> @@ -290,7 +295,10 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier);
>   * sub-devices allocated for the purposes of the notifier but not the notifier
>   * itself. The user is responsible for calling this function to clean up the
>   * notifier after calling
> - * @v4l2_async_notifier_add_subdev or
> + * @v4l2_async_notifier_add_fwnode_subdev,
> + * @v4l2_async_notifier_add_fwnode_remote_subdev,
> + * @v4l2_async_notifier_add_i2c_subdev,
> + * @v4l2_async_notifier_add_devname_subdev or
>   * @v4l2_async_notifier_parse_fwnode_endpoints.
>   *
>   * There is no harm from calling v4l2_async_notifier_cleanup in other

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev
  2021-01-12 13:23 ` [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev Ezequiel Garcia
@ 2021-01-14  2:27   ` Laurent Pinchart
  2021-01-14 13:47     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-14  2:27 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

Thank you for the patch.

On Tue, Jan 12, 2021 at 10:23:39AM -0300, Ezequiel Garcia wrote:
> Most -if not all- use-cases are expected to be covered by one of:
> v4l2_async_notifier_add_fwnode_subdev,
> v4l2_async_notifier_add_fwnode_remote_subdev,
> v4l2_async_notifier_add_i2c_subdev or
> v4l2_async_notifier_add_devname_subdev.
> 
> We'd like to discourage drivers from using v4l2_async_notifier_add_subdev,
> so rename it as __v4l2_async_notifier_add_subdev. This is
> typically a good hint for drivers to avoid using the function.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/v4l2-core/v4l2-async.c  | 10 +++++-----
>  drivers/media/v4l2-core/v4l2-fwnode.c |  2 +-
>  include/media/v4l2-async.h            | 10 ++++++++--
>  3 files changed, 14 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index b325bacddff4..e8e690280922 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -630,7 +630,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
>  }
>  EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
>  
> -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_async_subdev *asd)
>  {
>  	int ret;
> @@ -647,7 +647,7 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
>  	mutex_unlock(&list_lock);
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
> +EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_subdev);
>  
>  struct v4l2_async_subdev *
>  v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
> @@ -664,7 +664,7 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
>  	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
>  	asd->match.fwnode = fwnode_handle_get(fwnode);
>  
> -	ret = v4l2_async_notifier_add_subdev(notifier, asd);
> +	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
>  	if (ret) {
>  		fwnode_handle_put(fwnode);
>  		kfree(asd);
> @@ -714,7 +714,7 @@ v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
>  	asd->match.i2c.adapter_id = adapter_id;
>  	asd->match.i2c.address = address;
>  
> -	ret = v4l2_async_notifier_add_subdev(notifier, asd);
> +	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
>  	if (ret) {
>  		kfree(asd);
>  		return ERR_PTR(ret);
> @@ -739,7 +739,7 @@ v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
>  	asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
>  	asd->match.device_name = device_name;
>  
> -	ret = v4l2_async_notifier_add_subdev(notifier, asd);
> +	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
>  	if (ret) {
>  		kfree(asd);
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> index 5353e37eb950..919fde20032e 100644
> --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> @@ -833,7 +833,7 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
>  	if (ret < 0)
>  		goto out_err;
>  
> -	ret = v4l2_async_notifier_add_subdev(notifier, asd);
> +	ret = __v4l2_async_notifier_add_subdev(notifier, asd);
>  	if (ret < 0) {
>  		/* not an error if asd already exists */
>  		if (ret == -EEXIST)

I wonder if v4l2-fwnode should be moved to videodev-objs in the
Makefile, we could then avoid exporting
__v4l2_async_notifier_add_subdev(). This doesn't need to be fixed here,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> index 1278f98355a7..9cf83f1ecca6 100644
> --- a/include/media/v4l2-async.h
> +++ b/include/media/v4l2-async.h
> @@ -161,17 +161,23 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
>  void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
>  
>  /**
> - * v4l2_async_notifier_add_subdev - Add an async subdev to the
> + * __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
>   *
> + * \warning: Drivers should avoid using this function and instead use one of:
> + * @v4l2_async_notifier_add_fwnode_subdev,
> + * @v4l2_async_notifier_add_fwnode_remote_subdev,
> + * @v4l2_async_notifier_add_i2c_subdev or
> + * @v4l2_async_notifier_add_devname_subdev.
> + *
>   * Call this function before registering a notifier to link the provided @asd to
>   * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
>   * it will be freed by the framework when the notifier is destroyed.
>   */
> -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_async_subdev *asd);
>  
>  /**

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-14  2:06   ` Laurent Pinchart
@ 2021-01-14 13:36     ` Ezequiel Garcia
  2021-01-15 12:12     ` Ezequiel Garcia
  1 sibling, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 13:36 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Laurent,

Thanks a lot for the thorough review.

On Thu, 2021-01-14 at 04:06 +0200, Laurent Pinchart wrote:
> Hi Ezequiel,
> 
> Thank you for the patch.
> 
> On Tue, Jan 12, 2021 at 10:23:29AM -0300, Ezequiel Garcia wrote:
> > The use of v4l2_async_notifier_add_subdev is discouraged.
> 
> It's not yet, that only happens at the end of the series :-)
> 
> s/is discouraged/will be discouraged/
> 

Makes sense. Will change this on all the commits.

> > Drivers are instead encouraged to use a helper such as
> > v4l2_async_notifier_add_i2c_subdev.
> > 
> > This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> > should get a kmalloc'ed struct v4l2_async_subdev,
> > removing some boilerplate code while at it.
> > 
> > Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
> > or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
> > the needed setup, instead of open-coding it.
> > 
> > Using v4l2-async to allocate the driver-specific structs,
> > requires to change struct ceu_subdev so the embedded
> > struct v4l2_async_subdev is now the first element.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/platform/renesas-ceu.c | 89 ++++++++++------------------
> >  1 file changed, 31 insertions(+), 58 deletions(-)
> > 
> > diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
> > index 4a633ad0e8fa..18485812a21e 100644
> > --- a/drivers/media/platform/renesas-ceu.c
> > +++ b/drivers/media/platform/renesas-ceu.c
> > @@ -152,8 +152,8 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
> >   * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
> >   */
> >  struct ceu_subdev {
> > -       struct v4l2_subdev *v4l2_sd;
> >         struct v4l2_async_subdev asd;
> > +       struct v4l2_subdev *v4l2_sd;
> >  
> >         /* per-subdevice mbus configuration options */
> >         unsigned int mbus_flags;
> > @@ -174,7 +174,7 @@ struct ceu_device {
> >         struct v4l2_device      v4l2_dev;
> >  
> >         /* subdevices descriptors */
> > -       struct ceu_subdev       *subdevs;
> > +       struct ceu_subdev       **subdevs;
> >         /* the subdevice currently in use */
> >         struct ceu_subdev       *sd;
> >         unsigned int            sd_index;
> > @@ -1195,7 +1195,7 @@ static int ceu_enum_input(struct file *file, void *priv,
> >         if (inp->index >= ceudev->num_sd)
> >                 return -EINVAL;
> >  
> > -       ceusd = &ceudev->subdevs[inp->index];
> > +       ceusd = ceudev->subdevs[inp->index];
> >  
> >         inp->type = V4L2_INPUT_TYPE_CAMERA;
> >         inp->std = 0;
> > @@ -1230,7 +1230,7 @@ static int ceu_s_input(struct file *file, void *priv, unsigned int i)
> >                 return 0;
> >  
> >         ceu_sd_old = ceudev->sd;
> > -       ceudev->sd = &ceudev->subdevs[i];
> > +       ceudev->sd = ceudev->subdevs[i];
> >  
> >         /*
> >          * Make sure we can generate output image formats and apply
> > @@ -1423,7 +1423,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
> >          * ceu formats.
> >          */
> >         if (!ceudev->sd) {
> > -               ceudev->sd = &ceudev->subdevs[0];
> > +               ceudev->sd = ceudev->subdevs[0];
> >                 ceudev->sd_index = 0;
> >         }
> >  
> > @@ -1465,28 +1465,6 @@ static const struct v4l2_async_notifier_operations ceu_notify_ops = {
> >         .complete       = ceu_notify_complete,
> >  };
> >  
> > -/*
> > - * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
> > - *                           ceu device. Both DT and platform data parsing use
> > - *                           this routine.
> > - *
> > - * Returns 0 for success, -ENOMEM for failure.
> > - */
> > -static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
> > -{
> > -       /* Reserve memory for 'n_sd' ceu_subdev descriptors. */
> > -       ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
> > -                                      sizeof(*ceudev->subdevs), GFP_KERNEL);
> 
> I may be missing something, but it looks like the subdevs array isn't
> allocated anymore. It turned to an array of pointers, but it still need
> allocation.
> 

Oops. Thanks for spotting this.

> > -       if (!ceudev->subdevs)
> > -               return -ENOMEM;
> > -
> > -       ceudev->sd = NULL;
> > -       ceudev->sd_index = 0;
> > -       ceudev->num_sd = 0;
> > -
> > -       return 0;
> > -}
> > -
> >  /*
> >   * ceu_parse_platform_data() - Initialize async_subdevices using platform
> >   *                            device provided data.
> > @@ -1495,6 +1473,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
> >                                    const struct ceu_platform_data *pdata)
> >  {
> >         const struct ceu_async_subdev *async_sd;
> > +       struct v4l2_async_subdev *asd;
> >         struct ceu_subdev *ceu_sd;
> >         unsigned int i;
> >         int ret;
> > @@ -1502,29 +1481,26 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
> >         if (pdata->num_subdevs == 0)
> >                 return -ENODEV;
> >  
> > -       ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs);
> > -       if (ret)
> > -               return ret;
> > +       ceudev->sd = NULL;
> > +       ceudev->sd_index = 0;
> > +       ceudev->num_sd = 0;
> 
> ceudev is kzalloc()ed, so I think you could skip this.
> 

Right.

> >  
> >         for (i = 0; i < pdata->num_subdevs; i++) {
> >  
> >                 /* Setup the ceu subdevice and the async subdevice. */
> >                 async_sd = &pdata->subdevs[i];
> > -               ceu_sd = &ceudev->subdevs[i];
> > -
> > -               INIT_LIST_HEAD(&ceu_sd->asd.list);
> > -
> > -               ceu_sd->mbus_flags      = async_sd->flags;
> > -               ceu_sd->asd.match_type  = V4L2_ASYNC_MATCH_I2C;
> > -               ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
> > -               ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
> > -
> > -               ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
> > -                                                    &ceu_sd->asd);
> > -               if (ret) {
> > +               asd = v4l2_async_notifier_add_i2c_subdev(&ceudev->notifier,
> > +                               async_sd->i2c_adapter_id,
> > +                               async_sd->i2c_address,
> > +                               sizeof(*ceu_sd));
> > +               if (IS_ERR(asd)) {
> > +                       ret = PTR_ERR(asd);
> >                         v4l2_async_notifier_cleanup(&ceudev->notifier);
> >                         return ret;
> >                 }
> > +               ceu_sd = to_ceu_subdev(asd);
> > +               ceu_sd->mbus_flags = async_sd->flags;
> > +               ceudev->subdevs[i] = ceu_sd;
> >         }
> >  
> >         return pdata->num_subdevs;
> > @@ -1536,7 +1512,8 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev,
> >  static int ceu_parse_dt(struct ceu_device *ceudev)
> >  {
> >         struct device_node *of = ceudev->dev->of_node;
> > -       struct device_node *ep, *remote;
> > +       struct device_node *ep;
> > +       struct v4l2_async_subdev *asd;
> >         struct ceu_subdev *ceu_sd;
> >         unsigned int i;
> >         int num_ep;
> > @@ -1546,9 +1523,9 @@ static int ceu_parse_dt(struct ceu_device *ceudev)
> >         if (!num_ep)
> >                 return -ENODEV;
> >  
> > -       ret = ceu_init_async_subdevs(ceudev, num_ep);
> > -       if (ret)
> > -               return ret;
> > +       ceudev->sd = NULL;
> > +       ceudev->sd_index = 0;
> > +       ceudev->num_sd = 0;
> 
> Same here, I think this could be skipped.
> 

Yup.

Thanks,
Ezequiel


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

* Re: [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention
  2021-01-14  2:14   ` Laurent Pinchart
@ 2021-01-14 13:36     ` Ezequiel Garcia
  2021-01-15  6:56       ` Laurent Pinchart
  0 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 13:36 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

On Thu, 2021-01-14 at 04:14 +0200, Laurent Pinchart wrote:
> Hi Ezequiel,
> 
> Thank you for the patch.
> 
> On Tue, Jan 12, 2021 at 10:23:37AM -0300, Ezequiel Garcia wrote:
> > The v4l2_async_notifier_cleanup documentation mentions
> > v4l2_fwnode_reference_parse_sensor_common, which doesn't exist.
> > Drop it.
> 
> The function is actually called
> v4l2_async_notifier_parse_fwnode_sensor_common(). It was introduced in
> commit 7a9ec808ad46 ("media: v4l: fwnode: Add convenience function for
> parsing common external refs") with an incorrect name in the
> documentation. Commit b064945517ee ("media: fix kernel-doc markups")
> fixed the kerneldoc header for the function, but forgot to address this
> location.
> 

OK, I'll fix the commit description.

Thanks,
Ezequiel


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

* Re: [PATCH 12/13] media: Clarify v4l2-async subdevice addition API
  2021-01-14  2:21   ` Laurent Pinchart
@ 2021-01-14 13:39     ` Ezequiel Garcia
  2021-01-15  8:47       ` Sakari Ailus
  0 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 13:39 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

On Thu, 2021-01-14 at 04:21 +0200, Laurent Pinchart wrote:
> Hi Ezequiel,
> 
> Thank you for the patch.
> 
> On Tue, Jan 12, 2021 at 10:23:38AM -0300, Ezequiel Garcia wrote:
> > Now that most users of v4l2_async_notifier_add_subdev have
> > been converted, let's fix the documentation so it's more clear
> > how the v4l2-async API should be used.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  .../driver-api/media/v4l2-subdev.rst          | 38 ++++++++++++++++---
> >  include/media/v4l2-async.h                    | 12 +++++-
> >  2 files changed, 43 insertions(+), 7 deletions(-)
> > 
> > diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> > index bb5b1a7cdfd9..5ddf9de4fcf7 100644
> > --- a/Documentation/driver-api/media/v4l2-subdev.rst
> > +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> > @@ -204,11 +204,39 @@ Before registering the notifier, bridge drivers must do two things:
> >  first, the notifier must be initialized using the
> >  :c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
> >  begin to form a list of subdevice descriptors that the bridge device
> > -needs for its operation. Subdevice descriptors are added to the notifier
> > -using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
> > -takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
> > -and a pointer to the subdevice descripter, which is of type struct
> > -:c:type:`v4l2_async_subdev`.
> > +needs for its operation. Several functions are available, to
> > +add subdevice descriptors to a notifier, depending on the type of device:
> 
> You could reflow this to
> 
> needs for its operation. Several functions are available, to add subdevice
> descriptors to a notifier, depending on the type of device:
> 
> > +:c:func:`v4l2_async_notifier_add_devname_subdev`,
> > +:c:func:`v4l2_async_notifier_add_fwnode_subdev` or
> > +:c:func:`v4l2_async_notifier_add_i2c_subdev`.
> 
> Should you also list v4l2_async_notifier_add_fwnode_remote_subdev() (and

Yes.

> possibly v4l2_async_notifier_parse_fwnode_endpoints()) here ?
> 

Unsure. I'd rather not document this one, as it's deprecated
and we want to remove it.

> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 

Thanks!
Ezequiel


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

* Re: [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev
  2021-01-14  2:27   ` Laurent Pinchart
@ 2021-01-14 13:47     ` Ezequiel Garcia
  2021-01-15  6:57       ` Laurent Pinchart
  0 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 13:47 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Laurent,

On Thu, 2021-01-14 at 04:27 +0200, Laurent Pinchart wrote:
> Hi Ezequiel,
> 
> Thank you for the patch.
> 
> On Tue, Jan 12, 2021 at 10:23:39AM -0300, Ezequiel Garcia wrote:
> > Most -if not all- use-cases are expected to be covered by one of:
> > v4l2_async_notifier_add_fwnode_subdev,
> > v4l2_async_notifier_add_fwnode_remote_subdev,
> > v4l2_async_notifier_add_i2c_subdev or
> > v4l2_async_notifier_add_devname_subdev.
> > 
> > We'd like to discourage drivers from using v4l2_async_notifier_add_subdev,
> > so rename it as __v4l2_async_notifier_add_subdev. This is
> > typically a good hint for drivers to avoid using the function.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/v4l2-core/v4l2-async.c  | 10 +++++-----
> >  drivers/media/v4l2-core/v4l2-fwnode.c |  2 +-
> >  include/media/v4l2-async.h            | 10 ++++++++--
> >  3 files changed, 14 insertions(+), 8 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > index b325bacddff4..e8e690280922 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -630,7 +630,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
> >  }
> >  EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
> >  
> > -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> >                                    struct v4l2_async_subdev *asd)
> >  {
> >         int ret;
> > @@ -647,7 +647,7 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> >         mutex_unlock(&list_lock);
> >         return ret;
> >  }
> > -EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
> > +EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_subdev);
> >  
> >  struct v4l2_async_subdev *
> >  v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
> > @@ -664,7 +664,7 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
> >         asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> >         asd->match.fwnode = fwnode_handle_get(fwnode);
> >  
> > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> >         if (ret) {
> >                 fwnode_handle_put(fwnode);
> >                 kfree(asd);
> > @@ -714,7 +714,7 @@ v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
> >         asd->match.i2c.adapter_id = adapter_id;
> >         asd->match.i2c.address = address;
> >  
> > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> >         if (ret) {
> >                 kfree(asd);
> >                 return ERR_PTR(ret);
> > @@ -739,7 +739,7 @@ v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
> >         asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
> >         asd->match.device_name = device_name;
> >  
> > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> >         if (ret) {
> >                 kfree(asd);
> >                 return ERR_PTR(ret);
> > diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> > index 5353e37eb950..919fde20032e 100644
> > --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> > +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> > @@ -833,7 +833,7 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
> >         if (ret < 0)
> >                 goto out_err;
> >  
> > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> >         if (ret < 0) {
> >                 /* not an error if asd already exists */
> >                 if (ret == -EEXIST)
> 
> I wonder if v4l2-fwnode should be moved to videodev-objs in the
> Makefile, we could then avoid exporting
> __v4l2_async_notifier_add_subdev(). This doesn't need to be fixed here,
> 

Yeah, I thought about that, precisely to avoid the export and disallow
any future users of v4l2_async_notifier_add_subdev.

The impact of that is that we'd kill V4L2_FWNODE, increasing the
size of videodev.ko, by a small fraction.

Perhaps this is justified? I'm sure all the use-cases for this type
of hardware won't care for 20 KiB more or less in the kernel payload.

> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > index 1278f98355a7..9cf83f1ecca6 100644
> > --- a/include/media/v4l2-async.h
> > +++ b/include/media/v4l2-async.h
> > @@ -161,17 +161,23 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> >  void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
> >  
> >  /**
> > - * v4l2_async_notifier_add_subdev - Add an async subdev to the
> > + * __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
> >   *
> > + * \warning: Drivers should avoid using this function and instead use one of:
> > + * @v4l2_async_notifier_add_fwnode_subdev,
> > + * @v4l2_async_notifier_add_fwnode_remote_subdev,
> > + * @v4l2_async_notifier_add_i2c_subdev or
> > + * @v4l2_async_notifier_add_devname_subdev.
> > + *
> >   * Call this function before registering a notifier to link the provided @asd to
> >   * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
> >   * it will be freed by the framework when the notifier is destroyed.
> >   */
> > -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> >                                    struct v4l2_async_subdev *asd);
> >  
> >  /**
> 

Thanks,
Ezequiel



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

* Re: [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-14  1:59   ` Laurent Pinchart
@ 2021-01-14 13:47     ` Sakari Ailus
  2021-01-14 14:46       ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Sakari Ailus @ 2021-01-14 13:47 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Ezequiel Garcia, linux-media, Hans Verkuil, kernel

Hi Laurent, Ezequiel,

On Thu, Jan 14, 2021 at 03:59:10AM +0200, Laurent Pinchart wrote:
> > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > index 68da1eed753d..235dcf0c4122 100644
> > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> >  			.bus_type = V4L2_MBUS_CSI2_DPHY
> >  		};
> >  		struct rkisp1_sensor_async *rk_asd = NULL;
> > +		struct v4l2_async_subdev *asd;
> >  		struct fwnode_handle *ep;
> >  
> >  		ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
> > @@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> >  		if (ret)
> >  			goto err_parse;
> >  
> > -		rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
> > -		if (!rk_asd) {
> > -			ret = -ENOMEM;
> > +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> > +							sizeof(*rk_asd));
> > +		if (IS_ERR(asd))

The problem with registering the sub-device already here is that the driver
can proceed to use the information in the async sub-device object which is
initialised below.

There might not be practical problems but there's also no guarantee it
would work. The same problem is actually present in the rest of the
functions registering the object after allocating it.

> >  			goto err_parse;
> > -		}
> >  
> > +		rk_asd = container_of(asd, struct rkisp1_sensor_async, asd);
> 
> It could be nice to turn v4l2_async_notifier_add_fwnode_remote_subdev()
> into a macro that would take the asd structure type, and cast the
> result, to avoid container_of() in the caller. That can be done on top
> of this series.
> 
> >  		rk_asd->mbus_type = vep.bus_type;
> >  		rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;
> >  		rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;
> >  
> > -		ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> > -								   &rk_asd->asd);
> > -		if (ret)
> > -			goto err_parse;
> > -
> >  		dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n",
> >  			vep.base.id, rk_asd->lanes);
> >  

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-14 13:47     ` Sakari Ailus
@ 2021-01-14 14:46       ` Ezequiel Garcia
  2021-01-14 16:11         ` Sakari Ailus
  0 siblings, 1 reply; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 14:46 UTC (permalink / raw)
  To: Sakari Ailus, Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel

On Thu, 2021-01-14 at 15:47 +0200, Sakari Ailus wrote:
> Hi Laurent, Ezequiel,
> 
> On Thu, Jan 14, 2021 at 03:59:10AM +0200, Laurent Pinchart wrote:
> > > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > index 68da1eed753d..235dcf0c4122 100644
> > > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > >                         .bus_type = V4L2_MBUS_CSI2_DPHY
> > >                 };
> > >                 struct rkisp1_sensor_async *rk_asd = NULL;
> > > +               struct v4l2_async_subdev *asd;
> > >                 struct fwnode_handle *ep;
> > >  
> > >                 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
> > > @@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > >                 if (ret)
> > >                         goto err_parse;
> > >  
> > > -               rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
> > > -               if (!rk_asd) {
> > > -                       ret = -ENOMEM;
> > > +               asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> > > +                                                       sizeof(*rk_asd));
> > > +               if (IS_ERR(asd))
> 
> The problem with registering the sub-device already here is that the driver
> can proceed to use the information in the async sub-device object which is
> initialised below.
> 

Note that this interface is not really registering sub-devices.

> There might not be practical problems but there's also no guarantee it
> would work. The same problem is actually present in the rest of the
> functions registering the object after allocating it.
> 

I'd say the v4l2_async_notifier_add_{}_subdev interface is about adding a
v4l2-async subdevice descriptor to a v4l2-async notifier.

Until the v4l2-async notifier is not registered by v4l2_async_notifier_register()
(which is expected to happen after the structures that embed the descriptors
are filled, if such thing is needed), then I don't think the driver
would have access to the descriptors.

The access to the v4l2-async subdevice descriptor (struct v4l2_async_subdev)
should be done via v4l2_async_notifier_operations.bound and .complete ops.

I think this usage model is safe, and quite clear from the interface itself,
so don't think there's any issue with this change.

And OTOH, this is about making v4l2_async_notifier_add_fwnode_remote_subdev
consistent with v4l2_async_notifier_add_fwnode_subdev et al.

Thanks,
Ezequiel


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

* Re: [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-14 14:46       ` Ezequiel Garcia
@ 2021-01-14 16:11         ` Sakari Ailus
  2021-01-14 16:22           ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Sakari Ailus @ 2021-01-14 16:11 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: Laurent Pinchart, linux-media, Hans Verkuil, kernel

On Thu, Jan 14, 2021 at 11:46:11AM -0300, Ezequiel Garcia wrote:
> On Thu, 2021-01-14 at 15:47 +0200, Sakari Ailus wrote:
> > Hi Laurent, Ezequiel,
> > 
> > On Thu, Jan 14, 2021 at 03:59:10AM +0200, Laurent Pinchart wrote:
> > > > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > index 68da1eed753d..235dcf0c4122 100644
> > > > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > > >                         .bus_type = V4L2_MBUS_CSI2_DPHY
> > > >                 };
> > > >                 struct rkisp1_sensor_async *rk_asd = NULL;
> > > > +               struct v4l2_async_subdev *asd;
> > > >                 struct fwnode_handle *ep;
> > > >  
> > > >                 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
> > > > @@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > > >                 if (ret)
> > > >                         goto err_parse;
> > > >  
> > > > -               rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
> > > > -               if (!rk_asd) {
> > > > -                       ret = -ENOMEM;
> > > > +               asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> > > > +                                                       sizeof(*rk_asd));
> > > > +               if (IS_ERR(asd))
> > 
> > The problem with registering the sub-device already here is that the driver
> > can proceed to use the information in the async sub-device object which is
> > initialised below.
> > 
> 
> Note that this interface is not really registering sub-devices.

Not directly, but this will happen as a by-product of registering the async
sub-device and other functions that will be called. All this takes place
synchronously, meaming that by the time this function returns, the
character devices that are the user space interface have already been
created.

> 
> > There might not be practical problems but there's also no guarantee it
> > would work. The same problem is actually present in the rest of the
> > functions registering the object after allocating it.
> > 
> 
> I'd say the v4l2_async_notifier_add_{}_subdev interface is about adding a
> v4l2-async subdevice descriptor to a v4l2-async notifier.
> 
> Until the v4l2-async notifier is not registered by v4l2_async_notifier_register()
> (which is expected to happen after the structures that embed the descriptors
> are filled, if such thing is needed), then I don't think the driver
> would have access to the descriptors.
> 
> The access to the v4l2-async subdevice descriptor (struct v4l2_async_subdev)
> should be done via v4l2_async_notifier_operations.bound and .complete ops.
> 
> I think this usage model is safe, and quite clear from the interface itself,
> so don't think there's any issue with this change.

As I said, you might not have a practical problem but there's no
_guarantee_ that it'll be fine.

There are three things being done here, allocating memory for the async
sub-device, initialising it and finally registering it. These need to take
place in that order.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics
  2021-01-14 16:11         ` Sakari Ailus
@ 2021-01-14 16:22           ` Ezequiel Garcia
  0 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-14 16:22 UTC (permalink / raw)
  To: Sakari Ailus; +Cc: Laurent Pinchart, linux-media, Hans Verkuil, kernel

On Thu, 2021-01-14 at 18:11 +0200, Sakari Ailus wrote:
> On Thu, Jan 14, 2021 at 11:46:11AM -0300, Ezequiel Garcia wrote:
> > On Thu, 2021-01-14 at 15:47 +0200, Sakari Ailus wrote:
> > > Hi Laurent, Ezequiel,
> > > 
> > > On Thu, Jan 14, 2021 at 03:59:10AM +0200, Laurent Pinchart wrote:
> > > > > diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > > index 68da1eed753d..235dcf0c4122 100644
> > > > > --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > > +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
> > > > > @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > > > >                         .bus_type = V4L2_MBUS_CSI2_DPHY
> > > > >                 };
> > > > >                 struct rkisp1_sensor_async *rk_asd = NULL;
> > > > > +               struct v4l2_async_subdev *asd;
> > > > >                 struct fwnode_handle *ep;
> > > > >  
> > > > >                 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
> > > > > @@ -264,21 +265,16 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
> > > > >                 if (ret)
> > > > >                         goto err_parse;
> > > > >  
> > > > > -               rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
> > > > > -               if (!rk_asd) {
> > > > > -                       ret = -ENOMEM;
> > > > > +               asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
> > > > > +                                                       sizeof(*rk_asd));
> > > > > +               if (IS_ERR(asd))
> > > 
> > > The problem with registering the sub-device already here is that the driver
> > > can proceed to use the information in the async sub-device object which is
> > > initialised below.
> > > 
> > 
> > Note that this interface is not really registering sub-devices.
> 
> Not directly, but this will happen as a by-product of registering the async
> sub-device and other functions that will be called. All this takes place
> synchronously, meaming that by the time this function returns, the
> character devices that are the user space interface have already been
> created.
> 

That's not the case, as I've explained before, v4l2_async_notifier_add_fwnode_remote_subdev
is _not_ about registering any actual v4l2 subdevice/char device.

It's just about adding the v4l2 async subdevice descriptor
to a given (unregistered) notifier.

Thanks,
Ezequiel


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

* Re: [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention
  2021-01-14 13:36     ` Ezequiel Garcia
@ 2021-01-15  6:56       ` Laurent Pinchart
  0 siblings, 0 replies; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-15  6:56 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

On Thu, Jan 14, 2021 at 10:36:54AM -0300, Ezequiel Garcia wrote:
> On Thu, 2021-01-14 at 04:14 +0200, Laurent Pinchart wrote:
> > On Tue, Jan 12, 2021 at 10:23:37AM -0300, Ezequiel Garcia wrote:
> > > The v4l2_async_notifier_cleanup documentation mentions
> > > v4l2_fwnode_reference_parse_sensor_common, which doesn't exist.
> > > Drop it.
> > 
> > The function is actually called
> > v4l2_async_notifier_parse_fwnode_sensor_common(). It was introduced in
> > commit 7a9ec808ad46 ("media: v4l: fwnode: Add convenience function for
> > parsing common external refs") with an incorrect name in the
> > documentation. Commit b064945517ee ("media: fix kernel-doc markups")
> > fixed the kerneldoc header for the function, but forgot to address this
> > location.
> 
> OK, I'll fix the commit description.

I think it's more than the commit description, instead of dropping the
reference to v4l2_fwnode_reference_parse_sensor_common(), it should be
replaced with a reference to
v4l2_async_notifier_parse_fwnode_sensor_common().

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev
  2021-01-14 13:47     ` Ezequiel Garcia
@ 2021-01-15  6:57       ` Laurent Pinchart
  0 siblings, 0 replies; 41+ messages in thread
From: Laurent Pinchart @ 2021-01-15  6:57 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Ezequiel,

On Thu, Jan 14, 2021 at 10:47:08AM -0300, Ezequiel Garcia wrote:
> On Thu, 2021-01-14 at 04:27 +0200, Laurent Pinchart wrote:
> > On Tue, Jan 12, 2021 at 10:23:39AM -0300, Ezequiel Garcia wrote:
> > > Most -if not all- use-cases are expected to be covered by one of:
> > > v4l2_async_notifier_add_fwnode_subdev,
> > > v4l2_async_notifier_add_fwnode_remote_subdev,
> > > v4l2_async_notifier_add_i2c_subdev or
> > > v4l2_async_notifier_add_devname_subdev.
> > > 
> > > We'd like to discourage drivers from using v4l2_async_notifier_add_subdev,
> > > so rename it as __v4l2_async_notifier_add_subdev. This is
> > > typically a good hint for drivers to avoid using the function.
> > > 
> > > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > > ---
> > >  drivers/media/v4l2-core/v4l2-async.c  | 10 +++++-----
> > >  drivers/media/v4l2-core/v4l2-fwnode.c |  2 +-
> > >  include/media/v4l2-async.h            | 10 ++++++++--
> > >  3 files changed, 14 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > > index b325bacddff4..e8e690280922 100644
> > > --- a/drivers/media/v4l2-core/v4l2-async.c
> > > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > > @@ -630,7 +630,7 @@ void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier)
> > >  }
> > >  EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
> > >  
> > > -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > > +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > >                                    struct v4l2_async_subdev *asd)
> > >  {
> > >         int ret;
> > > @@ -647,7 +647,7 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > >         mutex_unlock(&list_lock);
> > >         return ret;
> > >  }
> > > -EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev);
> > > +EXPORT_SYMBOL_GPL(__v4l2_async_notifier_add_subdev);
> > >  
> > >  struct v4l2_async_subdev *
> > >  v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
> > > @@ -664,7 +664,7 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
> > >         asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
> > >         asd->match.fwnode = fwnode_handle_get(fwnode);
> > >  
> > > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> > >         if (ret) {
> > >                 fwnode_handle_put(fwnode);
> > >                 kfree(asd);
> > > @@ -714,7 +714,7 @@ v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier,
> > >         asd->match.i2c.adapter_id = adapter_id;
> > >         asd->match.i2c.address = address;
> > >  
> > > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> > >         if (ret) {
> > >                 kfree(asd);
> > >                 return ERR_PTR(ret);
> > > @@ -739,7 +739,7 @@ v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier,
> > >         asd->match_type = V4L2_ASYNC_MATCH_DEVNAME;
> > >         asd->match.device_name = device_name;
> > >  
> > > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> > >         if (ret) {
> > >                 kfree(asd);
> > >                 return ERR_PTR(ret);
> > > diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
> > > index 5353e37eb950..919fde20032e 100644
> > > --- a/drivers/media/v4l2-core/v4l2-fwnode.c
> > > +++ b/drivers/media/v4l2-core/v4l2-fwnode.c
> > > @@ -833,7 +833,7 @@ v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev,
> > >         if (ret < 0)
> > >                 goto out_err;
> > >  
> > > -       ret = v4l2_async_notifier_add_subdev(notifier, asd);
> > > +       ret = __v4l2_async_notifier_add_subdev(notifier, asd);
> > >         if (ret < 0) {
> > >                 /* not an error if asd already exists */
> > >                 if (ret == -EEXIST)
> > 
> > I wonder if v4l2-fwnode should be moved to videodev-objs in the
> > Makefile, we could then avoid exporting
> > __v4l2_async_notifier_add_subdev(). This doesn't need to be fixed here,
> > 
> 
> Yeah, I thought about that, precisely to avoid the export and disallow
> any future users of v4l2_async_notifier_add_subdev.
> 
> The impact of that is that we'd kill V4L2_FWNODE, increasing the
> size of videodev.ko, by a small fraction.

We don't have to drop V4L2_FWNODE, we can still make v4l2-async.o
conditional, even if it's included in videodev.ko.

> Perhaps this is justified? I'm sure all the use-cases for this type
> of hardware won't care for 20 KiB more or less in the kernel payload.
> 
> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > 
> > > diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
> > > index 1278f98355a7..9cf83f1ecca6 100644
> > > --- a/include/media/v4l2-async.h
> > > +++ b/include/media/v4l2-async.h
> > > @@ -161,17 +161,23 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir);
> > >  void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier);
> > >  
> > >  /**
> > > - * v4l2_async_notifier_add_subdev - Add an async subdev to the
> > > + * __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
> > >   *
> > > + * \warning: Drivers should avoid using this function and instead use one of:
> > > + * @v4l2_async_notifier_add_fwnode_subdev,
> > > + * @v4l2_async_notifier_add_fwnode_remote_subdev,
> > > + * @v4l2_async_notifier_add_i2c_subdev or
> > > + * @v4l2_async_notifier_add_devname_subdev.
> > > + *
> > >   * Call this function before registering a notifier to link the provided @asd to
> > >   * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as
> > >   * it will be freed by the framework when the notifier is destroyed.
> > >   */
> > > -int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > > +int __v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
> > >                                    struct v4l2_async_subdev *asd);
> > >  
> > >  /**

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/13] media: Clarify v4l2-async subdevice addition API
  2021-01-14 13:39     ` Ezequiel Garcia
@ 2021-01-15  8:47       ` Sakari Ailus
  0 siblings, 0 replies; 41+ messages in thread
From: Sakari Ailus @ 2021-01-15  8:47 UTC (permalink / raw)
  To: Ezequiel Garcia; +Cc: Laurent Pinchart, linux-media, Hans Verkuil, kernel

On Thu, Jan 14, 2021 at 10:39:33AM -0300, Ezequiel Garcia wrote:
> On Thu, 2021-01-14 at 04:21 +0200, Laurent Pinchart wrote:
> > Hi Ezequiel,
> > 
> > Thank you for the patch.
> > 
> > On Tue, Jan 12, 2021 at 10:23:38AM -0300, Ezequiel Garcia wrote:
> > > Now that most users of v4l2_async_notifier_add_subdev have
> > > been converted, let's fix the documentation so it's more clear
> > > how the v4l2-async API should be used.
> > > 
> > > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > > ---
> > >  .../driver-api/media/v4l2-subdev.rst          | 38 ++++++++++++++++---
> > >  include/media/v4l2-async.h                    | 12 +++++-
> > >  2 files changed, 43 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
> > > index bb5b1a7cdfd9..5ddf9de4fcf7 100644
> > > --- a/Documentation/driver-api/media/v4l2-subdev.rst
> > > +++ b/Documentation/driver-api/media/v4l2-subdev.rst
> > > @@ -204,11 +204,39 @@ Before registering the notifier, bridge drivers must do two things:
> > >  first, the notifier must be initialized using the
> > >  :c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
> > >  begin to form a list of subdevice descriptors that the bridge device
> > > -needs for its operation. Subdevice descriptors are added to the notifier
> > > -using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
> > > -takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
> > > -and a pointer to the subdevice descripter, which is of type struct
> > > -:c:type:`v4l2_async_subdev`.
> > > +needs for its operation. Several functions are available, to
> > > +add subdevice descriptors to a notifier, depending on the type of device:
> > 
> > You could reflow this to
> > 
> > needs for its operation. Several functions are available, to add subdevice
> > descriptors to a notifier, depending on the type of device:
> > 
> > > +:c:func:`v4l2_async_notifier_add_devname_subdev`,
> > > +:c:func:`v4l2_async_notifier_add_fwnode_subdev` or
> > > +:c:func:`v4l2_async_notifier_add_i2c_subdev`.
> > 
> > Should you also list v4l2_async_notifier_add_fwnode_remote_subdev() (and
> 
> Yes.
> 
> > possibly v4l2_async_notifier_parse_fwnode_endpoints()) here ?
> > 
> 
> Unsure. I'd rather not document this one, as it's deprecated
> and we want to remove it.

This document is here to guide people to use the right functions and that
isn't one of them. So it shouldn't be added here.

-- 
Regards,

Sakari Ailus

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

* Re: [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-14  2:06   ` Laurent Pinchart
  2021-01-14 13:36     ` Ezequiel Garcia
@ 2021-01-15 12:12     ` Ezequiel Garcia
  1 sibling, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-15 12:12 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, Hans Verkuil, kernel, Sakari Ailus

Hi Laurent,

On Thu, 2021-01-14 at 04:06 +0200, Laurent Pinchart wrote:
> Hi Ezequiel,
> 
> Thank you for the patch.
> 
> On Tue, Jan 12, 2021 at 10:23:29AM -0300, Ezequiel Garcia wrote:
> > The use of v4l2_async_notifier_add_subdev is discouraged.
> 
> It's not yet, that only happens at the end of the series :-)
> 
> s/is discouraged/will be discouraged/
> 
> > Drivers are instead encouraged to use a helper such as
> > v4l2_async_notifier_add_i2c_subdev.
> > 
> > This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> > should get a kmalloc'ed struct v4l2_async_subdev,
> > removing some boilerplate code while at it.
> > 
> > Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
> > or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
> > the needed setup, instead of open-coding it.
> > 
> > Using v4l2-async to allocate the driver-specific structs,
> > requires to change struct ceu_subdev so the embedded
> > struct v4l2_async_subdev is now the first element.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/platform/renesas-ceu.c | 89 ++++++++++------------------
> >  1 file changed, 31 insertions(+), 58 deletions(-)
> > 
> > diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
> > index 4a633ad0e8fa..18485812a21e 100644
> > --- a/drivers/media/platform/renesas-ceu.c
> > +++ b/drivers/media/platform/renesas-ceu.c
> > @@ -152,8 +152,8 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
> >   * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
> >   */
> >  struct ceu_subdev {
> > -       struct v4l2_subdev *v4l2_sd;
> >         struct v4l2_async_subdev asd;
> > +       struct v4l2_subdev *v4l2_sd;
> >  
> >         /* per-subdevice mbus configuration options */
> >         unsigned int mbus_flags;
> > @@ -174,7 +174,7 @@ struct ceu_device {
> >         struct v4l2_device      v4l2_dev;
> >  
> >         /* subdevices descriptors */
> > -       struct ceu_subdev       *subdevs;
> > +       struct ceu_subdev       **subdevs;
> >         /* the subdevice currently in use */
> >         struct ceu_subdev       *sd;
> >         unsigned int            sd_index;
> > @@ -1195,7 +1195,7 @@ static int ceu_enum_input(struct file *file, void *priv,
> >         if (inp->index >= ceudev->num_sd)
> >                 return -EINVAL;
> >  
> > -       ceusd = &ceudev->subdevs[inp->index];
> > +       ceusd = ceudev->subdevs[inp->index];
> >  
> >         inp->type = V4L2_INPUT_TYPE_CAMERA;
> >         inp->std = 0;
> > @@ -1230,7 +1230,7 @@ static int ceu_s_input(struct file *file, void *priv, unsigned int i)
> >                 return 0;
> >  
> >         ceu_sd_old = ceudev->sd;
> > -       ceudev->sd = &ceudev->subdevs[i];
> > +       ceudev->sd = ceudev->subdevs[i];
> >  
> >         /*
> >          * Make sure we can generate output image formats and apply
> > @@ -1423,7 +1423,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
> >          * ceu formats.
> >          */
> >         if (!ceudev->sd) {
> > -               ceudev->sd = &ceudev->subdevs[0];
> > +               ceudev->sd = ceudev->subdevs[0];
> >                 ceudev->sd_index = 0;
> >         }
> >  
> > @@ -1465,28 +1465,6 @@ static const struct v4l2_async_notifier_operations ceu_notify_ops = {
> >         .complete       = ceu_notify_complete,
> >  };
> >  
> > -/*
> > - * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
> > - *                           ceu device. Both DT and platform data parsing use
> > - *                           this routine.
> > - *
> > - * Returns 0 for success, -ENOMEM for failure.
> > - */
> > -static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
> > -{
> > -       /* Reserve memory for 'n_sd' ceu_subdev descriptors. */
> > -       ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
> > -                                      sizeof(*ceudev->subdevs), GFP_KERNEL);
> 
> I may be missing something, but it looks like the subdevs array isn't
> allocated anymore. It turned to an array of pointers, but it still need
> allocation.
> 

After some thought, I'd say it would be better to leave
ceu_init_async_subdevs() untouched, trying to be as
uninvasive as possible.

Thanks for the catch.

Ezequiel


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

* Re: [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 ` [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
@ 2021-01-16 15:35   ` Jacopo Mondi
  2021-01-16 16:27     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 15:35 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:28AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> which handles the needed setup, instead of open-coding it.
>
> This results in removal of the now unneeded driver-specific state
> struct dcmi_graph_entity, keeping track of just the source
> subdevice.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/platform/stm32/stm32-dcmi.c | 86 ++++++++---------------
>  1 file changed, 30 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
> index b745f1342c2e..142f63d07dcd 100644
> --- a/drivers/media/platform/stm32/stm32-dcmi.c
> +++ b/drivers/media/platform/stm32/stm32-dcmi.c
> @@ -99,13 +99,6 @@ enum state {
>
>  #define OVERRUN_ERROR_THRESHOLD	3
>
> -struct dcmi_graph_entity {
> -	struct v4l2_async_subdev asd;
> -
> -	struct device_node *remote_node;
> -	struct v4l2_subdev *source;
> -};
> -
>  struct dcmi_format {
>  	u32	fourcc;
>  	u32	mbus_code;
> @@ -139,7 +132,7 @@ struct stm32_dcmi {
>  	struct v4l2_device		v4l2_dev;
>  	struct video_device		*vdev;
>  	struct v4l2_async_notifier	notifier;
> -	struct dcmi_graph_entity	entity;
> +	struct v4l2_subdev		*source;
>  	struct v4l2_format		fmt;
>  	struct v4l2_rect		crop;
>  	bool				do_crop;
> @@ -610,7 +603,7 @@ static int dcmi_pipeline_s_fmt(struct stm32_dcmi *dcmi,
>  			       struct v4l2_subdev_pad_config *pad_cfg,
>  			       struct v4l2_subdev_format *format)
>  {
> -	struct media_entity *entity = &dcmi->entity.source->entity;
> +	struct media_entity *entity = &dcmi->source->entity;
>  	struct v4l2_subdev *subdev;
>  	struct media_pad *sink_pad = NULL;
>  	struct media_pad *src_pad = NULL;
> @@ -1018,7 +1011,7 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
>  	}
>
>  	v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
> +	ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
>  			       &pad_cfg, &format);
>  	if (ret < 0)
>  		return ret;
> @@ -1152,7 +1145,7 @@ static int dcmi_get_sensor_format(struct stm32_dcmi *dcmi,
>  	};
>  	int ret;
>
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad, get_fmt, NULL, &fmt);
> +	ret = v4l2_subdev_call(dcmi->source, pad, get_fmt, NULL, &fmt);
>  	if (ret)
>  		return ret;
>
> @@ -1181,7 +1174,7 @@ static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi,
>  	}
>
>  	v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
> +	ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
>  			       &pad_cfg, &format);
>  	if (ret < 0)
>  		return ret;
> @@ -1204,7 +1197,7 @@ static int dcmi_get_sensor_bounds(struct stm32_dcmi *dcmi,
>  	/*
>  	 * Get sensor bounds first
>  	 */
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad, get_selection,
> +	ret = v4l2_subdev_call(dcmi->source, pad, get_selection,
>  			       NULL, &bounds);
>  	if (!ret)
>  		*r = bounds.r;
> @@ -1385,7 +1378,7 @@ static int dcmi_enum_framesizes(struct file *file, void *fh,
>
>  	fse.code = sd_fmt->mbus_code;
>
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad, enum_frame_size,
> +	ret = v4l2_subdev_call(dcmi->source, pad, enum_frame_size,
>  			       NULL, &fse);
>  	if (ret)
>  		return ret;
> @@ -1402,7 +1395,7 @@ static int dcmi_g_parm(struct file *file, void *priv,
>  {
>  	struct stm32_dcmi *dcmi = video_drvdata(file);
>
> -	return v4l2_g_parm_cap(video_devdata(file), dcmi->entity.source, p);
> +	return v4l2_g_parm_cap(video_devdata(file), dcmi->source, p);
>  }
>
>  static int dcmi_s_parm(struct file *file, void *priv,
> @@ -1410,7 +1403,7 @@ static int dcmi_s_parm(struct file *file, void *priv,
>  {
>  	struct stm32_dcmi *dcmi = video_drvdata(file);
>
> -	return v4l2_s_parm_cap(video_devdata(file), dcmi->entity.source, p);
> +	return v4l2_s_parm_cap(video_devdata(file), dcmi->source, p);
>  }
>
>  static int dcmi_enum_frameintervals(struct file *file, void *fh,
> @@ -1432,7 +1425,7 @@ static int dcmi_enum_frameintervals(struct file *file, void *fh,
>
>  	fie.code = sd_fmt->mbus_code;
>
> -	ret = v4l2_subdev_call(dcmi->entity.source, pad,
> +	ret = v4l2_subdev_call(dcmi->source, pad,
>  			       enum_frame_interval, NULL, &fie);
>  	if (ret)
>  		return ret;
> @@ -1452,7 +1445,7 @@ MODULE_DEVICE_TABLE(of, stm32_dcmi_of_match);
>  static int dcmi_open(struct file *file)
>  {
>  	struct stm32_dcmi *dcmi = video_drvdata(file);
> -	struct v4l2_subdev *sd = dcmi->entity.source;
> +	struct v4l2_subdev *sd = dcmi->source;
>  	int ret;
>
>  	if (mutex_lock_interruptible(&dcmi->lock))
> @@ -1483,7 +1476,7 @@ static int dcmi_open(struct file *file)
>  static int dcmi_release(struct file *file)
>  {
>  	struct stm32_dcmi *dcmi = video_drvdata(file);
> -	struct v4l2_subdev *sd = dcmi->entity.source;
> +	struct v4l2_subdev *sd = dcmi->source;
>  	bool fh_singular;
>  	int ret;
>
> @@ -1616,7 +1609,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
>  {
>  	const struct dcmi_format *sd_fmts[ARRAY_SIZE(dcmi_formats)];
>  	unsigned int num_fmts = 0, i, j;
> -	struct v4l2_subdev *subdev = dcmi->entity.source;
> +	struct v4l2_subdev *subdev = dcmi->source;
>  	struct v4l2_subdev_mbus_code_enum mbus_code = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> @@ -1675,7 +1668,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
>  static int dcmi_framesizes_init(struct stm32_dcmi *dcmi)
>  {
>  	unsigned int num_fsize = 0;
> -	struct v4l2_subdev *subdev = dcmi->entity.source;
> +	struct v4l2_subdev *subdev = dcmi->source;
>  	struct v4l2_subdev_frame_size_enum fse = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  		.code = dcmi->sd_format->mbus_code,
> @@ -1727,14 +1720,13 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
>  	 * we search for the source subdevice
>  	 * in order to expose it through V4L2 interface
>  	 */
> -	dcmi->entity.source =
> -		media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
> -	if (!dcmi->entity.source) {
> +	dcmi->source = media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
> +	if (!dcmi->source) {
>  		dev_err(dcmi->dev, "Source subdevice not found\n");
>  		return -ENODEV;
>  	}
>
> -	dcmi->vdev->ctrl_handler = dcmi->entity.source->ctrl_handler;
> +	dcmi->vdev->ctrl_handler = dcmi->source->ctrl_handler;
>
>  	ret = dcmi_formats_init(dcmi);
>  	if (ret) {
> @@ -1813,46 +1805,28 @@ static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = {
>  	.complete = dcmi_graph_notify_complete,
>  };
>
> -static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
> -{
> -	struct device_node *ep = NULL;
> -	struct device_node *remote;
> -
> -	ep = of_graph_get_next_endpoint(node, ep);
> -	if (!ep)
> -		return -EINVAL;
> -
> -	remote = of_graph_get_remote_port_parent(ep);
> -	of_node_put(ep);
> -	if (!remote)
> -		return -EINVAL;
> -
> -	/* Remote node to connect */
> -	dcmi->entity.remote_node = remote;
> -	dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
> -	return 0;
> -}
> -
>  static int dcmi_graph_init(struct stm32_dcmi *dcmi)
>  {
> +	struct v4l2_async_subdev *asd;
> +	struct device_node *ep;
>  	int ret;
>
> -	/* Parse the graph to extract a list of subdevice DT nodes. */
> -	ret = dcmi_graph_parse(dcmi, dcmi->dev->of_node);
> -	if (ret < 0) {
> -		dev_err(dcmi->dev, "Failed to parse graph\n");
> -		return ret;
> +	ep = of_graph_get_next_endpoint(dcmi->dev->of_node, NULL);
> +	if (!ep) {
> +		dev_err(dcmi->dev, "Failed to get next endpoint\n");
> +		return -EINVAL;

Maybe -ENODEV, but I'm not sure we have any convention here, so do
what you like the most :)

>  	}
>
>  	v4l2_async_notifier_init(&dcmi->notifier);
>
> -	ret = v4l2_async_notifier_add_subdev(&dcmi->notifier,
> -					     &dcmi->entity.asd);
> -	if (ret) {
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +		&dcmi->notifier, of_fwnode_handle(ep), sizeof(*asd));

&dcmi->notifier might fit on the the previous line, but it's a matter
of tastes.

I don't have hw to test, but it looks good at a first look
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
   j

> +
> +	of_node_put(ep);
> +
> +	if (IS_ERR(asd)) {
>  		dev_err(dcmi->dev, "Failed to add subdev notifier\n");
> -		of_node_put(dcmi->entity.remote_node);
> -		return ret;
> +		return PTR_ERR(asd);
>  	}
>
>  	dcmi->notifier.ops = &dcmi_graph_notify_ops;
> --
> 2.29.2
>

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

* Re: [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 ` [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
  2021-01-14  2:06   ` Laurent Pinchart
@ 2021-01-16 15:56   ` Jacopo Mondi
  1 sibling, 0 replies; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 15:56 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:29AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_i2c_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
> or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
> the needed setup, instead of open-coding it.
>
> Using v4l2-async to allocate the driver-specific structs,
> requires to change struct ceu_subdev so the embedded
> struct v4l2_async_subdev is now the first element.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/platform/renesas-ceu.c | 89 ++++++++++------------------
>  1 file changed, 31 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c
> index 4a633ad0e8fa..18485812a21e 100644
> --- a/drivers/media/platform/renesas-ceu.c
> +++ b/drivers/media/platform/renesas-ceu.c
> @@ -152,8 +152,8 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)
>   * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
>   */
>  struct ceu_subdev {
> -	struct v4l2_subdev *v4l2_sd;
>  	struct v4l2_async_subdev asd;
> +	struct v4l2_subdev *v4l2_sd;
>
>  	/* per-subdevice mbus configuration options */
>  	unsigned int mbus_flags;
> @@ -174,7 +174,7 @@ struct ceu_device {
>  	struct v4l2_device	v4l2_dev;
>
>  	/* subdevices descriptors */
> -	struct ceu_subdev	*subdevs;
> +	struct ceu_subdev	**subdevs;
>  	/* the subdevice currently in use */
>  	struct ceu_subdev	*sd;
>  	unsigned int		sd_index;
> @@ -1195,7 +1195,7 @@ static int ceu_enum_input(struct file *file, void *priv,
>  	if (inp->index >= ceudev->num_sd)
>  		return -EINVAL;
>
> -	ceusd = &ceudev->subdevs[inp->index];
> +	ceusd = ceudev->subdevs[inp->index];
>
>  	inp->type = V4L2_INPUT_TYPE_CAMERA;
>  	inp->std = 0;
> @@ -1230,7 +1230,7 @@ static int ceu_s_input(struct file *file, void *priv, unsigned int i)
>  		return 0;
>
>  	ceu_sd_old = ceudev->sd;
> -	ceudev->sd = &ceudev->subdevs[i];
> +	ceudev->sd = ceudev->subdevs[i];
>
>  	/*
>  	 * Make sure we can generate output image formats and apply
> @@ -1423,7 +1423,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
>  	 * ceu formats.
>  	 */
>  	if (!ceudev->sd) {
> -		ceudev->sd = &ceudev->subdevs[0];
> +		ceudev->sd = ceudev->subdevs[0];
>  		ceudev->sd_index = 0;
>  	}
>
> @@ -1465,28 +1465,6 @@ static const struct v4l2_async_notifier_operations ceu_notify_ops = {
>  	.complete	= ceu_notify_complete,
>  };
>
> -/*
> - * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
> - *			      ceu device. Both DT and platform data parsing use
> - *			      this routine.
> - *
> - * Returns 0 for success, -ENOMEM for failure.
> - */
> -static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)
> -{
> -	/* Reserve memory for 'n_sd' ceu_subdev descriptors. */
> -	ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,
> -				       sizeof(*ceudev->subdevs), GFP_KERNEL);
> -	if (!ceudev->subdevs)
> -		return -ENOMEM;
> -
> -	ceudev->sd = NULL;
> -	ceudev->sd_index = 0;
> -	ceudev->num_sd = 0;
> -

As Laurent the array of subdevs still needs to be allocated, and the
zeroing of the ceudev fields could be removed. If you don't want to
mix too many things I can do it on top as..

> -	return 0;
> -}
> -

[snip]

>  		}
>
>  		/* Setup the ceu subdevice and the async subdevice. */
> -		ceu_sd = &ceudev->subdevs[i];
> -		INIT_LIST_HEAD(&ceu_sd->asd.list);
> -
> -		remote = of_graph_get_remote_port_parent(ep);
> -		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
> -		ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -		ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
> -
> -		ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
> -						     &ceu_sd->asd);
> -		if (ret) {
> -			of_node_put(remote);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +				&ceudev->notifier, of_fwnode_handle(ep),
> +				sizeof(*ceu_sd));
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);

This could also probably be moved before the endpoint parsing to
avoid that if the async subdev registration fails.

All on top though and not major.
With the subdev allocation fixed
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

>  			goto error_cleanup;
>  		}
> +		ceu_sd = to_ceu_subdev(asd);
> +		ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
> +		ceudev->subdevs[i] = ceu_sd;
>
>  		of_node_put(ep);
>  	}
> --
> 2.29.2
>

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

* Re: [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev
  2021-01-12 13:23 ` [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev Ezequiel Garcia
@ 2021-01-16 16:07   ` Jacopo Mondi
  2021-01-16 16:55     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 16:07 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel

On Tue, Jan 12, 2021 at 10:23:30AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> which handles the needed setup, instead of open-coding it.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/platform/exynos4-is/media-dev.c | 25 +++++++++----------
>  drivers/media/platform/exynos4-is/media-dev.h |  2 +-
>  2 files changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> index e636c33e847b..196166a9a4e5 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.c
> +++ b/drivers/media/platform/exynos4-is/media-dev.c
> @@ -401,6 +401,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
>  	int index = fmd->num_sensors;
>  	struct fimc_source_info *pd = &fmd->sensor[index].pdata;
>  	struct device_node *rem, *np;
> +	struct v4l2_async_subdev *asd;
>  	struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
>  	int ret;
>
> @@ -418,7 +419,6 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
>  	pd->mux_id = (endpoint.base.port - 1) & 0x1;
>
>  	rem = of_graph_get_remote_port_parent(ep);
> -	of_node_put(ep);

If you remove it from here, don't forget to put it in the here below
error path

>  	if (rem == NULL) {

>  		v4l2_info(&fmd->v4l2_dev, "Remote device at %pOF not found\n",
>  							ep);
> @@ -450,6 +450,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
>  	 * checking parent's node name.
>  	 */
>  	np = of_get_parent(rem);
> +	of_node_put(rem);

unrelated but good
>
>  	if (of_node_name_eq(np, "i2c-isp"))
>  		pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
> @@ -457,21 +458,18 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
>  		pd->fimc_bus_type = pd->sensor_bus_type;
>  	of_node_put(np);
>
> -	if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {
> -		of_node_put(rem);

I think if you need to keep 'ep' around until the call to
v4l2_async_notifier_add_fwnode_remote_subdev() below, it should be put
here as you remove the above of_node_put(ep).

I wonder if registering the async subdev before parsing the endpoint
would make things simpler. Not required for this patch though.

> +	if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
>  		return -EINVAL;
> -	}
>
> -	fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +		&fmd->subdev_notifier, of_fwnode_handle(ep), sizeof(*asd));
>
> -	ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier,
> -					     &fmd->sensor[index].asd);
> -	if (ret) {
> -		of_node_put(rem);
> -		return ret;
> -	}
> +	of_node_put(ep);
> +
> +	if (IS_ERR(asd))
> +		return PTR_ERR(asd);
>
> +	fmd->sensor[index].asd = asd;
>  	fmd->num_sensors++;
>
>  	return 0;
> @@ -1381,7 +1379,8 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
>
>  	/* Find platform data for this sensor subdev */
>  	for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
> -		if (fmd->sensor[i].asd.match.fwnode ==
> +		if (fmd->sensor[i].asd &&

Is this needed ? If the subdev has bound the async subdev has been
allocated correctly, doesn't it ?

With the ep ref counting clarified
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j


> +		    fmd->sensor[i].asd->match.fwnode ==
>  		    of_fwnode_handle(subdev->dev->of_node))
>  			si = &fmd->sensor[i];
>
> diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
> index 9447fafe23c6..a3876d668ea6 100644
> --- a/drivers/media/platform/exynos4-is/media-dev.h
> +++ b/drivers/media/platform/exynos4-is/media-dev.h
> @@ -83,7 +83,7 @@ struct fimc_camclk_info {
>   */
>  struct fimc_sensor_info {
>  	struct fimc_source_info pdata;
> -	struct v4l2_async_subdev asd;
> +	struct v4l2_async_subdev *asd;
>  	struct v4l2_subdev *subdev;
>  	struct fimc_dev *host;
>  };
> --
> 2.29.2
>

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

* Re: [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 ` [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
@ 2021-01-16 16:23   ` Jacopo Mondi
  0 siblings, 0 replies; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 16:23 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:31AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> which handles the needed setup, instead of open-coding it.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>

I don't have hw to test this, but it looks good!
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

> ---
>  drivers/media/i2c/st-mipid02.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c
> index 003ba22334cd..9e04ff02257c 100644
> --- a/drivers/media/i2c/st-mipid02.c
> +++ b/drivers/media/i2c/st-mipid02.c
> @@ -92,7 +92,6 @@ struct mipid02_dev {
>  	u64 link_frequency;
>  	struct v4l2_fwnode_endpoint tx;
>  	/* remote source */
> -	struct v4l2_async_subdev asd;
>  	struct v4l2_async_notifier notifier;
>  	struct v4l2_subdev *s_subdev;
>  	/* registers */
> @@ -844,6 +843,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
>  {
>  	struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
>  	struct i2c_client *client = bridge->i2c_client;
> +	struct v4l2_async_subdev *asd;
>  	struct device_node *ep_node;
>  	int ret;
>
> @@ -875,17 +875,17 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
>  	bridge->rx = ep;
>
>  	/* register async notifier so we get noticed when sensor is connected */
> -	bridge->asd.match.fwnode =
> -		fwnode_graph_get_remote_port_parent(of_fwnode_handle(ep_node));
> -	bridge->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> +	v4l2_async_notifier_init(&bridge->notifier);
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +					&bridge->notifier,
> +					of_fwnode_handle(ep_node),
> +					sizeof(*asd));
>  	of_node_put(ep_node);
>
> -	v4l2_async_notifier_init(&bridge->notifier);
> -	ret = v4l2_async_notifier_add_subdev(&bridge->notifier, &bridge->asd);
> -	if (ret) {
> +	if (IS_ERR(asd)) {
> +		ret = PTR_ERR(asd);
>  		dev_err(&client->dev, "fail to register asd to notifier %d",
>  			ret);
> -		fwnode_handle_put(bridge->asd.match.fwnode);
>  		return ret;
>  	}
>  	bridge->notifier.ops = &mipid02_notifier_ops;
> --
> 2.29.2
>

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

* Re: [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-16 15:35   ` Jacopo Mondi
@ 2021-01-16 16:27     ` Ezequiel Garcia
  0 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-16 16:27 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

On Sat, 2021-01-16 at 16:35 +0100, Jacopo Mondi wrote:
> Hi Ezequiel,
> 
> On Tue, Jan 12, 2021 at 10:23:28AM -0300, Ezequiel Garcia wrote:
> > The use of v4l2_async_notifier_add_subdev is discouraged.
> > Drivers are instead encouraged to use a helper such as
> > v4l2_async_notifier_add_fwnode_remote_subdev.
> > 
> > This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> > should get a kmalloc'ed struct v4l2_async_subdev,
> > removing some boilerplate code while at it.
> > 
> > Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> > which handles the needed setup, instead of open-coding it.
> > 
> > This results in removal of the now unneeded driver-specific state
> > struct dcmi_graph_entity, keeping track of just the source
> > subdevice.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/platform/stm32/stm32-dcmi.c | 86 ++++++++---------------
> >  1 file changed, 30 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
> > index b745f1342c2e..142f63d07dcd 100644
> > --- a/drivers/media/platform/stm32/stm32-dcmi.c
> > +++ b/drivers/media/platform/stm32/stm32-dcmi.c
> > @@ -99,13 +99,6 @@ enum state {
> > 
> >  #define OVERRUN_ERROR_THRESHOLD        3
> > 
> > -struct dcmi_graph_entity {
> > -       struct v4l2_async_subdev asd;
> > -
> > -       struct device_node *remote_node;
> > -       struct v4l2_subdev *source;
> > -};
> > -
> >  struct dcmi_format {
> >         u32     fourcc;
> >         u32     mbus_code;
> > @@ -139,7 +132,7 @@ struct stm32_dcmi {
> >         struct v4l2_device              v4l2_dev;
> >         struct video_device             *vdev;
> >         struct v4l2_async_notifier      notifier;
> > -       struct dcmi_graph_entity        entity;
> > +       struct v4l2_subdev              *source;
> >         struct v4l2_format              fmt;
> >         struct v4l2_rect                crop;
> >         bool                            do_crop;
> > @@ -610,7 +603,7 @@ static int dcmi_pipeline_s_fmt(struct stm32_dcmi *dcmi,
> >                                struct v4l2_subdev_pad_config *pad_cfg,
> >                                struct v4l2_subdev_format *format)
> >  {
> > -       struct media_entity *entity = &dcmi->entity.source->entity;
> > +       struct media_entity *entity = &dcmi->source->entity;
> >         struct v4l2_subdev *subdev;
> >         struct media_pad *sink_pad = NULL;
> >         struct media_pad *src_pad = NULL;
> > @@ -1018,7 +1011,7 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
> >         }
> > 
> >         v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
> > +       ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
> >                                &pad_cfg, &format);
> >         if (ret < 0)
> >                 return ret;
> > @@ -1152,7 +1145,7 @@ static int dcmi_get_sensor_format(struct stm32_dcmi *dcmi,
> >         };
> >         int ret;
> > 
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad, get_fmt, NULL, &fmt);
> > +       ret = v4l2_subdev_call(dcmi->source, pad, get_fmt, NULL, &fmt);
> >         if (ret)
> >                 return ret;
> > 
> > @@ -1181,7 +1174,7 @@ static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi,
> >         }
> > 
> >         v4l2_fill_mbus_format(&format.format, pix, sd_fmt->mbus_code);
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad, set_fmt,
> > +       ret = v4l2_subdev_call(dcmi->source, pad, set_fmt,
> >                                &pad_cfg, &format);
> >         if (ret < 0)
> >                 return ret;
> > @@ -1204,7 +1197,7 @@ static int dcmi_get_sensor_bounds(struct stm32_dcmi *dcmi,
> >         /*
> >          * Get sensor bounds first
> >          */
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad, get_selection,
> > +       ret = v4l2_subdev_call(dcmi->source, pad, get_selection,
> >                                NULL, &bounds);
> >         if (!ret)
> >                 *r = bounds.r;
> > @@ -1385,7 +1378,7 @@ static int dcmi_enum_framesizes(struct file *file, void *fh,
> > 
> >         fse.code = sd_fmt->mbus_code;
> > 
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad, enum_frame_size,
> > +       ret = v4l2_subdev_call(dcmi->source, pad, enum_frame_size,
> >                                NULL, &fse);
> >         if (ret)
> >                 return ret;
> > @@ -1402,7 +1395,7 @@ static int dcmi_g_parm(struct file *file, void *priv,
> >  {
> >         struct stm32_dcmi *dcmi = video_drvdata(file);
> > 
> > -       return v4l2_g_parm_cap(video_devdata(file), dcmi->entity.source, p);
> > +       return v4l2_g_parm_cap(video_devdata(file), dcmi->source, p);
> >  }
> > 
> >  static int dcmi_s_parm(struct file *file, void *priv,
> > @@ -1410,7 +1403,7 @@ static int dcmi_s_parm(struct file *file, void *priv,
> >  {
> >         struct stm32_dcmi *dcmi = video_drvdata(file);
> > 
> > -       return v4l2_s_parm_cap(video_devdata(file), dcmi->entity.source, p);
> > +       return v4l2_s_parm_cap(video_devdata(file), dcmi->source, p);
> >  }
> > 
> >  static int dcmi_enum_frameintervals(struct file *file, void *fh,
> > @@ -1432,7 +1425,7 @@ static int dcmi_enum_frameintervals(struct file *file, void *fh,
> > 
> >         fie.code = sd_fmt->mbus_code;
> > 
> > -       ret = v4l2_subdev_call(dcmi->entity.source, pad,
> > +       ret = v4l2_subdev_call(dcmi->source, pad,
> >                                enum_frame_interval, NULL, &fie);
> >         if (ret)
> >                 return ret;
> > @@ -1452,7 +1445,7 @@ MODULE_DEVICE_TABLE(of, stm32_dcmi_of_match);
> >  static int dcmi_open(struct file *file)
> >  {
> >         struct stm32_dcmi *dcmi = video_drvdata(file);
> > -       struct v4l2_subdev *sd = dcmi->entity.source;
> > +       struct v4l2_subdev *sd = dcmi->source;
> >         int ret;
> > 
> >         if (mutex_lock_interruptible(&dcmi->lock))
> > @@ -1483,7 +1476,7 @@ static int dcmi_open(struct file *file)
> >  static int dcmi_release(struct file *file)
> >  {
> >         struct stm32_dcmi *dcmi = video_drvdata(file);
> > -       struct v4l2_subdev *sd = dcmi->entity.source;
> > +       struct v4l2_subdev *sd = dcmi->source;
> >         bool fh_singular;
> >         int ret;
> > 
> > @@ -1616,7 +1609,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
> >  {
> >         const struct dcmi_format *sd_fmts[ARRAY_SIZE(dcmi_formats)];
> >         unsigned int num_fmts = 0, i, j;
> > -       struct v4l2_subdev *subdev = dcmi->entity.source;
> > +       struct v4l2_subdev *subdev = dcmi->source;
> >         struct v4l2_subdev_mbus_code_enum mbus_code = {
> >                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >         };
> > @@ -1675,7 +1668,7 @@ static int dcmi_formats_init(struct stm32_dcmi *dcmi)
> >  static int dcmi_framesizes_init(struct stm32_dcmi *dcmi)
> >  {
> >         unsigned int num_fsize = 0;
> > -       struct v4l2_subdev *subdev = dcmi->entity.source;
> > +       struct v4l2_subdev *subdev = dcmi->source;
> >         struct v4l2_subdev_frame_size_enum fse = {
> >                 .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >                 .code = dcmi->sd_format->mbus_code,
> > @@ -1727,14 +1720,13 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier)
> >          * we search for the source subdevice
> >          * in order to expose it through V4L2 interface
> >          */
> > -       dcmi->entity.source =
> > -               media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
> > -       if (!dcmi->entity.source) {
> > +       dcmi->source = media_entity_to_v4l2_subdev(dcmi_find_source(dcmi));
> > +       if (!dcmi->source) {
> >                 dev_err(dcmi->dev, "Source subdevice not found\n");
> >                 return -ENODEV;
> >         }
> > 
> > -       dcmi->vdev->ctrl_handler = dcmi->entity.source->ctrl_handler;
> > +       dcmi->vdev->ctrl_handler = dcmi->source->ctrl_handler;
> > 
> >         ret = dcmi_formats_init(dcmi);
> >         if (ret) {
> > @@ -1813,46 +1805,28 @@ static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = {
> >         .complete = dcmi_graph_notify_complete,
> >  };
> > 
> > -static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node)
> > -{
> > -       struct device_node *ep = NULL;
> > -       struct device_node *remote;
> > -
> > -       ep = of_graph_get_next_endpoint(node, ep);
> > -       if (!ep)
> > -               return -EINVAL;
> > -
> > -       remote = of_graph_get_remote_port_parent(ep);
> > -       of_node_put(ep);
> > -       if (!remote)
> > -               return -EINVAL;
> > -
> > -       /* Remote node to connect */
> > -       dcmi->entity.remote_node = remote;
> > -       dcmi->entity.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> > -       dcmi->entity.asd.match.fwnode = of_fwnode_handle(remote);
> > -       return 0;
> > -}
> > -
> >  static int dcmi_graph_init(struct stm32_dcmi *dcmi)
> >  {
> > +       struct v4l2_async_subdev *asd;
> > +       struct device_node *ep;
> >         int ret;
> > 
> > -       /* Parse the graph to extract a list of subdevice DT nodes. */
> > -       ret = dcmi_graph_parse(dcmi, dcmi->dev->of_node);
> > -       if (ret < 0) {
> > -               dev_err(dcmi->dev, "Failed to parse graph\n");
> > -               return ret;
> > +       ep = of_graph_get_next_endpoint(dcmi->dev->of_node, NULL);
> > +       if (!ep) {
> > +               dev_err(dcmi->dev, "Failed to get next endpoint\n");
> > +               return -EINVAL;
> 
> Maybe -ENODEV, but I'm not sure we have any convention here, so do
> what you like the most :)
> 

You are arguably right, but I've chosen not to change the errnos.
You never know what applications are doing, and this way is safer.

> >         }
> > 
> >         v4l2_async_notifier_init(&dcmi->notifier);
> > 
> > -       ret = v4l2_async_notifier_add_subdev(&dcmi->notifier,
> > -                                            &dcmi->entity.asd);
> > -       if (ret) {
> > +       asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> > +               &dcmi->notifier, of_fwnode_handle(ep), sizeof(*asd));
> 
> &dcmi->notifier might fit on the the previous line, but it's a matter
> of tastes.
> 
> I don't have hw to test, but it looks good at a first look
> Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> 

Thanks a lot,
Ezequiel


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

* Re: [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev
  2021-01-16 16:07   ` Jacopo Mondi
@ 2021-01-16 16:55     ` Ezequiel Garcia
  0 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-16 16:55 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

On Sat, 2021-01-16 at 17:07 +0100, Jacopo Mondi wrote:
> Hi Ezequiel
> 
> On Tue, Jan 12, 2021 at 10:23:30AM -0300, Ezequiel Garcia wrote:
> > The use of v4l2_async_notifier_add_subdev is discouraged.
> > Drivers are instead encouraged to use a helper such as
> > v4l2_async_notifier_add_fwnode_remote_subdev.
> > 
> > This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> > should get a kmalloc'ed struct v4l2_async_subdev,
> > removing some boilerplate code while at it.
> > 
> > Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> > which handles the needed setup, instead of open-coding it.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/platform/exynos4-is/media-dev.c | 25 +++++++++----------
> >  drivers/media/platform/exynos4-is/media-dev.h |  2 +-
> >  2 files changed, 13 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> > index e636c33e847b..196166a9a4e5 100644
> > --- a/drivers/media/platform/exynos4-is/media-dev.c
> > +++ b/drivers/media/platform/exynos4-is/media-dev.c
> > @@ -401,6 +401,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
> >         int index = fmd->num_sensors;
> >         struct fimc_source_info *pd = &fmd->sensor[index].pdata;
> >         struct device_node *rem, *np;
> > +       struct v4l2_async_subdev *asd;
> >         struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 };
> >         int ret;
> > 
> > @@ -418,7 +419,6 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
> >         pd->mux_id = (endpoint.base.port - 1) & 0x1;
> > 
> >         rem = of_graph_get_remote_port_parent(ep);
> > -       of_node_put(ep);
> 
> If you remove it from here, don't forget to put it in the here below
> error path
> 

Oops, think you are right.

> >         if (rem == NULL) {
> 
> >                 v4l2_info(&fmd->v4l2_dev, "Remote device at %pOF not found\n",
> >                                                         ep);
> > @@ -450,6 +450,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
> >          * checking parent's node name.
> >          */
> >         np = of_get_parent(rem);
> > +       of_node_put(rem);
> 
> unrelated but good
> > 
> >         if (of_node_name_eq(np, "i2c-isp"))
> >                 pd->fimc_bus_type = FIMC_BUS_TYPE_ISP_WRITEBACK;
> > @@ -457,21 +458,18 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd,
> >                 pd->fimc_bus_type = pd->sensor_bus_type;
> >         of_node_put(np);
> > 
> > -       if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) {
> > -               of_node_put(rem);
> 
> I think if you need to keep 'ep' around until the call to
> v4l2_async_notifier_add_fwnode_remote_subdev() below, it should be put
> here as you remove the above of_node_put(ep).
> 
> I wonder if registering the async subdev before parsing the endpoint
> would make things simpler. Not required for this patch though.
> 

I have tried to make these conversions simple, and let the
people with hardware do more interesting cleanups.

> > +       if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
> >                 return -EINVAL;
> > -       }
> > 
> > -       fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> > -       fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem);
> > +       asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> > +               &fmd->subdev_notifier, of_fwnode_handle(ep), sizeof(*asd));
> > 
> > -       ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier,
> > -                                            &fmd->sensor[index].asd);
> > -       if (ret) {
> > -               of_node_put(rem);
> > -               return ret;
> > -       }
> > +       of_node_put(ep);
> > +
> > +       if (IS_ERR(asd))
> > +               return PTR_ERR(asd);
> > 
> > +       fmd->sensor[index].asd = asd;
> >         fmd->num_sensors++;
> > 
> >         return 0;
> > @@ -1381,7 +1379,8 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> > 
> >         /* Find platform data for this sensor subdev */
> >         for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
> > -               if (fmd->sensor[i].asd.match.fwnode ==
> > +               if (fmd->sensor[i].asd &&
> 
> Is this needed ? If the subdev has bound the async subdev has been
> allocated correctly, doesn't it ?
> 

The idea is to keep the code the same. You are probably right,
and the above felt quite nasty, but then again, didn't
want to go down the cleanup road.

> With the ep ref counting clarified

Sure.

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

Thanks a lot,
Ezequiel


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

* Re: [PATCH 06/13] media: atmel: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 ` [PATCH 06/13] media: atmel: " Ezequiel Garcia
@ 2021-01-16 17:21   ` Jacopo Mondi
  2021-01-17 17:57     ` Ezequiel Garcia
  0 siblings, 1 reply; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 17:21 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:32AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> ---
>  drivers/media/platform/atmel/atmel-isc.h      |  1 +
>  drivers/media/platform/atmel/atmel-isi.c      | 46 ++++++-------------
>  .../media/platform/atmel/atmel-sama5d2-isc.c  | 44 ++++++------------
>  3 files changed, 29 insertions(+), 62 deletions(-)
>
>  	}
>

[snip]

>  	list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
> +		struct v4l2_async_subdev *asd;
> +
>  		v4l2_async_notifier_init(&subdev_entity->notifier);
>
> -		ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier,
> -						     subdev_entity->asd);
> -		if (ret) {
> -			fwnode_handle_put(subdev_entity->asd->match.fwnode);
> -			kfree(subdev_entity->asd);
> +		asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> +					&subdev_entity->notifier,
> +					of_fwnode_handle(subdev_entity->epn),
> +					sizeof(*asd));
> +
> +		of_node_put(subdev_entity->epn);
> +		subdev_entity->epn = NULL;
> +
> +		if (IS_ERR(asd)) {
> +			ret = PTR_ERR(asd);
>  			goto cleanup_subdev;

The isc_subdev_cleanup() this label jumps to does not put the other
subdev_entity->epn

The issue was there already if I'm not mistaken. If I'm not, I think
it's worth recording it with a FIXME: comment while you're here

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

Thanks
  j

>  		}
>
> --
> 2.29.2
>

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

* Re: [PATCH 07/13] media: cdns-csi2rx: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-12 13:23 ` [PATCH 07/13] media: cdns-csi2rx: " Ezequiel Garcia
@ 2021-01-16 17:23   ` Jacopo Mondi
  0 siblings, 0 replies; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 17:23 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:33AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper v4l2_async_notifier_add_fwnode_remote_subdev,
> which handles the needed setup, instead of open-coding it.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>

Seems good!
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j
> ---
>  drivers/media/platform/cadence/cdns-csi2rx.c | 16 ++++++----------
>  1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
> index be9ec59774d6..7d299cacef8c 100644
> --- a/drivers/media/platform/cadence/cdns-csi2rx.c
> +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
> @@ -81,7 +81,6 @@ struct csi2rx_priv {
>  	struct media_pad		pads[CSI2RX_PAD_MAX];
>
>  	/* Remote source */
> -	struct v4l2_async_subdev	asd;
>  	struct v4l2_subdev		*source_subdev;
>  	int				source_pad;
>  };
> @@ -362,6 +361,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx,
>  static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>  {
>  	struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
> +	struct v4l2_async_subdev *asd;
>  	struct fwnode_handle *fwh;
>  	struct device_node *ep;
>  	int ret;
> @@ -395,17 +395,13 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx)
>  		return -EINVAL;
>  	}
>
> -	csi2rx->asd.match.fwnode = fwnode_graph_get_remote_port_parent(fwh);
> -	csi2rx->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	of_node_put(ep);
> -
>  	v4l2_async_notifier_init(&csi2rx->notifier);
>
> -	ret = v4l2_async_notifier_add_subdev(&csi2rx->notifier, &csi2rx->asd);
> -	if (ret) {
> -		fwnode_handle_put(csi2rx->asd.match.fwnode);
> -		return ret;
> -	}
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi2rx->notifier,
> +							   fwh, sizeof(*asd));
> +	of_node_put(ep);
> +	if (IS_ERR(asd))
> +		return PTR_ERR(asd);
>
>  	csi2rx->notifier.ops = &csi2rx_notifier_ops;
>
> --
> 2.29.2
>

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

* Re: [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers
  2021-01-12 13:23 ` [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
@ 2021-01-16 17:36   ` Jacopo Mondi
  0 siblings, 0 replies; 41+ messages in thread
From: Jacopo Mondi @ 2021-01-16 17:36 UTC (permalink / raw)
  To: Ezequiel Garcia
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

Hi Ezequiel,

On Tue, Jan 12, 2021 at 10:23:34AM -0300, Ezequiel Garcia wrote:
> The use of v4l2_async_notifier_add_subdev is discouraged.
> Drivers are instead encouraged to use a helper such as
> v4l2_async_notifier_add_fwnode_remote_subdev.
>
> This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> should get a kmalloc'ed struct v4l2_async_subdev,
> removing some boilerplate code while at it.
>
> Use the appropriate helper: v4l2_async_notifier_add_i2c_subdev
> or v4l2_async_notifier_add_fwnode_remote_subdev, which handles
> the needed setup, instead of open-coding it.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>

looks good, thanks
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
   j

> ---
>  drivers/media/platform/marvell-ccic/cafe-driver.c | 14 +++++++++++---
>  drivers/media/platform/marvell-ccic/mcam-core.c   | 10 ----------
>  drivers/media/platform/marvell-ccic/mcam-core.h   |  1 -
>  drivers/media/platform/marvell-ccic/mmp-driver.c  | 11 ++++++++---
>  4 files changed, 19 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c
> index 00f623d62c96..91d65f71be96 100644
> --- a/drivers/media/platform/marvell-ccic/cafe-driver.c
> +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
> @@ -489,6 +489,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  	int ret;
>  	struct cafe_camera *cam;
>  	struct mcam_camera *mcam;
> +	struct v4l2_async_subdev *asd;
>
>  	/*
>  	 * Start putting together one of our big camera structures.
> @@ -546,9 +547,16 @@ static int cafe_pci_probe(struct pci_dev *pdev,
>  	if (ret)
>  		goto out_pdown;
>
> -	mcam->asd.match_type = V4L2_ASYNC_MATCH_I2C;
> -	mcam->asd.match.i2c.adapter_id = i2c_adapter_id(cam->i2c_adapter);
> -	mcam->asd.match.i2c.address = ov7670_info.addr;
> +	v4l2_async_notifier_init(&mcam->notifier);
> +
> +	asd = v4l2_async_notifier_add_i2c_subdev(&mcam->notifier,
> +					i2c_adapter_id(cam->i2c_adapter),
> +					ov7670_info.addr,
> +					sizeof(*asd));
> +	if (IS_ERR(asd)) {
> +		ret = PTR_ERR(asd);
> +		goto out_smbus_shutdown;
> +	}
>
>  	ret = mccic_register(mcam);
>  	if (ret)
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index c012fd2e1d29..153277e4fe80 100644
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -1866,16 +1866,6 @@ int mccic_register(struct mcam_camera *cam)
>  	cam->pix_format = mcam_def_pix_format;
>  	cam->mbus_code = mcam_def_mbus_code;
>
> -	/*
> -	 * Register sensor notifier.
> -	 */
> -	v4l2_async_notifier_init(&cam->notifier);
> -	ret = v4l2_async_notifier_add_subdev(&cam->notifier, &cam->asd);
> -	if (ret) {
> -		cam_warn(cam, "failed to add subdev to a notifier");
> -		goto out;
> -	}
> -
>  	cam->notifier.ops = &mccic_notify_ops;
>  	ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier);
>  	if (ret < 0) {
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index b55545822fd2..f324d808d737 100644
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -151,7 +151,6 @@ struct mcam_camera {
>  	 */
>  	struct video_device vdev;
>  	struct v4l2_async_notifier notifier;
> -	struct v4l2_async_subdev asd;
>  	struct v4l2_subdev *sensor;
>
>  	/* Videobuf2 stuff */
> diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
> index 032fdddbbecc..40d9fc4a731a 100644
> --- a/drivers/media/platform/marvell-ccic/mmp-driver.c
> +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
> @@ -180,6 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	struct resource *res;
>  	struct fwnode_handle *ep;
>  	struct mmp_camera_platform_data *pdata;
> +	struct v4l2_async_subdev *asd;
>  	int ret;
>
>  	cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
> @@ -238,10 +239,15 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	if (!ep)
>  		return -ENODEV;
>
> -	mcam->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
> -	mcam->asd.match.fwnode = fwnode_graph_get_remote_port_parent(ep);
> +	v4l2_async_notifier_init(&mcam->notifier);
>
> +	asd = v4l2_async_notifier_add_fwnode_remote_subdev(&mcam->notifier,
> +							   ep, sizeof(*asd));
>  	fwnode_handle_put(ep);
> +	if (IS_ERR(asd)) {
> +		ret = PTR_ERR(asd);
> +		goto out;
> +	}
>
>  	/*
>  	 * Register the device with the core.
> @@ -278,7 +284,6 @@ static int mmpcam_probe(struct platform_device *pdev)
>  	pm_runtime_enable(&pdev->dev);
>  	return 0;
>  out:
> -	fwnode_handle_put(mcam->asd.match.fwnode);
>  	mccic_shutdown(mcam);
>
>  	return ret;
> --
> 2.29.2
>

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

* Re: [PATCH 06/13] media: atmel: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers
  2021-01-16 17:21   ` Jacopo Mondi
@ 2021-01-17 17:57     ` Ezequiel Garcia
  0 siblings, 0 replies; 41+ messages in thread
From: Ezequiel Garcia @ 2021-01-17 17:57 UTC (permalink / raw)
  To: Jacopo Mondi
  Cc: linux-media, Hans Verkuil, kernel, Laurent Pinchart, Sakari Ailus

On Sat, 2021-01-16 at 18:21 +0100, Jacopo Mondi wrote:
> Hi Ezequiel,
> 
> On Tue, Jan 12, 2021 at 10:23:32AM -0300, Ezequiel Garcia wrote:
> > The use of v4l2_async_notifier_add_subdev is discouraged.
> > Drivers are instead encouraged to use a helper such as
> > v4l2_async_notifier_add_fwnode_remote_subdev.
> > 
> > This fixes a misuse of the API, as v4l2_async_notifier_add_subdev
> > should get a kmalloc'ed struct v4l2_async_subdev,
> > removing some boilerplate code while at it.
> > 
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > ---
> >  drivers/media/platform/atmel/atmel-isc.h      |  1 +
> >  drivers/media/platform/atmel/atmel-isi.c      | 46 ++++++-------------
> >  .../media/platform/atmel/atmel-sama5d2-isc.c  | 44 ++++++------------
> >  3 files changed, 29 insertions(+), 62 deletions(-)
> > 
> >         }
> > 
> 
> [snip]
> 
> >         list_for_each_entry(subdev_entity, &isc->subdev_entities, list) {
> > +               struct v4l2_async_subdev *asd;
> > +
> >                 v4l2_async_notifier_init(&subdev_entity->notifier);
> > 
> > -               ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier,
> > -                                                    subdev_entity->asd);
> > -               if (ret) {
> > -                       fwnode_handle_put(subdev_entity->asd->match.fwnode);
> > -                       kfree(subdev_entity->asd);
> > +               asd = v4l2_async_notifier_add_fwnode_remote_subdev(
> > +                                       &subdev_entity->notifier,
> > +                                       of_fwnode_handle(subdev_entity->epn),
> > +                                       sizeof(*asd));
> > +
> > +               of_node_put(subdev_entity->epn);
> > +               subdev_entity->epn = NULL;
> > +
> > +               if (IS_ERR(asd)) {
> > +                       ret = PTR_ERR(asd);
> >                         goto cleanup_subdev;
> 
> The isc_subdev_cleanup() this label jumps to does not put the other
> subdev_entity->epn
> 
> The issue was there already if I'm not mistaken. If I'm not, I think
> it's worth recording it with a FIXME: comment while you're here
> 

Although, as you've noticed I tend to break this rule myself,
I'd rather avoid adding more changes to the patch.

The OF/fwnode handling in this atmel driver might benefit
from some improvements (and the same can be said of some
other drivers) but I'd say let's stick to just improving
the v4l2-async API.

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

Thanks a lot for the reviews!
Ezequiel


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

end of thread, other threads:[~2021-01-17 17:59 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-12 13:23 [PATCH 00/13] V4L2 Async notifier API cleanup Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 01/13] media: v4l2-async: Clean v4l2_async_notifier_add_fwnode_remote_subdev semantics Ezequiel Garcia
2021-01-14  1:59   ` Laurent Pinchart
2021-01-14 13:47     ` Sakari Ailus
2021-01-14 14:46       ` Ezequiel Garcia
2021-01-14 16:11         ` Sakari Ailus
2021-01-14 16:22           ` Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 02/13] media: stm32-dcmi: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
2021-01-16 15:35   ` Jacopo Mondi
2021-01-16 16:27     ` Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 03/13] media: renesas-ceu: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
2021-01-14  2:06   ` Laurent Pinchart
2021-01-14 13:36     ` Ezequiel Garcia
2021-01-15 12:12     ` Ezequiel Garcia
2021-01-16 15:56   ` Jacopo Mondi
2021-01-12 13:23 ` [PATCH 04/13] media: exynos4-is: Use v4l2_async_notifier_add_fwnode_remote_subdev Ezequiel Garcia
2021-01-16 16:07   ` Jacopo Mondi
2021-01-16 16:55     ` Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 05/13] media: st-mipid02: Use v4l2_async_notifier_add_fwnode_remote_subdev helpers Ezequiel Garcia
2021-01-16 16:23   ` Jacopo Mondi
2021-01-12 13:23 ` [PATCH 06/13] media: atmel: " Ezequiel Garcia
2021-01-16 17:21   ` Jacopo Mondi
2021-01-17 17:57     ` Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 07/13] media: cdns-csi2rx: " Ezequiel Garcia
2021-01-16 17:23   ` Jacopo Mondi
2021-01-12 13:23 ` [PATCH 08/13] media: marvell-ccic: Use v4l2_async_notifier_add_{i2c,fwnode_remote}_subdev helpers Ezequiel Garcia
2021-01-16 17:36   ` Jacopo Mondi
2021-01-12 13:23 ` [PATCH 09/13] media: pxa-camera: " Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 10/13] media: davinci: vpif_display: Remove unused v4l2-async code Ezequiel Garcia
2021-01-12 13:23 ` [PATCH 11/13] media: v4l2-async: Drop v4l2_fwnode_reference_parse_sensor_common mention Ezequiel Garcia
2021-01-14  2:14   ` Laurent Pinchart
2021-01-14 13:36     ` Ezequiel Garcia
2021-01-15  6:56       ` Laurent Pinchart
2021-01-12 13:23 ` [PATCH 12/13] media: Clarify v4l2-async subdevice addition API Ezequiel Garcia
2021-01-14  2:21   ` Laurent Pinchart
2021-01-14 13:39     ` Ezequiel Garcia
2021-01-15  8:47       ` Sakari Ailus
2021-01-12 13:23 ` [PATCH 13/13] media: v4l2-async: Discourage use of v4l2_async_notifier_add_subdev Ezequiel Garcia
2021-01-14  2:27   ` Laurent Pinchart
2021-01-14 13:47     ` Ezequiel Garcia
2021-01-15  6:57       ` Laurent Pinchart

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.